Overview
Full data table with header, body, and optional footer for structured tabular content.
Usage
Table is a compound component. Import the parent and compose its leaves via
the namespace API: Table.Header, Table.HeaderCell, Table.Body,
Table.Row, and Table.Cell.
Pass scrollable for dense or unknown-width tables. The Table root stays a
native <table>; Cinder generates a focusable .cinder-table-scroll wrapper
that owns horizontal overflow when the available component width is too narrow.
Use scrollContainerProps to label, style, or override attributes on that
generated wrapper. When scrollable and stickyHeader are combined, the
generated wrapper is the sticky header's scroll container; set a bounded block
size on scrollContainerProps when the table should scroll vertically inside
that wrapper.
The leaves remain importable individually for à-la-carte builds — see
@lostgradient/cinder/table-body, @lostgradient/cinder/table-cell, @lostgradient/cinder/table-header,
@lostgradient/cinder/table-header-cell, and @lostgradient/cinder/table-row.
When to use
- Comparing rows of structured records across consistent columns.
- Coordinating column sort state across header cells via the sort prop.
- Rendering a responsive card grid — use grid-list instead.
- Listing key-value attributes of one entity — use description-list instead.
Examples
Scrollable table
Hand-composed cells inside the public horizontal scroll wrapper for dense tables.
Empty table
A table with no body rows still renders the header and caption.
Selectable rows
Table with a select-all checkbox in the header and per-row selection. One row is explicitly disabled from selection.
Sticky sortable header
Sortable columns with stickyHeader={true}. Scroll the table body to verify the focus ring on the sort button is not clipped by the sticky thead.
Props
| Name | Type | Default | Required | Bindable | Description |
|---|---|---|---|---|---|
sort | TableSort | undefined | bind | Bound sort state. When the user activates a sortable header, this prop
is updated to reflect the new column / direction.
Pass undefined initially when no column is sorted; the component will
never write back undefined itself (sort always toggles to a column). | ||
caption | text | Visual caption rendered as a <caption> element. | |||
stickyHeader | boolean | false | When true, the header sticks to the top of the scrolling container. | ||
density | 'comfortable' | 'condensed' | 'spacious' | 'comfortable' | Vertical padding density for header and body cells.
Defaults to 'comfortable'. | ||
selectable | boolean | false | Enables the leading selection column on the entire table. When true:
- The single TableRow inside TableHeader renders a leading <th>
with a select-all checkbox sourced from the header's props.
- Every TableRow inside TableBody renders a leading selection cell.
Selection is strictly controlled — the consumer owns all selection state. | ||
scrollable | boolean | false | When true, wraps the table in a .cinder-table-scroll container that
enables horizontal overflow scrolling for dense or unknown-width tables.
Use this instead of manually wrapping Table in .cinder-table-scroll.
When combined with stickyHeader, the generated wrapper is the sticky
header's scroll container. Set a bounded block size on scrollContainerProps
when the table should scroll vertically inside that wrapper. | ||
scrollContainerProps | Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'class' > & { /** Additional class names merged with `.cinder-table-scroll`. */ class?: string; } | Attributes forwarded to the generated .cinder-table-scroll wrapper when
scrollable is true. The wrapper is focusable by default so keyboard users
can scroll read-only wide tables. When the table has a caption, or when
aria-label or aria-labelledby is provided here, the wrapper becomes a
named region; pass role or tabindex here to override those defaults. | |||
children | snippet | req | TableHeader, TableBody, etc. |