Data table
Sortable, selectable, paged table composed from the table, checkbox, button, and pagination items.
Block · data
Install
Section titled “Install”npx shadcn@latest add https://ndigo.dev/r/data-table.jsonTo use the shorter @ndigo/data-table form, configure the namespace in components.json.
| Source | Target | Type |
|---|---|---|
registry/blocks/data-table/data-table.html |
@components/data-table/data-table.html |
registry:block |
registry/blocks/data-table/data-table.css |
@components/data-table/data-table.css |
registry:file |
registry/blocks/data-table/data-table.ts |
@components/data-table/data-table.ts |
registry:file |
Live example
Section titled “Live example”See this component rendered live on the live examples page.
Dependencies
Section titled “Dependencies”Registry: Ndigo theme, Table, Checkbox and radio, Button, Pagination.
Documentation
Section titled “Documentation”The block is authored rows plus a small glue module. Sorting, page-local selection, and pagination run on the client; the markup and styles compose the items already shipped, so there is no table runtime dependency.
import { initDataTable } from './components/data-table/data-table';
const table = initDataTable(document);initDataTable(document) finds [data-data-table] and returns a handle, or
null when the markup is absent.
<div class="nd-data-table" data-data-table data-page-size="3"> <div class="nd-table-wrap"> <table class="nd-table nd-table--striped"> <caption class="nd-table__caption"> Invoices </caption> <thead> <tr> <th scope="col" class="nd-data-table__select"> <input class="nd-checkbox" type="checkbox" data-select-all aria-label="Select all rows on this page" /> </th> <th scope="col" data-sort-key="invoice" data-sort-type="text"> <button class="nd-table__sort" type="button"> Invoice <span class="nd-table__sort-icon" aria-hidden="true">↕</span> </button> </th> <th scope="col">Status</th> </tr> </thead> <tbody data-rows> <tr data-row-id="INV-001"> <td class="nd-data-table__select"> <input class="nd-checkbox" type="checkbox" data-select-row aria-label="Select INV-001" /> </td> <td data-sort-value="INV-001">INV-001</td> <td>Paid</td> </tr> </tbody> </table> </div> <div class="nd-data-table__footer"> <p class="nd-data-table__status" data-status role="status" aria-live="polite"></p> <nav class="nd-pagination" data-pagination aria-label="Invoice pages"></nav> </div></div>Markup contract
Section titled “Markup contract”| Hook | Purpose |
|---|---|
[data-data-table] |
Block root; data-page-size sets rows per page (default 10) |
[data-rows] |
<tbody> that owns the rows |
[data-row-id] |
Stable row id used by selection |
[data-sort-key] + [data-sort-type] |
Sortable <th>; the button inside triggers sorting. Types: text (default), number, date |
[data-sort-value] |
Cell sort value when the display text is formatted (amounts, dates) |
[data-select-all] |
Header checkbox; selects the current page |
[data-select-row] |
Row checkbox |
[data-status] |
Live range text |
[data-pagination] |
Empty <nav> that the glue fills |
Methods
Section titled “Methods”sort(key, direction?)— sort by adata-sort-key; defaults toascending.setPage(page)— move to a page.selectedIds()— ids of every selected row across pages.refresh()— re-read rows (call after replacing the tbody contents).destroy()— remove the glue’s listeners.
Events
Section titled “Events”nd-sort-change—{ key, direction }.nd-selection-change—{ ids: string[] }for all selected rows.nd-page-change—{ page, pageCount }.
Behaviour
Section titled “Behaviour”Sorting reads the cell at the header’s column index from data-sort-value or
the trimmed text. Numbers use number, dates Date.parse, and text
localeCompare with numeric collation. Sorting reorders all rows, keeps a stable
tie-break, and returns to page 1.
The header checkbox selects the rows on the current page; selections survive
sorting and paging, and the footer count reflects every selected row. Rows outside
the current page stay in the DOM with hidden, so their state is preserved.
Accessibility
Section titled “Accessibility”Sortable headers carry aria-sort; the icon is aria-hidden and the button
keeps the column label. The status line is a polite live region. Every row
checkbox has a per-row aria-label, and the header checkbox describes its
page scope. Generated page controls expose aria-current="page" and disabled
edges, matching the pagination item.
Styling
Section titled “Styling”Import nd-table.css, nd-checkbox.css, nd-button.css,
nd-pagination.css, and data-table.css. The block only adds the footer
layout, the select-column width, and the hidden-row rule; the table and
pagination keep their own tokens.