Data table
A native table with controls: a selection column with a mixed select-all, sortable headers, row focus with the ring on the fill, and static resize handles.
stable · light DOM · 4.0.0. Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.
Live variants
default
| Atlas library | Avery Kim | Ready | 24 |
| Orion workspace | Jordan Lee | In progress | 12 |
| Field notes | Morgan Noor | Ready | 38 |
| Signal monitor | Riley Stone | Review | 6 |
| No rows match. | |||
| ⋯ Loading rows | |||
<j3w1-data-table id="example-data-table-default"><div class="table-scroller" tabindex="0" role="region" aria-label="Project records"><table class="data-table"><caption class="table-caption">Project records · synthetic fixture</caption><thead class="data-table-head"><tr><th class="data-table-header" scope="col"><button class="data-table-sort" type="button">Project<span class="data-table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="data-table-header" scope="col"><button class="data-table-sort" type="button">Owner<span class="data-table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="data-table-header" scope="col"><button class="data-table-sort" type="button">Status<span class="data-table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="data-table-header" scope="col"><button class="data-table-sort" type="button">Scope<span class="data-table-sort-glyph" aria-hidden="true">↕</span></button></th></tr></thead><tbody class="data-table-body"><tr class="data-table-row" id="example-data-table-default-record-0" data-status="Ready" aria-selected="false" tabindex="0"><td class="data-table-cell" id="example-data-table-default-record-name-0">Atlas library</td><td class="data-table-cell">Avery Kim</td><td class="data-table-cell">Ready</td><td class="data-table-cell">24</td></tr><tr class="data-table-row" id="example-data-table-default-record-1" data-status="In progress" aria-selected="false" tabindex="-1"><td class="data-table-cell" id="example-data-table-default-record-name-1">Orion workspace</td><td class="data-table-cell">Jordan Lee</td><td class="data-table-cell">In progress</td><td class="data-table-cell">12</td></tr><tr class="data-table-row" id="example-data-table-default-record-2" data-status="Ready" aria-selected="false" tabindex="-1"><td class="data-table-cell" id="example-data-table-default-record-name-2">Field notes</td><td class="data-table-cell">Morgan Noor</td><td class="data-table-cell">Ready</td><td class="data-table-cell">38</td></tr><tr class="data-table-row" id="example-data-table-default-record-3" data-status="Review" aria-selected="false" tabindex="-1"><td class="data-table-cell" id="example-data-table-default-record-name-3">Signal monitor</td><td class="data-table-cell">Riley Stone</td><td class="data-table-cell">Review</td><td class="data-table-cell">6</td></tr><tr class="data-table-empty" hidden=""><td class="data-table-empty-cell" colspan="4">No rows match.</td></tr><tr class="data-table-loading" hidden=""><td colspan="4">⋯ Loading rows</td></tr></tbody></table></div></j3w1-data-table>selectable
| Atlas library | Avery Kim | Ready | 24 | |
| Orion workspace | Jordan Lee | In progress | 12 | |
| Field notes | Morgan Noor | Ready | 38 | |
| Signal monitor | Riley Stone | Review | 6 | |
| No rows match. | ||||
| ⋯ Loading rows | ||||
<j3w1-data-table id="example-data-table-selectable"><div class="table-scroller" tabindex="0" role="region" aria-label="Project records"><table class="data-table"><caption class="table-caption">Project records · synthetic fixture</caption><thead class="data-table-head"><tr><th class="data-table-header data-table-header-select" scope="col"><button class="data-table-select-all" type="button" role="checkbox" aria-checked="false" aria-label="Select all rows"><span class="data-table-check-glyph" aria-hidden="true">✓</span></button></th><th class="data-table-header" scope="col"><button class="data-table-sort" type="button">Project<span class="data-table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="data-table-header" scope="col"><button class="data-table-sort" type="button">Owner<span class="data-table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="data-table-header" scope="col"><button class="data-table-sort" type="button">Status<span class="data-table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="data-table-header" scope="col"><button class="data-table-sort" type="button">Scope<span class="data-table-sort-glyph" aria-hidden="true">↕</span></button></th></tr></thead><tbody class="data-table-body"><tr class="data-table-row" id="example-data-table-selectable-record-0" data-status="Ready" aria-selected="false" tabindex="0"><td class="data-table-cell data-table-cell-select"><input class="data-table-checkbox" type="checkbox" aria-labelledby="example-data-table-selectable-record-name-0" name="example-data-table-selectable-value"></td><td class="data-table-cell" id="example-data-table-selectable-record-name-0">Atlas library</td><td class="data-table-cell">Avery Kim</td><td class="data-table-cell">Ready</td><td class="data-table-cell">24</td></tr><tr class="data-table-row" id="example-data-table-selectable-record-1" data-status="In progress" aria-selected="false" tabindex="-1"><td class="data-table-cell data-table-cell-select"><input class="data-table-checkbox" type="checkbox" aria-labelledby="example-data-table-selectable-record-name-1" name="example-data-table-selectable-value"></td><td class="data-table-cell" id="example-data-table-selectable-record-name-1">Orion workspace</td><td class="data-table-cell">Jordan Lee</td><td class="data-table-cell">In progress</td><td class="data-table-cell">12</td></tr><tr class="data-table-row" id="example-data-table-selectable-record-2" data-status="Ready" aria-selected="false" tabindex="-1"><td class="data-table-cell data-table-cell-select"><input class="data-table-checkbox" type="checkbox" aria-labelledby="example-data-table-selectable-record-name-2" name="example-data-table-selectable-value"></td><td class="data-table-cell" id="example-data-table-selectable-record-name-2">Field notes</td><td class="data-table-cell">Morgan Noor</td><td class="data-table-cell">Ready</td><td class="data-table-cell">38</td></tr><tr class="data-table-row" id="example-data-table-selectable-record-3" data-status="Review" aria-selected="false" tabindex="-1"><td class="data-table-cell data-table-cell-select"><input class="data-table-checkbox" type="checkbox" aria-labelledby="example-data-table-selectable-record-name-3" name="example-data-table-selectable-value"></td><td class="data-table-cell" id="example-data-table-selectable-record-name-3">Signal monitor</td><td class="data-table-cell">Riley Stone</td><td class="data-table-cell">Review</td><td class="data-table-cell">6</td></tr><tr class="data-table-empty" hidden=""><td class="data-table-empty-cell" colspan="5">No rows match.</td></tr><tr class="data-table-loading" hidden=""><td colspan="5">⋯ Loading rows</td></tr></tbody></table></div></j3w1-data-table>resizable
| Atlas library | Avery Kim | Ready | 24 | |
| Orion workspace | Jordan Lee | In progress | 12 | |
| Field notes | Morgan Noor | Ready | 38 | |
| Signal monitor | Riley Stone | Review | 6 | |
| No rows match. | ||||
| ⋯ Loading rows | ||||
<j3w1-data-table id="example-data-table-resizable"><div class="table-scroller" tabindex="0" role="region" aria-label="Project records"><table class="data-table"><caption class="table-caption">Project records · synthetic fixture</caption><thead class="data-table-head"><tr><th class="data-table-header data-table-header-select" scope="col"><button class="data-table-select-all" type="button" role="checkbox" aria-checked="false" aria-label="Select all rows"><span class="data-table-check-glyph" aria-hidden="true">✓</span></button></th><th class="data-table-header" scope="col"><button class="data-table-sort" type="button">Project<span class="data-table-sort-glyph" aria-hidden="true">↕</span></button><span class="data-table-resize" aria-hidden="true"></span><j3w1-menu><div class="menu"><button class="menu-button" type="button" id="example-data-table-resizable-width-trigger-1" aria-haspopup="menu" aria-expanded="false" aria-controls="example-data-table-resizable-width-menu-1">Width: Project</button><ul class="menu-list" role="menu" id="example-data-table-resizable-width-menu-1" aria-labelledby="example-data-table-resizable-width-trigger-1" hidden=""><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="resize:1:narrow">Narrower</button></li><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="resize:1:widen">Wider</button></li><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="resize:1:reset">Reset width</button></li></ul></div></j3w1-menu></th><th class="data-table-header" scope="col"><button class="data-table-sort" type="button">Owner<span class="data-table-sort-glyph" aria-hidden="true">↕</span></button><span class="data-table-resize" aria-hidden="true"></span><j3w1-menu><div class="menu"><button class="menu-button" type="button" id="example-data-table-resizable-width-trigger-2" aria-haspopup="menu" aria-expanded="false" aria-controls="example-data-table-resizable-width-menu-2">Width: Owner</button><ul class="menu-list" role="menu" id="example-data-table-resizable-width-menu-2" aria-labelledby="example-data-table-resizable-width-trigger-2" hidden=""><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="resize:2:narrow">Narrower</button></li><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="resize:2:widen">Wider</button></li><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="resize:2:reset">Reset width</button></li></ul></div></j3w1-menu></th><th class="data-table-header" scope="col"><button class="data-table-sort" type="button">Status<span class="data-table-sort-glyph" aria-hidden="true">↕</span></button><span class="data-table-resize" aria-hidden="true"></span><j3w1-menu><div class="menu"><button class="menu-button" type="button" id="example-data-table-resizable-width-trigger-3" aria-haspopup="menu" aria-expanded="false" aria-controls="example-data-table-resizable-width-menu-3">Width: Status</button><ul class="menu-list" role="menu" id="example-data-table-resizable-width-menu-3" aria-labelledby="example-data-table-resizable-width-trigger-3" hidden=""><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="resize:3:narrow">Narrower</button></li><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="resize:3:widen">Wider</button></li><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="resize:3:reset">Reset width</button></li></ul></div></j3w1-menu></th><th class="data-table-header" scope="col"><button class="data-table-sort" type="button">Scope<span class="data-table-sort-glyph" aria-hidden="true">↕</span></button><span class="data-table-resize" aria-hidden="true"></span><j3w1-menu><div class="menu"><button class="menu-button" type="button" id="example-data-table-resizable-width-trigger-4" aria-haspopup="menu" aria-expanded="false" aria-controls="example-data-table-resizable-width-menu-4">Width: Scope</button><ul class="menu-list" role="menu" id="example-data-table-resizable-width-menu-4" aria-labelledby="example-data-table-resizable-width-trigger-4" hidden=""><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="resize:4:narrow">Narrower</button></li><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="resize:4:widen">Wider</button></li><li role="none"><button class="menu-item" type="button" role="menuitem" tabindex="-1" data-action="resize:4:reset">Reset width</button></li></ul></div></j3w1-menu></th></tr></thead><tbody class="data-table-body"><tr class="data-table-row" id="example-data-table-resizable-record-0" data-status="Ready" aria-selected="false" tabindex="0"><td class="data-table-cell data-table-cell-select"><input class="data-table-checkbox" type="checkbox" aria-labelledby="example-data-table-resizable-record-name-0" name="example-data-table-resizable-value"></td><td class="data-table-cell" id="example-data-table-resizable-record-name-0">Atlas library</td><td class="data-table-cell">Avery Kim</td><td class="data-table-cell">Ready</td><td class="data-table-cell">24</td></tr><tr class="data-table-row" id="example-data-table-resizable-record-1" data-status="In progress" aria-selected="false" tabindex="-1"><td class="data-table-cell data-table-cell-select"><input class="data-table-checkbox" type="checkbox" aria-labelledby="example-data-table-resizable-record-name-1" name="example-data-table-resizable-value"></td><td class="data-table-cell" id="example-data-table-resizable-record-name-1">Orion workspace</td><td class="data-table-cell">Jordan Lee</td><td class="data-table-cell">In progress</td><td class="data-table-cell">12</td></tr><tr class="data-table-row" id="example-data-table-resizable-record-2" data-status="Ready" aria-selected="false" tabindex="-1"><td class="data-table-cell data-table-cell-select"><input class="data-table-checkbox" type="checkbox" aria-labelledby="example-data-table-resizable-record-name-2" name="example-data-table-resizable-value"></td><td class="data-table-cell" id="example-data-table-resizable-record-name-2">Field notes</td><td class="data-table-cell">Morgan Noor</td><td class="data-table-cell">Ready</td><td class="data-table-cell">38</td></tr><tr class="data-table-row" id="example-data-table-resizable-record-3" data-status="Review" aria-selected="false" tabindex="-1"><td class="data-table-cell data-table-cell-select"><input class="data-table-checkbox" type="checkbox" aria-labelledby="example-data-table-resizable-record-name-3" name="example-data-table-resizable-value"></td><td class="data-table-cell" id="example-data-table-resizable-record-name-3">Signal monitor</td><td class="data-table-cell">Riley Stone</td><td class="data-table-cell">Review</td><td class="data-table-cell">6</td></tr><tr class="data-table-empty" hidden=""><td class="data-table-empty-cell" colspan="5">No rows match.</td></tr><tr class="data-table-loading" hidden=""><td colspan="5">⋯ Loading rows</td></tr></tbody></table></div></j3w1-data-table>Install and register
Use the exact version. If npm publication is pending, install the release tarball from the installation guide.
npm install --save-exact @j3w1/ui@4.0.0import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/data-table.css';
import '@j3w1/ui/register/data-table';Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.
Copy the complete implementation
npx --package=@j3w1/ui@4.0.0 j3w1-ui copy data-table --out ./vendor/j3w1/data-tableThe CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.
Public API
attributes
| Name | Type / signature | Meaning |
|---|---|---|
disabled | CustomEvent | Disable the native controls owned by this instance. |
loading | CustomEvent | Mark the primary control busy and prevent duplicate activation. |
properties
| Name | Type / signature | Meaning |
|---|---|---|
disabled | boolean | Delegates disabled state to native children. |
name | string | Native control name; application form keys remain explicit. |
selectedIds | string[] | Stable selected row IDs. |
methods
| Name | Type / signature | Meaning |
|---|---|---|
refresh | (): void | Reconnect behavior after replacing native child structure. |
focus | (options?: FocusOptions): void | Focus the first usable native control. |
sort | (column: number, direction?: 'ascending' | 'descending'): void | Sort existing native rows by a column. |
filter | (query: string): void | Filter existing rows by literal text. |
events
| Name | Type / signature | Meaning |
|---|---|---|
j3w1-sort | CustomEvent | The user requested sorting. |
j3w1-selection | CustomEvent | Selected row identities changed. |
Dependencies and verification
Registered components: menu. Style dependencies: menu.
Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.
Full implementation manifest, API and token dependency closure
Canonical specification
Data table data-table
A native table with controls: a selection column with a mixed select-all, sortable headers, row focus with the ring on the fill, and static resize handles.
Report an issue with this component
Tokens
Focus a role to inspect its values; follow its link for persistent usage and source details.
| Part | Role | Value | Use |
|---|---|---|---|
root.bg | color.surface.defaultapproveduse | #0d0707 | D-041 surface.default: color.primitive.modern.panel. |
header.text | color.text.brightapproveduse | #ffa2a7 | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
header.rule | color.border.strongobserveduse | #9e231f | Emphasised 2px rule: sticky headers, section ends. |
sort.glyph | color.text.brightapproveduse | #ffa2a7 | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
row.text | color.text.defaultapproveduse | #e99499 | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
row.divider | color.border.dividerapproveduse | #482b2b | D-041 border.divider: color.primitive.modern.divider. |
row.bg-hover | color.interaction.hover.bgapproveduse | #1c1010 | D-041 interaction.hover.bg: color.primitive.modern.hover. |
row.ring | color.interaction.focus.ringobserveduse | #e53935 | 1px dashed focus ring on controls and rows. |
selected.bg | color.interaction.selection.bgapproveduse | #531310 | Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection. |
selected.text | color.interaction.selection.textobserveduse | #f4eeee | Text on the selection. |
selected.ring | color.interaction.focus.ringobserveduse | #e53935 | 1px dashed focus ring on controls and rows. |
checkbox.bg | color.surface.inputapproveduse | #000000 | Form-control fill. |
checkbox.border | color.border.controlapproveduse | #c81a1a | D-041 owner correction: red control and floating-frame borders, distinct from rose text. |
checkbox.checked-bg | color.action.primary.bgapproveduse | #7d1310 | Primary button fill; D-026 darkened it off color12, which stays fixed as heritage ANSI 12. |
checkbox.glyph | color.action.primary.textapproveduse | #ffa2a7 | Primary action labels: bright rose across rest, hover and pressed states (D-033). |
resize.handle | color.border.defaultapproveduse | #482b2b | D-041 border.default: color.primitive.modern.divider. |
resize.handle-hover | color.border.activeobserveduse | #e53935 | Active or focused control border. |
empty.text | color.text.mutedapproveduse | #d4868b | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
loading.glyph | color.text.mutedapproveduse | #d4868b | D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills. |
State matrix
Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).
| State | Default | Selectable | Resizable | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
default |
|
|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hover | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
focus-visible | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selected | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
selected+focus-visible | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sorted | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mixed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
empty | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
loading | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Purpose
A table the user works in; the plain table is for reading. It stays a
native table so cells keep their header associations; a host that needs
cell-level navigation promotes it to a grid and records the change.
Anatomy
The table structure, rule, dividers and fills, plus the parts listed in
the anatomy; row checkboxes have a 1px color.border.control boundary.
States
| State | Visual | Non-colour channel |
|---|---|---|
| default | rows on color.surface.default; header rule 1px color.border.strong | — |
| hover | row → color.interaction.hover.bg; a resize handle → color.border.active | cursor: default on rows, col-resize on handles |
| focus-visible | 1px dashed color.interaction.focus.ring at −2px around the focused row or control | the ring |
| selected | row fill color.interaction.selection.bg; every cell color.interaction.selection.text; row checkbox checked | aria-selected="true"; the checked box |
| selected+focus-visible | the fill and 1px dashed color.interaction.focus.ring at −2px | both visible at once |
| sorted | ▲ or ▼ in color.text.bright on the sorted header | aria-sort; the glyph |
| mixed | select-all on color.action.primary.bg with the – glyph | aria-checked="mixed"; the glyph |
| empty | one full-width cell in color.text.muted: “No rows match.”; header and controls stay | the message text |
| loading | one full-width cell with the static ⋯ glyph; the header stays | aria-busy="true"; the glyph; no animation |
Precedence: loading > empty; selected > hover; focus-visible is always drawn. Selection is a fill, focus a ring; neither borrows the other’s form.
Keyboard
Controls inside the focused row are reached with Tab and left with Shift+Tab. Column widths come from a header menu or the handle, which is never a tab stop.
Accessibility
Each row checkbox is labelled by the row’s first data cell
(aria-labelledby); the select-all is named “Select all rows”.
aria-selected on the row mirrors its checkbox. The selected-row count is
announced through a live region owned by the surrounding toolbar. Text meets
4.5:1; boundaries and rings 3:1. Checkboxes and handles are at least 24 CSS
pixels tall in compact.
Portability
The table drawing plus a checkbox column and header checkbox; the handle
is a 1px rule. Native table views map row selection to their selection model
and mixed to their tristate checkbox. A host without row focus keeps the
checkbox as the only row control and records it.
Non-examples
A grid role on a table not navigated cell by cell. Zebra stripes. A
select-all that is a native checkbox with a script-only indeterminate state
and no aria-checked.
Row selection by click with no checkbox alternative. A selected row shown by
a border alone. A resize handle as a tab stop. An animated loading skeleton.
Rounded checkboxes. Truncated text with no full-value affordance.
Contrast report
17 declared pairs measured on resolved sRGB values with the WCAG 2.x formula; 0 waived (decorative only), 0 failing. A pass is a design target for the named role, not an application-wide conformance claim.
| Pair | State | Kind | Foreground | Background | Ratio | Min | Result |
|---|---|---|---|---|---|---|---|
| data-table default text | default | text | color.text.default #e99499 | color.surface.default #0d0707 | 8.72 | 4.5 | pass |
| data-table hover text | hover | text | color.text.default #e99499 | color.interaction.hover.bg #1c1010 | 8.10 | 4.5 | pass |
| data-table focus-visible text | focus-visible | text | color.text.default #e99499 | color.surface.default #0d0707 | 8.72 | 4.5 | pass |
| data-table focus-visible outline | focus-visible | ui | color.interaction.focus.ring #e53935 | color.surface.default #0d0707 | 4.73 | 3 | pass |
| data-table selected text | selected | text | color.interaction.selection.text #f4eeee | color.interaction.selection.bg #531310 | 12.47 | 4.5 | pass |
| data-table selected+focus-visible text | selected+focus-visible | text | color.interaction.selection.text #f4eeee | color.interaction.selection.bg #531310 | 12.47 | 4.5 | pass |
| data-table selected+focus-visible outline | selected+focus-visible | ui | color.interaction.focus.ring #e53935 | color.interaction.selection.bg #531310 | 3.38 | 3 | pass |
| data-table sorted text | sorted | text | color.text.bright #ffa2a7 | color.surface.default #0d0707 | 10.45 | 4.5 | pass |
| data-table mixed text | mixed | text | color.action.primary.text #ffa2a7 | color.action.primary.bg #7d1310 | 5.57 | 4.5 | pass |
| data-table empty text | empty | text | color.text.muted #d4868b | color.surface.default #0d0707 | 7.22 | 4.5 | pass |
| data-table loading text | loading | text | color.text.muted #d4868b | color.surface.default #0d0707 | 7.22 | 4.5 | pass |
| header text | — | text | color.text.bright #ffa2a7 | color.surface.default #0d0707 | 10.45 | 4.5 | pass |
| checkbox boundary | — | ui | color.border.control #c81a1a | color.surface.input #000000 | 3.62 | 3 | pass |
| checked fill against the row (the glyph and the boundary carry the state) | mixed | ui | color.action.primary.bg #7d1310 | color.surface.default #0d0707 | 1.88 | 1 | pass |
| header rule (decorative) | — | ui | color.border.strong #9e231f | color.surface.default #0d0707 | 2.58 | 1 | pass |
| row divider (decorative) | — | ui | color.border.divider #482b2b | color.surface.default #0d0707 | 1.58 | 1 | pass |
| resize handle at rest (decorative; keyboard resizing is a header action) | — | ui | color.border.default #482b2b | color.surface.default #0d0707 | 1.58 | 1 | pass |
Keys
| Key | Action |
|---|---|
| Tab / Shift+Tab | Moves through the select-all, the sort buttons, then the rows (one row is the tab stop; roving tabindex) and any control inside the focused row. |
| Down / Up | Moves row focus; in a single-select table the selection follows focus. |
| Space | Toggles the focused row's selection (the same as its checkbox). |
| Shift+Down / Shift+Up | Extends the selection by one row. |
| Ctrl+A | Selects every row; the select-all reflects it. |
| Enter / Space | On a sort button, cycles the sort; on the select-all, toggles between all and none. |
| Left / Right | Reserved for cell navigation in hosts that promote the table to a grid; not used here. |
For agents
Component JSON ·Implementation brief ·Build a task kit ·
Related: table checkbox pagination toolbar filterable-table
Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-DENSITY FX-OVERFLOW FX-TOUCH FX-STATE-MATRIX