Table
A composable, accessible table built from primitives. Compose
nana-table with
header, body, footer, row, head, cell and caption elements. Built on the CSS
table model and surface tokens, so it lays out natively, scrolls on small
screens, and follows the light/dark theme. Data-grid features (pagination,
filtering, selection) compose around these primitives.
Anatomy
Name Email Status Amount John Doe john@example.com Active KSh 120.00 Jane Roe jane@example.com Pending KSh 80.00 Sam Poe sam@example.com Active KSh 240.00 Recent transactions
| 1 | <nana-table variant="striped" hoverable> |
| 2 | <nana-table-header> |
| 3 | <nana-table-row> |
| 4 | <nana-table-head>Name</nana-table-head> |
| 5 | <nana-table-head>Email</nana-table-head> |
| 6 | <nana-table-head>Status</nana-table-head> |
| 7 | <nana-table-head align="right">Amount</nana-table-head> |
| 8 | </nana-table-row> |
| 9 | </nana-table-header> |
| 10 | |
| 11 | <nana-table-body> |
| 12 | <nana-table-row> |
| 13 | <nana-table-cell>John Doe</nana-table-cell> |
| 14 | <nana-table-cell>john@example.com</nana-table-cell> |
| 15 | <nana-table-cell>Active</nana-table-cell> |
| 16 | <nana-table-cell align="right">KSh 120.00</nana-table-cell> |
| 17 | </nana-table-row> |
| 18 | </nana-table-body> |
| 19 | |
| 20 | <nana-table-caption>Recent transactions</nana-table-caption> |
| 21 | </nana-table> |
Variants
variant="default"
NameEmailStatusAmount John Doe john@example.com Active KSh 120.00 Jane Roe jane@example.com Pending KSh 80.00 Sam Poe sam@example.com Active KSh 240.00
variant="bordered"
NameEmailStatusAmount John Doe john@example.com Active KSh 120.00 Jane Roe jane@example.com Pending KSh 80.00 Sam Poe sam@example.com Active KSh 240.00
variant="striped"
NameEmailStatusAmount John Doe john@example.com Active KSh 120.00 Jane Roe jane@example.com Pending KSh 80.00 Sam Poe sam@example.com Active KSh 240.00
variant="minimal"
NameEmailStatusAmount John Doe john@example.com Active KSh 120.00 Jane Roe jane@example.com Pending KSh 80.00 Sam Poe sam@example.com Active KSh 240.00
| 1 | <nana-table variant="bordered">…</nana-table> |
Density
density="compact"
Name Email Amount John Doe john@example.com KSh 120.00 Jane Roe jane@example.com KSh 80.00
density="normal"
Name Email Amount John Doe john@example.com KSh 120.00 Jane Roe jane@example.com KSh 80.00
density="comfortable"
Name Email Amount John Doe john@example.com KSh 120.00 Jane Roe jane@example.com KSh 80.00
| 1 | <nana-table density="compact">…</nana-table> |
Sortable Headers
Mark a nana-table-head
as sortable. It renders the
indicator and emits nana-sort
on activation — the consumer owns the sort state and updates the
sort attribute.
Name Email Amount John Doe john@example.com KSh 120.00 Jane Roe jane@example.com KSh 80.00
| 1 | <nana-table-head sortable sort="asc">Name</nana-table-head> |
| 2 | |
| 3 | <!-- The header only renders state and emits an event; the consumer sorts: --> |
| 4 | <nana-table @nana-sort=${onSort}> … </nana-table> |
Customization
variant and
density set the look
and spacing. These variables tune the palette, and the parts let you reach internals.
Q2 revenue by region Region Owner Revenue North America Ada Lovelace $420,000 Europe Alan Turing $318,500 Asia Pacific Grace Hopper $265,200
| 1 | <nana-table class="report" variant="striped" hoverable> |
| 2 | <nana-table-caption>Q2 revenue by region</nana-table-caption> |
| 3 | <nana-table-header> |
| 4 | <nana-table-row> |
| 5 | <nana-table-head>Region</nana-table-head> |
| 6 | <nana-table-head>Owner</nana-table-head> |
| 7 | <nana-table-head align="right">Revenue</nana-table-head> |
| 8 | </nana-table-row> |
| 9 | </nana-table-header> |
| 10 | <nana-table-body> |
| 11 | <nana-table-row> |
| 12 | <nana-table-cell>North America</nana-table-cell> |
| 13 | <nana-table-cell>Ada Lovelace</nana-table-cell> |
| 14 | <nana-table-cell align="right">$420,000</nana-table-cell> |
| 15 | </nana-table-row> |
| 16 | <!-- …more rows… --> |
| 17 | </nana-table-body> |
| 18 | </nana-table> |
| 1 | /* variant + density handle the common looks; these tune the palette */ |
| 2 | nana-table.report { |
| 3 | --nana-table-border-color: #e2e8f0; |
| 4 | --nana-table-row-hover: #eef2ff; |
| 5 | --nana-table-stripe: #f8fafc; |
| 6 | --nana-table-header-bg: #0b1220; |
| 7 | --nana-table-header-color: #e5edff; |
| 8 | } |
| CSS Variable | Description |
--nana-table-border-color | Grid / divider colour |
--nana-table-row-hover | Row hover background |
--nana-table-stripe | Zebra-stripe background (striped variant) |
--nana-table-header-bg | Header background colour |
--nana-table-header-color | Header text colour |
| Part | Description |
container | The scroll container |
table | The native <table> element |
cell | A header or body cell |
caption | The table caption |
Import
A single import registers every table element.
| 1 | import "@nana-tec/ui-components/table"; |
Elements
| Element | Maps to | Description |
nana-table | <table> | Container, scroll region, and design vars (variant/density/hoverable/sticky-header) |
nana-table-header | <thead> | Header group |
nana-table-body | <tbody> | Body group |
nana-table-footer | <tfoot> | Footer group (totals/summary) |
nana-table-row | <tr> | Row (handles stripe and hover) |
nana-table-head | <th> | Header cell — optionally sortable |
nana-table-cell | <td> | Data cell — supports align |
nana-table-caption | <caption> | Accessible table description |
Props (nana-table)
| Attribute | Type | Default | Description |
variant | default | bordered | striped | minimal | default | Visual style |
density | compact | normal | comfortable | normal | Cell padding |
hoverable | boolean | false | Highlight rows on hover |
sticky-header | boolean | false | Keep the header visible while scrolling |
Props (nana-table-head / nana-table-cell)
| Attribute | Type | Description |
align | left | center | right | Cell text alignment (head & cell) |
sortable | boolean | Head only — shows indicator and emits nana-sort |
sort | none | asc | desc | Head only — current sort direction (controlled) |