j3w1 / theme

j3w1 / theme4.0.0

j3w1 / command

  • SPEC Overview
  • SPEC Foundations
  • SPEC Components
  • SPEC Patterns
  • SPEC Tokens
  • SPEC Tools
  • SPEC Workbench
  • SPEC Form builder
  • SPEC Task kit
  • SPEC Recipes
  • SPEC Figma bridge
  • SPEC Report an issue
  • SPEC Implement
  • SPEC For agents
  • SPEC Ports
  • SPEC Releases
  • SPEC Specification
  • DEMO Vue application demo

Table

A native data table with a header rule, row dividers, hover and selection fills, sortable headers with a glyph, and static empty and loading rows.

stable · light DOM · 4.0.0. Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.

Live variants

default

Project records · synthetic fixture
Atlas libraryAvery KimReady24
Orion workspaceJordan LeeIn progress12
Field notesMorgan NoorReady38
Signal monitorRiley StoneReview6
Markup
<j3w1-table id="example-table-default"><div class="table-scroller" tabindex="0" role="region" aria-label="Project records"><table class="table"><caption class="table-caption">Project records · synthetic fixture</caption><thead class="table-head"><tr><th class="table-header" scope="col"><button class="table-sort" type="button">Project<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="table-header" scope="col"><button class="table-sort" type="button">Owner<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="table-header" scope="col"><button class="table-sort" type="button">Status<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="table-header" scope="col"><button class="table-sort" type="button">Scope<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th></tr></thead><tbody class="table-body"><tr class="table-row" id="example-table-default-record-0" data-status="Ready"><td class="table-cell" id="example-table-default-record-name-0">Atlas library</td><td class="table-cell">Avery Kim</td><td class="table-cell">Ready</td><td class="table-cell">24</td></tr><tr class="table-row" id="example-table-default-record-1" data-status="In progress"><td class="table-cell" id="example-table-default-record-name-1">Orion workspace</td><td class="table-cell">Jordan Lee</td><td class="table-cell">In progress</td><td class="table-cell">12</td></tr><tr class="table-row" id="example-table-default-record-2" data-status="Ready"><td class="table-cell" id="example-table-default-record-name-2">Field notes</td><td class="table-cell">Morgan Noor</td><td class="table-cell">Ready</td><td class="table-cell">38</td></tr><tr class="table-row" id="example-table-default-record-3" data-status="Review"><td class="table-cell" id="example-table-default-record-name-3">Signal monitor</td><td class="table-cell">Riley Stone</td><td class="table-cell">Review</td><td class="table-cell">6</td></tr><tr class="table-empty" hidden=""><td class="table-empty-cell" colspan="4">No rows match.</td></tr><tr class="table-loading" hidden=""><td colspan="4">⋯ Loading rows</td></tr></tbody></table></div></j3w1-table>

sticky-header

Project records · synthetic fixture
Atlas libraryAvery KimReady24
Orion workspaceJordan LeeIn progress12
Field notesMorgan NoorReady38
Signal monitorRiley StoneReview6
Markup
<j3w1-table id="example-table-sticky-header"><div class="table-scroller" tabindex="0" role="region" aria-label="Project records"><table class="table"><caption class="table-caption">Project records · synthetic fixture</caption><thead class="table-head"><tr><th class="table-header" scope="col"><button class="table-sort" type="button">Project<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="table-header" scope="col"><button class="table-sort" type="button">Owner<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="table-header" scope="col"><button class="table-sort" type="button">Status<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="table-header" scope="col"><button class="table-sort" type="button">Scope<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th></tr></thead><tbody class="table-body"><tr class="table-row" id="example-table-sticky-header-record-0" data-status="Ready"><td class="table-cell" id="example-table-sticky-header-record-name-0">Atlas library</td><td class="table-cell">Avery Kim</td><td class="table-cell">Ready</td><td class="table-cell">24</td></tr><tr class="table-row" id="example-table-sticky-header-record-1" data-status="In progress"><td class="table-cell" id="example-table-sticky-header-record-name-1">Orion workspace</td><td class="table-cell">Jordan Lee</td><td class="table-cell">In progress</td><td class="table-cell">12</td></tr><tr class="table-row" id="example-table-sticky-header-record-2" data-status="Ready"><td class="table-cell" id="example-table-sticky-header-record-name-2">Field notes</td><td class="table-cell">Morgan Noor</td><td class="table-cell">Ready</td><td class="table-cell">38</td></tr><tr class="table-row" id="example-table-sticky-header-record-3" data-status="Review"><td class="table-cell" id="example-table-sticky-header-record-name-3">Signal monitor</td><td class="table-cell">Riley Stone</td><td class="table-cell">Review</td><td class="table-cell">6</td></tr><tr class="table-empty" hidden=""><td class="table-empty-cell" colspan="4">No rows match.</td></tr><tr class="table-loading" hidden=""><td colspan="4">⋯ Loading rows</td></tr></tbody></table></div></j3w1-table>

