@htmlbricks/hb-table
v0.76.5
Published
Bulma-styled data table driven by JSON `headers` and `rows` (`_id` required): column sort, header search (text, enum, date range, IP substring filter), formatted values (nested keys, datetime via dayjs, **`ip`** as IPv4 `A.B.C.D` or CIDR `A.B.C.D/p` with
Readme
hb-table — integrator guide
Category: data · Tags: data, table · Package: @htmlbricks/hb-table
Summary
hb-table is a Bulma-styled data table web component. You drive it with JSON headers and rows. Each row must include _id. The table can sort columns, filter from the header row (text, enum, date range), format values (nested keys with dot notation, datetimes via dayjs), copy cell text, highlight rows, and handle row / cell clicks. Optional global actions and per-row _actions open hb-dialog (confirm) or hb-dialogform (schema-driven edit). Multi-select is optional via selectactions. The footer embeds hb-paginate for page size, sort controls, and server-style workflows (externalfilter, total). is_loading shows Bulma skeleton placeholders while keeping pagination props in sync. Internationalization uses i18nlang.
Inner components
The implementation registers and embeds hb-paginate, hb-dialog, hb-dialogform, and hb-tooltip. Bootstrap Icons are loaded for action icons. Theme behaviour follows Bulma --bulma-* variables; dark mode follows prefers-color-scheme unless you override with data-theme or .theme-light / .theme-dark on html, body, or the hb-table host (inner layout-only data-theme is ignored so nested wrappers do not force light mode). Action icons inherit the button foreground colour.
Custom element
| Tag | Package |
| ---------- | -------------------- |
| hb-table | @htmlbricks/hb-table |
HTML integration rules
- Attributes use snake_case and are strings in plain HTML.
- String flags: HTML attributes are always strings — e.g.
externalfilterisyes/no(ortrue/false); same idea fordisablepagination,add_item,is_loading,disable_paginate_sort,sort_strict_direction(the component coerces these at runtime). - Arrays / objects (
rows,headers,actions,selectactions): pass a JSON string on the attribute, or assign parsed objects from JavaScript. - Numbers (
size,page,pages,total, …): pass numeric values as strings in HTML (e.g.page="0"). - Pagination index:
pageandpageChangedetail.pageare zero-based (first page is0). Align with APIs that use 1-based pages in your host code.
Attributes and props
| Attribute / prop | Required | Description |
| ---------------- | -------- | ----------- |
| headers | yes | JSON array of column definitions (ITableHeader). See Column headers. |
| rows | yes | JSON array of row objects. Each row must have _id. Optional _actions, _evidenced. |
| id | no | Host id; echoed on addItem as detail.id. |
| style | no | Host inline style string (typed on component; use as needed). |
| size | no | Page size (default 12 in implementation). |
| page | no | Current page index, zero-based. |
| pages | no | Total number of pages (non-negative). |
| total | no | Total row count for server-side pagination (passed through to pagination when set). |
| actions | no | JSON IActionButton[] rendered as one shared actions column for every row. |
| selectactions | no | JSON array of bulk toolbar actions when multi-select is enabled ({ name, type, iconOrText }). |
| selectrow | no | When enabled (yes / true), row clicks dispatch clickonrow (selection / navigation UX). |
| enableselect | no | Toggles multi-select mode (gear); when on, row checkboxes appear if selectactions has entries. |
| selected | no | Row _id to highlight (::part(selected-row)). |
| externalfilter | no | String yes / true → server mode: header filters still emit events but client-side filtering / sorting of rows is skipped. Omit the attribute or use no / false for local filter + sort on rows. |
| disablepagination | no | Hides hb-paginate. |
| add_item | no | Shows the Add control in the footer toolbar when not in multi-select gear mode. |
| i18nlang | no | Language code (metadata lists en, it). |
| page_size_type | no | number (free input) or select (dropdown) for page size UI. |
| page_size_options | no | Comma-separated sizes for select mode, e.g. 10,25,50,100. |
| sort_default | no | Header key that should match the initial sort column when using pagination sort UI. |
| sort_default_label | no | Label for the “default” sort option in the pagination bar (e.g. “Relevance”). |
| disable_paginate_sort | no | Hides sort field / direction controls on hb-paginate. |
| sort_strict_direction | no | When set, sort direction toggles asc / desc only (no “default” cleared state from column cycling). |
| sort_direction | no | Current direction: asc, desc, or default. |
| is_loading | no | When yes / true, tbody shows Bulma skeleton rows (count from size, max 100); footer shows a skeleton-block over hidden hb-paginate so page / pages stay wired. |
| fixed_columns | no | yes: table-layout: fixed, equal column widths, ellipsis overflow. no (default): auto table layout. |
Column headers (ITableHeader)
Each entry describes one column.
| Field | Type / values | Role |
| ----- | -------------- | ---- |
| label | string | Header label. |
| key | string | Row field key; supports dot paths (e.g. testnested.nested). |
| type | string (default), datetime, enum, number, ip, actions | Affects formatting, search UI, and sort participation. ip: values A.B.C.D or A.B.C.D/p (IPv4, optional CIDR p 0–32); client-side sort orders by numeric address then prefix length. |
| format | string | For datetime, dayjs format string (e.g. DD MMMM YYYY). |
| search | boolean | Enables header search (text includes, enum select, or date range for searchable datetime). |
| click | boolean | Makes cells dispatch cellclick when clicked (non-actions columns). |
| select | string[] | For enum, allowed values. |
| nosort | boolean | Excludes column from header sort cycling. |
| sortBy | asc | desc | none | Initial sort indicator on column (internal default none). |
| truncateAt | number | Truncate displayed string length (with ... when trimmed). |
| copyTxt | boolean | Shows copy control; successful copy dispatches clipboardCopyText. |
| tooltip | object | Optional tooltip config for the header (see hb-tooltip / TTooltip). |
| centerCell | boolean | When true, body cells (and skeleton placeholders) for this column use centered horizontal text/content. |
| centerHeader | boolean | When true, header content for this column is centered: title row centers the label (tooltip + text) in the space beside the sort control; sort stays left. Filter rows (search) also center controls in the cell. |
type: "actions": Renders _actions for that row (per-row buttons). You usually set nosort: true. A dummy key is still required for the column definition.
Rows (IRow)
_id: string, required, stable row identifier (events use it asitemId/rowId)._actions: optionalIActionButton[]for theactions-type column._evidenced: optional boolean; marks the row for emphasised styling.- Other keys are your data fields, aligned with header
keypaths.
Filters (IFilter)
Emitted on changeFilter and used internally when not in externalfilter mode:
key,type(datetime|string|enum|number|ip), optionalvalue, and for datetime rangestart/end(Datein TS; serialized appropriately in JSON props).
Actions (IActionButton)
Used for actions (global column) and _actions (per row).
| Field | Description |
| ----- | ----------- |
| name | Stable id; appears as action in events. |
| type | text — iconOrText is the label; icon — Bootstrap Icon glyph (name after bi-, e.g. pencil, not bi-pencil). |
| iconOrText | Label or icon name. |
| btnClass | Optional Bulma colour token (primary, danger, link, …). Omitted → is-link. Case-insensitive; optional btn- prefix stripped. Strings starting with button are passed through (legacy). |
| btnFill | If true / yes, filled button (no outline). If omitted, false, or no, the button is not filled and is-outlined only when the resolved Bulma theme on this host is dark (reads --bulma-scheme-brightness / --bulma-hb-def-scheme-brightness / --bulma-scheme-main-l from getComputedStyle(host), then falls back to data-theme / .theme-* / prefers-color-scheme). |
| disabled | Disables the control. |
| confirm | Opens hb-dialog with title, content, confirmLabel, optional denyLabel, text. |
| edit | Opens hb-dialogform with title, schema (form schema), confirmLabel, optional denyLabel, description, text. |
| tooltip | Optional tooltip on icon buttons. |
Click behaviour
- Global
actionscolumn:handleClickOnAction— if the button hasconfirmoredit, the modal opens; otherwisetableactionfires with{ itemId, action }. - Per-row
_actions:handleClickOnCustomActionalways emitstableCustomActionClickwith{ itemId, action }. Ifconfirm/editis set, the corresponding dialog opens; there is notableactionfor plain per-row clicks (usetableCustomActionClickonly).
Custom events
Listen on the host element. Names are case-sensitive as in the table.
| Event | detail (TypeScript Events) | Notes |
| ----- | ------------------------------ | ----- |
| pageChange | { page: number; pages: number } (see typings) | Zero-based page. The component dispatches detail with at least { page }; keep total pages aligned via the pages attribute (and your server state) when integrating. |
| changePageSize | { page_size: number } | Page size changed; table resets to page 0 internally when not external. |
| removeFilter | { key: string } | Filter cleared for key. |
| changeFilter | { filter: IFilter } | Filter added/updated. |
| tableCustomActionClick | { itemId: string; action: string } | Per-row _actions (distinction from global column). |
| tableaction | { itemId: string; action: string } | Global actions column without confirm/edit. |
| cellclick | { rowId: string; cellId: string } | Fired for clickable cells; cellId is the column header key (TypeScript Events uses cellId). |
| actiononselected | { key: string; selectedItems: string[] } | Bulk toolbar action (key = button name). |
| clickonrow | { itemId: string } | Row click when selectrow is enabled. |
| changeSort | { sortedBy?: string; sortedDirection: "asc" \| "desc" \| "default" } | Column header sort or pagination sort control. |
| showConfirmModal | { action: string; detail: { id: string; show: boolean } } | Confirm dialog visibility. |
| showConfirmModalForm | { action: string; detail: { id: string; show: boolean } } | Form dialog visibility. |
| confirmActionModal | { action: string; id: string; confirm: boolean } | Confirm dialog result. |
| confirmActionModalForm | { action: string; id: string; confirm: boolean } | Form dialog result; detail merges the dialog payload with the table’s action context (see typings — extra keys may appear). |
| clipboardCopyText | { text: string } | After copy-to-clipboard. |
| addItem | { id: string } | Add control clicked; id is the table’s id attribute or empty string. |
Slots
| Slot | Purpose |
| ---- | ------- |
| add-button-content | Replaces the default plus icon for Add when add_item is on. |
| buttons-container | Extra toolbar controls before hb-paginate inside part="table-actions". |
CSS parts
| Part | Exposes |
| ---- | ------- |
| table | Root <table> (headers, body, embedded dialogs). |
| table-actions | Footer toolbar: settings, add, bulk actions, buttons-container, hb-paginate. |
| selected-row | <tr> when selected matches the row _id. |
| common-row | Standard data <tr>. |
Toolbar order (conceptually): settings (gear) → Add (when allowed) → bulk actions → buttons-container → hb-paginate. Spacing can be tuned with --hb-table-toolbar-settings-margin-inline-start and --hb-paginate-list-gap on the host where relevant.
CSS custom properties (host)
Dimensional spacing follows Bulma rhythm variables (--bulma-block-spacing, --bulma-size-normal, --bulma-control-height, --bulma-pagination-item-margin, …) with unitless *-mul knobs on the host. Override a --hb-table-*-mul to tune density, or set the resolved --hb-table-* / --bulma-table-cell-padding for full control.
| Variable | Role |
| -------- | ---- |
| --hb-table-*-mul | Unitless multipliers (see extra/docs.ts styleSetup.vars for defaults). |
| --hb-table-footer-margin-inline-end | calc(var(--bulma-block-spacing) * mul) — footer pagination inline-end margin. |
| --hb-table-sk-pagination-height | calc(var(--bulma-control-height) * mul) — loading skeleton height. |
| --hb-table-sk-pagination-min-width | min(calc(var(--bulma-size-normal) * mul), 100%) — skeleton min width while loading. |
| --hb-table-sk-pagination-offset-inline-end | calc(var(--bulma-block-spacing) * mul) — extra inline-end offset when loading. |
| --hb-table-toolbar-settings-margin-inline-start | calc(var(--bulma-block-spacing) * mul) — space before the first toolbar control group. |
| --hb-table-actions-gap | calc(var(--bulma-block-spacing) * mul) — gap in the actions flex row. |
| --bulma-table-cell-padding | calc(var(--bulma-size-normal) * block-mul) calc(var(--bulma-size-normal) * inline-mul) — cell padding (Bulma token). |
| --hb-table-cell-line-height | Unitless line-height on td / th (default 1.1); lower for denser multi-line cells. |
Additional theming uses Bulma --bulma-* variables on the host / document as for other hb-* components.
Behaviour notes for integrators
- Client vs server data: Without
externalfilter, filters and column sort run against the in-memoryrowsyou pass. Withexternalfilter, usechangeFilter,changeSort,pageChange, andchangePageSizeto query the server and then assign newrows/total/pages/page. - Empty rows while loading: With client-side pagination, clearing
rowsduring refresh can leavepagesderived from old state until new data arrives—keeppage,pages, andtotalconsistent with your API. - Multi-select: Checkboxes appear only when
selectactionsis a non-empty array andenableselectis on. The Add button is hidden while the gear multi-select mode is active. - Examples: See
extra/docs.ts(examplesarray) for Storybook-style datasets: page size modes, sort defaults, strict direction, loading skeleton, fixed columns, tooltips, truncate/copy, and confirm/form actions.
Minimal examples
Basic table
<hb-table
headers='[{"label":"Title","key":"title"},{"label":"When","key":"time","type":"datetime","format":"DD MMM YYYY"}]'
rows='[{"_id":"1","title":"Row A","time":"2024-01-01T12:00:00.000Z"}]'
page="0"
pages="1"
></hb-table>Loading state
<hb-table
is_loading="yes"
size="10"
headers='[{"label":"Title","key":"title"}]'
rows="[]"
total="0"
page="0"
pages="0"
></hb-table>Add row entry point
<hb-table
id="orders"
add_item="yes"
headers='[{"label":"Title","key":"title"}]'
rows='[{"_id":"1","title":"A"}]'
></hb-table>
<script>
document.querySelector("hb-table").addEventListener("addItem", (e) => {
console.log("Create item for table id:", e.detail.id);
});
</script>Types in this repo
Authoritative TypeScript shapes for props and events live in types/webcomponent.type.d.ts (Component, Events, ITableHeader, IRow, IActionButton, IFilter). Generated consumer typings are produced on npm run build:wc (types/html-elements.d.ts, types/svelte-elements.d.ts).
