Skip to content

Table

A semantic table in a scroll container, with sortable headers, loading, empty and error rows.

2.9 kB gzipSource Registry JSON

Basic

NameRegionStatus
robineu-westLive
wrenus-eastLive
fincheu-westBuilding
heronus-eastPaused

Installation

npx shadcn@latest add https://sproutboat.com/ikada/r/table.json

The CLI writes components/ikada/table.tsx and merges the ikada theme into your CSS. It also installs the components it is built from: Skeleton. Or take it from the package: import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell, TableEmpty, TableError, TableLoading } from "@sproutboat/ikada";

Usage

import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell, TableEmpty, TableError, TableLoading } from "@/components/ikada/table";

<Table label="Sprouts">
  <TableHeader>
    <TableRow>
      <TableHead>Name</TableHead>
      <TableHead>Region</TableHead>
      <TableHead>Status</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell>robin</TableCell>
      <TableCell>eu-west</TableCell>
      <TableCell>
        <StatusDot tone="success" live label="Live" />
      </TableCell>
    </TableRow>
    <TableRow>
      <TableCell>wren</TableCell>
      <TableCell>us-east</TableCell>
      <TableCell>
        <StatusDot tone="success" live label="Live" />
      </TableCell>
    </TableRow>
    <TableRow>
      <TableCell>finch</TableCell>
      <TableCell>eu-west</TableCell>
      <TableCell>
        <StatusDot tone="info" pulse label="Building" />
      </TableCell>
    </TableRow>
    <TableRow>
      <TableCell>heron</TableCell>
      <TableCell>us-east</TableCell>
      <TableCell>
        <StatusDot tone="neutral" label="Paused" />
      </TableCell>
    </TableRow>
  </TableBody>
</Table>

Examples

Basic

Wide tables scroll inside their container, never the page. 48px rows.
NameRegionStatus
robineu-westLive
wrenus-eastLive
fincheu-westBuilding
heronus-eastPaused

Numbers and long names

Number columns take `numeric`: right-aligned tabular figures, so digits line up. Long names scroll inside the table.
SproutRequestsp50 (ms)
robin1,284,03111.4
wren860108.9
very-long-sprout-name-that-keeps-going-and-going-without-a-break12,000,000,0000.2

Sortable

A sortable header holds a button and sets aria-sort. nextSort cycles none, ascending, descending. Updated hides below the container's md width.
RegionUpdated
robineu-west3 min ago
wrenus-east2 h ago
fincheu-westjust now
heronus-east5 days ago

Selected row

Highlights the row and sets aria-selected. Pair it with a checkbox cell: that is the control.
NameRegion
robineu-west
wrenus-east

Sticky header

The header stays put while the body scrolls. Pair stickyHeader with a maxHeight.
NameRegion
robineu-west
wrenus-east
fincheu-west
heronus-east
robineu-west
wrenus-east
fincheu-west
heronus-east

Loading

Skeleton rows keep the layout of the loaded table. Mark the table aria-busy.
NameRegionStatus

Empty

NameRegion
No sprouts yet. Plant your first one.

Error

NameRegion

Props

HideBelowProps
PropTypeDescription
hideBelowTableBreakpointDrops this column (set it on its `TableHead` and every `TableCell`) when the table's container is narrower than the breakpoint. Use it for low-priority columns only; never put critical status (failure) in a column that can hide; the container still scrolls sideways as the last resort.
TableProps
PropTypeDescription
labelrequiredstringNames the scrolling region for screen readers. Required: say what the table lists.
stickyHeaderbooleanHeader stays put while the body scrolls. Pair with `maxHeight`. Default `false`.
maxHeightstringCSS max-height of the scroll area, e.g. "24rem".
containerClassNamestringApplied to the scroll container.

Also takes every prop of ComponentProps<"table">.

TableRowProps
PropTypeDescription
selectedbooleanHighlights the row and sets aria-selected. Pair with a checkbox cell: that is the control. Default `false`.

Also takes every prop of ComponentProps<"tr">.

NumericProps
PropTypeDescription
numericbooleanRight-aligns the column (start edge in RTL reads end) and sets tabular figures. Set it on the `TableHead` and every `TableCell` of a number column.
TableHeadProps
PropTypeDescription
sortablebooleanMakes the header a button. `undefined` means sortable but not sorted. Default `false`.
sortSortDirectionCurrent sort of this column; shows the arrow and sets aria-sort.
onSort(() => void)Makes the header a sort button; called when it is pressed.
hideBelowTableBreakpointDrops this column (set it on its `TableHead` and every `TableCell`) when the table's container is narrower than the breakpoint. Use it for low-priority columns only; never put critical status (failure) in a column that can hide; the container still scrolls sideways as the last resort.
numericbooleanRight-aligns the column (start edge in RTL reads end) and sets tabular figures. Set it on the `TableHead` and every `TableCell` of a number column.

Also takes every prop of Omit<ComponentProps<"th">, "onClick" | "aria-sort">, HideBelowProps, NumericProps.

TableCellProps
PropTypeDescription
hideBelowTableBreakpointDrops this column (set it on its `TableHead` and every `TableCell`) when the table's container is narrower than the breakpoint. Use it for low-priority columns only; never put critical status (failure) in a column that can hide; the container still scrolls sideways as the last resort.
numericbooleanRight-aligns the column (start edge in RTL reads end) and sets tabular figures. Set it on the `TableHead` and every `TableCell` of a number column.
TableEmptyProps
PropTypeDescription
colSpanrequirednumber—
TableErrorProps
PropTypeDescription
colSpanrequirednumber—
titlestringDefault `Could not load this list`.
actionReactNodeA retry Button.
TableLoadingProps
PropTypeDescription
columnsrequirednumber—
rowsnumberDefault `4`.

Source: src/components/table.tsx