numeric

Project records · synthetic fixture
Atlas libraryAvery KimReady24
Orion workspaceJordan LeeIn progress12
Field notesMorgan NoorReady38
Signal monitorRiley StoneReview6
Markup
<j3w1-table id="example-table-numeric"><div class="table-scroller" tabindex="0" role="region" aria-label="Project records"><table class="table"><caption class="table-caption">Project records · synthetic fixture</caption><thead class="table-head"><tr><th class="table-header" scope="col"><button class="table-sort" type="button">Project<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="table-header" scope="col"><button class="table-sort" type="button">Owner<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="table-header" scope="col"><button class="table-sort" type="button">Status<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="table-header" scope="col"><button class="table-sort" type="button">Scope<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th></tr></thead><tbody class="table-body"><tr class="table-row" id="example-table-numeric-record-0" data-status="Ready"><td class="table-cell" id="example-table-numeric-record-name-0">Atlas library</td><td class="table-cell">Avery Kim</td><td class="table-cell">Ready</td><td class="table-cell">24</td></tr><tr class="table-row" id="example-table-numeric-record-1" data-status="In progress"><td class="table-cell" id="example-table-numeric-record-name-1">Orion workspace</td><td class="table-cell">Jordan Lee</td><td class="table-cell">In progress</td><td class="table-cell">12</td></tr><tr class="table-row" id="example-table-numeric-record-2" data-status="Ready"><td class="table-cell" id="example-table-numeric-record-name-2">Field notes</td><td class="table-cell">Morgan Noor</td><td class="table-cell">Ready</td><td class="table-cell">38</td></tr><tr class="table-row" id="example-table-numeric-record-3" data-status="Review"><td class="table-cell" id="example-table-numeric-record-name-3">Signal monitor</td><td class="table-cell">Riley Stone</td><td class="table-cell">Review</td><td class="table-cell">6</td></tr><tr class="table-empty" hidden=""><td class="table-empty-cell" colspan="4">No rows match.</td></tr><tr class="table-loading" hidden=""><td colspan="4">⋯ Loading rows</td></tr></tbody></table></div></j3w1-table>

with-caption

Project records · synthetic fixture
Atlas libraryAvery KimReady24
Orion workspaceJordan LeeIn progress12
Field notesMorgan NoorReady38
Signal monitorRiley StoneReview6
Markup
<j3w1-table id="example-table-with-caption"><div class="table-scroller" tabindex="0" role="region" aria-label="Project records"><table class="table"><caption class="table-caption">Project records · synthetic fixture</caption><thead class="table-head"><tr><th class="table-header" scope="col"><button class="table-sort" type="button">Project<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="table-header" scope="col"><button class="table-sort" type="button">Owner<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="table-header" scope="col"><button class="table-sort" type="button">Status<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th><th class="table-header" scope="col"><button class="table-sort" type="button">Scope<span class="table-sort-glyph" aria-hidden="true">↕</span></button></th></tr></thead><tbody class="table-body"><tr class="table-row" id="example-table-with-caption-record-0" data-status="Ready"><td class="table-cell" id="example-table-with-caption-record-name-0">Atlas library</td><td class="table-cell">Avery Kim</td><td class="table-cell">Ready</td><td class="table-cell">24</td></tr><tr class="table-row" id="example-table-with-caption-record-1" data-status="In progress"><td class="table-cell" id="example-table-with-caption-record-name-1">Orion workspace</td><td class="table-cell">Jordan Lee</td><td class="table-cell">In progress</td><td class="table-cell">12</td></tr><tr class="table-row" id="example-table-with-caption-record-2" data-status="Ready"><td class="table-cell" id="example-table-with-caption-record-name-2">Field notes</td><td class="table-cell">Morgan Noor</td><td class="table-cell">Ready</td><td class="table-cell">38</td></tr><tr class="table-row" id="example-table-with-caption-record-3" data-status="Review"><td class="table-cell" id="example-table-with-caption-record-name-3">Signal monitor</td><td class="table-cell">Riley Stone</td><td class="table-cell">Review</td><td class="table-cell">6</td></tr><tr class="table-empty" hidden=""><td class="table-empty-cell" colspan="4">No rows match.</td></tr><tr class="table-loading" hidden=""><td colspan="4">⋯ Loading rows</td></tr></tbody></table></div></j3w1-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.0
import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/table.css';
import '@j3w1/ui/register/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.

