j3w1/theme implementation brief — filterable-table theme: j3w1-theme 1.1.0 profile: default sourceDigest: sha256-C+iD5Q7l0XPU/boMj003wPbPLBOq3C3ZM7s4OfzJ6mc= pin: https://raw.githubusercontent.com/j3w1/theme/v1.1.0/exports/components/filterable-table.json spec: spec/components/filterable-table.md site: https://j3w1.github.io/theme/reference/#c-filterable-table maturity: stable priority: R1 Summary: A list screen composed from a toolbar with search and filter, removable chips, a selectable sortable data-table with status badges, a count and pagination; with empty and loading variants. Use the pinned approved default profile. Pending roles in that profile use-and-report their decision IDs; this does not approve them. Proposed profiles are preview-only and blocked for delivery. Heritage profiles are historical-only. Deprecated or heritage roles are blocked for new approved-profile mappings. Consume roles within their documented scope, never primitives. Release numbering does not approve profiles or tokens. Tokens (resolved): root.bg #100c0c ({color.surface.default}) use root.border #531310 ({color.border.default}) use toolbar.bg #090707 ({color.surface.chrome}) use toolbar.border #2b0e0d ({color.border.divider}) use-and-report (D-008) toolbar.separator #531310 ({color.border.default}) use search.bg #000000 ({color.surface.input}) use search.border #a3676b ({color.border.control}) use-and-report (D-007) search.text #e99499 ({color.text.default}) use search.placeholder #a3676b ({color.text.placeholder}) use search.icon #e99499 ({color.icon.default}) use filter.text #e99499 ({color.text.default}) use filter.border #a3676b ({color.border.control}) use-and-report (D-007) new.bg #7d1310 ({color.action.primary.bg}) use new.text #f4eeee ({color.action.primary.text}) use chip.bg #100c0c ({color.surface.default}) use chip.border #a3676b ({color.border.control}) use-and-report (D-007) chip.text #e99499 ({color.text.default}) use chip.remove #bd787d ({color.text.muted}) use header.text #ffa2a7 ({color.text.bright}) use header.rule #9e231f ({color.border.strong}) use row.text #e99499 ({color.text.default}) use row.rule #2b0e0d ({color.border.divider}) use-and-report (D-008) row.bg-hover #1c0a09 ({color.interaction.hover.bg}) use row.ring #e53935 ({color.interaction.focus.ring}) use row.selected-bg #531310 ({color.interaction.selection.bg}) use row.selected-text #f4eeee ({color.interaction.selection.text}) use row.ring-on-selection #ffa2a7 ({color.interaction.focus.ring-container}) use check.bg #000000 ({color.surface.input}) use check.border #a3676b ({color.border.control}) use-and-report (D-007) check.checked-bg #7d1310 ({color.action.primary.bg}) use check.glyph #f4eeee ({color.action.primary.text}) use badge.tested-fill #86a46f ({color.status.success.fill}) use badge.tested-text #0c0909 ({color.status.success.on-fill}) use badge.demonstrated-fill #7e9ebb ({color.status.info.fill}) use badge.demonstrated-text #0c0909 ({color.status.info.on-fill}) use empty.text #bd787d ({color.text.muted}) use empty.heading #ffa2a7 ({color.text.bright}) use empty.glyph #a3676b ({color.icon.decorative}) use count.text #bd787d ({color.text.muted}) use pagination.text #e99499 ({color.text.default}) use pagination.current #ffa2a7 ({color.text.bright}) use pagination.disabled #8a5559 ({color.text.disabled}) use States: default, hover, focus-visible, selected, no-results default: rest tokens of every component; Name sorted ascending with its ▲ glyph; Prev disabled [`aria-sort`; the glyph] hover: the pointed row takes {color.interaction.hover.bg}; the toolbar controls and chips keep their own hover on their own pointer events only [cursor] focus-visible: the dashed {color.interaction.focus.ring} on the row holding focus (shown on the third row); the toolbar and chips stay at rest [the ring] selected: two rows take {color.interaction.selection.bg} with {color.interaction.selection.text} and a checked box; the select-all reports mixed with the – glyph [`aria-selected`; ✓ and – glyphs; `aria-checked="mixed"`] no-results: the body is the "No components match" row, the count reads 0 of 43, the search field's status line announces it; the chips stay so the cause is visible [text; `role="status"`] Keyboard: Tab / Shift+Tab: Into the toolbar (the search input is its stop), then each chip's Remove button, then the table (the first row is its stop), then Next. Arrow keys: Inside the toolbar move between the search field, Filter, Columns and New; inside the table move between rows; Home and End reach the first and last row. Enter / Space: Open the Filter menu; toggle Columns; activate New or a chip's Remove; on a header sort by it; on a row's checkbox toggle its selection. Escape: Clears a non-empty search; closes the Filter menu and returns focus to its button. ARIA: region landmark; a toolbar with roving tabindex holding a search landmark, a menu button, a toggle icon button and a button; a group of removable chips; a grid-less native table with aria-sort, aria-selected rows and a checkbox-role select-all; role=status for the count; a pagination nav (https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/) Responsive: The root is an inline-size container; below 600px the toolbar wraps with the search field on its own row and New at the end of the second, chips wrap, and the table scrolls inside its own container while the region never scrolls horizontally. The footer wraps the count above the pagination. RTL mirrors the toolbar order, the chip Remove side, the numeric column and the pagination glyphs. Portability: Native table semantics with aria-sort and aria-selected; the toolbar's roving tabindex and the menu need the host's script, everything else is static. The count is a status region so filtering announces its result once. Hosts without container queries wrap the toolbar at the 600px viewport breakpoint. The 56rem width and the 44rem table minimum are layout of this specimen, not rules. native: GTK4: a SearchBar and a MenuButton above a ColumnView with a selection column; badges are styled labels; the empty state is a StatusPage. native: Qt: a QToolBar, a flow of tag widgets, a QTableView with a check column and QStyledItemDelegate badges; the count is a QLabel in the status bar. native: Terminal UI: a one-line prompt row, filters as bracketed tags, the table as aligned columns with the selection fill; no hover. Rules: use only these values; no invented colours; radius 0; borders 1px (2px emphasis); focus is a 1px dashed ring, selection is a fill; do not restyle unrelated elements; report deviations per agents/consume.md; record theme.lock.json at the pinned revision.