GitHub

/ table

Table

@kumiki/components/table

Semantic <table> with sortable headers, row selection (single/multiple/tri-state select-all), and tree-row disclosure. Per ADR 0015: not a Data Grid.

This component, layer by layer

Styled, copy-paste presets (preview). Run pnpm kumiki add to drop the source into your project, then edit freely.

Live preview

Live preview…

Install
pnpm add @kumiki/atelier
Sortable + selectable
<script lang="ts">
  import { Tailwind as Table } from '@kumiki/atelier/table';
  import type { SortState } from '@kumiki/components/table';

  let sort = $state<SortState | null>(null);
  let selection = $state(new Set<string>());

  const rows = [
    { id: '1', name: 'Akari', role: 'Eng' },
    { id: '2', name: 'Ben',   role: 'PM' },
  ];
</script>

<Table.Root
  {sort}
  onSortChange={(s) => (sort = s)}
  {selection}
  onSelectionChange={(s) => (selection = s)}
  selectionMode="multiple"
>
  <Table.Caption>Members</Table.Caption>
  <Table.Header>
    <Table.HeaderRow>
      <Table.SelectAllCell />
      <Table.HeaderCell column="name" sortable>Name</Table.HeaderCell>
      <Table.HeaderCell column="role">Role</Table.HeaderCell>
    </Table.HeaderRow>
  </Table.Header>
  <Table.Body>
    {#each rows as row (row.id)}
      <Table.Row rowId={row.id} selectable>
        <Table.SelectCell />
        <Table.Cell>{row.name}</Table.Cell>
        <Table.Cell>{row.role}</Table.Cell>
      </Table.Row>
    {/each}
  </Table.Body>
</Table.Root>

/ accessibility

Accessibility

axe-core — run on every PR (LTR + RTL × every documented state).

Keyboard

No component-specific keymap. Inherits standard browser focus / activation behaviour.

Test discipline

  • axe-core — run on every PR (LTR + RTL × every documented state).
  • APG keyboard tests — Playwright, hand-written per pattern.
  • VoiceOver / NVDA — Guidepup nightly schedule.
  • Type-level required names — title / aria-label / aria-labelledby.
Read the W3C ARIA APG pattern ↗