Vue SFC, React, Astro and plain HTML integration →

Copy the complete implementation

npx --package=@j3w1/ui@4.0.0 j3w1-ui copy table --out ./vendor/j3w1/table

The 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

NameType / signatureMeaning
disabledCustomEventDisable the native controls owned by this instance.
loadingCustomEventMark the primary control busy and prevent duplicate activation.

properties

NameType / signatureMeaning
disabledbooleanDelegates disabled state to native children.
namestringNative control name; application form keys remain explicit.

methods

NameType / signatureMeaning
refresh(): voidReconnect behavior after replacing native child structure.
focus(options?: FocusOptions): voidFocus the first usable native control.
sort(column: number, direction?: 'ascending' | 'descending'): voidSort existing native rows by a column.
filter(query: string): voidFilter existing rows by literal text.

events

NameType / signatureMeaning
j3w1-sortCustomEventThe user requested sorting.
j3w1-selectionCustomEventSelected row identities changed.

Dependencies and verification

Registered components: none. Style dependencies: none.

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

Table table

  • Family: Information display
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native table with caption, thead, th scope, aria-sort on sorted headers and aria-busy while loading
  • specified
  • demonstrated
  • test implemented

A native data table with a header rule, row dividers, hover and selection fills, sortable headers with a glyph, and static empty and loading rows.

Report an issue with this component

Open component workbench

Tokens

Focus a role to inspect its values; follow its link for persistent usage and source details.

PartRoleValueUse
root.bgcolor.surface.defaultapproveduse#0d0707D-041 surface.default: color.primitive.modern.panel.
header.textcolor.text.brightapproveduse#ffa2a7D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
header.bgcolor.surface.defaultapproveduse#0d0707D-041 surface.default: color.primitive.modern.panel.
header.rulecolor.border.strongobserveduse#9e231fEmphasised 2px rule: sticky headers, section ends.
header.bg-stickycolor.surface.raisedapproveduse#140b0bD-041 surface.raised: color.primitive.modern.raised.
sort.glyphcolor.text.brightapproveduse#ffa2a7D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
sort.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
row.textcolor.text.defaultapproveduse#e99499D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
row.dividercolor.border.dividerapproveduse#482b2bD-041 border.divider: color.primitive.modern.divider.
row.bg-hovercolor.interaction.hover.bgapproveduse#1c1010D-041 interaction.hover.bg: color.primitive.modern.hover.
selected.bgcolor.interaction.selection.bgapproveduse#531310Selected row, tab, workspace; D-027 recessed the fill, leaving the 2px indicator and the check to carry selection.
selected.textcolor.interaction.selection.textobserveduse#f4eeeeText on the selection.
selected.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
selected.inactive-bgcolor.interaction.selection.inactive-bgobserveduse#420f0cSelection while the container is not focused.
selected.inactive-textcolor.interaction.selection.inactive-textapproveduse#e99499D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
caption.textcolor.text.mutedapproveduse#d4868bD-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
empty.textcolor.text.mutedapproveduse#d4868bD-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
loading.glyphcolor.text.mutedapproveduse#d4868bD-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).

StateDefaultSticky headerNumericWith caption
default
tabsnavigationR17
menunavigationR18
tabledisplayR18
chartdisplayR20
tabsnavigationR17
menunavigationR18
tabledisplayR18
chartdisplayR20
tabsnavigationR17
menunavigationR18
tabledisplayR18
chartdisplayR20
Components in this batch, with their declared state counts
tabsnavigationR17
menunavigationR18
tabledisplayR18
chartdisplayR20
hover
selected
selected+focus-visible
selected+container-inactive
sorted
empty
loading

Purpose

Records as rows, attributes as columns, compared down a column. For reading only: selection, resizing and a toolbar make it a data-table; a single column of rows is a list.

Anatomy

Parts as listed in the anatomy; the sticky header sits on color.surface.raised.

States

StateVisualNon-colour channel
defaultrows on color.surface.default; header rule 1px color.border.strong—
hoverrow → color.interaction.hover.bgcursor: default; hover-capable pointers only
selectedrow fill color.interaction.selection.bg; every cell color.interaction.selection.textaria-selected="true" on the row
selected+focus-visiblethe fill and 1px dashed color.interaction.focus.ring at −2px around the rowboth visible at once
selected+container-inactiverow fill color.interaction.selection.inactive-bg with color.interaction.selection.inactive-text; no ringlightness drop between the two fills
sorted▲ (ascending) or ▼ (descending) in color.text.bright on the sorted headeraria-sort; the glyph
emptyone full-width cell in color.text.muted: “No rows match.”the message text
loadingone full-width cell with the static ⋯ glyph in color.text.muted; the header staysaria-busy="true"; the glyph; no animation

Precedence: loading > empty; selected > hover; focus-visible is always drawn.

Keyboard

As in the key table. Rows that are targets (row links, row selection) make it a data-table, which adds row focus.

Accessibility

caption or aria-labelledby names the table; scope="row" on a row header column. aria-sort is none or absent on unsorted headers; the glyph is aria-hidden. Empty and loading rows are real rows; a live region reports the loading outcome. Text meets 4.5:1; rings 3:1. Rows are at least 24 CSS pixels tall; sort buttons fill the header cell.

Portability

Row backgrounds, one border under the header, one between rows, an outline on a selected row. Native table views take the rule, the divider and the two fills. A host that cannot outline a row draws the ring as an inset 1px border and records it.

Non-examples

Zebra striping. A rounded or bordered frame. A selected row marked by a left bar (that is navigation). Header text in caption size or uppercase. Sorting by colour alone without aria-sort and a glyph. An animated spinner. An empty state that removes the header. Truncated text with no way to read the full value. Hover fill on touch.

Contrast report

15 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.

PairStateKindForegroundBackgroundRatioMinResult
table default textdefaulttextcolor.text.default #e99499color.surface.default #0d07078.724.5pass
table hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c10108.104.5pass
table selected textselectedtextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
table selected+focus-visible textselected+focus-visibletextcolor.interaction.selection.text #f4eeeecolor.interaction.selection.bg #53131012.474.5pass
table selected+focus-visible outlineselected+focus-visibleuicolor.interaction.focus.ring #e53935color.interaction.selection.bg #5313103.383pass
table selected+container-inactive textselected+container-inactivetextcolor.interaction.selection.inactive-text #e99499color.interaction.selection.inactive-bg #420f0c7.024.5pass
table sorted textsortedtextcolor.text.bright #ffa2a7color.surface.default #0d070710.454.5pass
table empty textemptytextcolor.text.muted #d4868bcolor.surface.default #0d07077.224.5pass
table loading textloadingtextcolor.text.muted #d4868bcolor.surface.default #0d07077.224.5pass
header text—textcolor.text.bright #ffa2a7color.surface.default #0d070710.454.5pass
sticky header text on the raised surface—textcolor.text.bright #ffa2a7color.surface.raised #140b0b10.144.5pass
caption—textcolor.text.muted #d4868bcolor.surface.default #0d07077.224.5pass
ring on a sort button—uicolor.interaction.focus.ring #e53935color.surface.default #0d07074.733pass
header rule (decorative; thead carries the structure)—uicolor.border.strong #9e231fcolor.surface.default #0d07072.581pass
row divider (decorative)—uicolor.border.divider #482b2bcolor.surface.default #0d07071.581pass

Keys

KeyAction
Tab / Shift+TabMoves between the sort buttons and any controls inside cells; rows themselves are not tab stops in a plain table.
Enter / SpaceToggles the sort of the focused header between ascending and descending.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: data-table list pagination badge filterable-table

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-DENSITY FX-OVERFLOW FX-STATE-MATRIX