MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-113

2.5.2 `components/ui/TreeTable` primitive (accessible tree-grid)

Done
Description

Estimate: 18m

The reusable, design-system primitive the list route composes — there is NO table primitive in components/ui/* today (JobsDashboard / WorkflowEditor each hand-roll a local <table>; this is the shared one). A generic, presentational TreeTable: typed columns (header + per-row cell render) and a nested rows model with expand/collapse, indentation by depth, a per-row chevron (leaf rows show none — matching the mockup), sticky header, and a whole-row link target. Pure presentation: it takes already-shaped data + render-props and emits no queries.

Accessibility is the load-bearing requirement. Implement the WAI-ARIA treegrid pattern: role="treegrid", rows with aria-level / aria-expanded / aria-posinset / aria-setsize, roving focus, and keyboard support (Up/Down move, Right expand / move-in, Left collapse / move-out, Enter opens the row). Themed entirely off --el-* tokens (header text --el-text-secondary, row hover hover:bg-(--el-surface) on the ROW not a page surface, borders --el-border); add a /tokens/tree-table specimen joined to the shell-a11y sweep. Match the mockup's spacing, the uppercase column captions, and the row density.

Acceptance criteria

  • Generic TreeTable<Row> with typed columns + nested rows; renders header + indented, expandable rows matching tree.png (chevron only on parents, type-icon/identifier/title in the TITLE cell via render-prop).
  • Full treegrid a11y: role="treegrid", aria-level/expanded/posinset/setsize, roving tabindex, arrow-key expand/collapse/move, Enter activates the row link; axe-clean on the specimen.
  • Colours via --el-* only (no Tier-0 utilities); row hover tints the row, never a page surface (finding #35).
  • Presentational only — no data fetching, no Server-Action imports; expand/collapse state is controllable by the consumer.
  • Component test (happy-dom): nesting + indent, expand/collapse toggles children + aria-expanded, keyboard move/expand; /tokens/tree-table in the strict shell-a11y sweep.

Context refs

  • design/work-items/tree.png (+ tree.pen) — layout / density / column captions (open it FIRST; inspect all 3 panels)
  • components/issues/ChildList.tsx (2.4.3) + ISSUE_TYPE_META / IssueTypeIcon / Pill — the row vocabulary to reuse
  • components/ui/Combobox.tsx (2.3.4) — the project's hand-rolled WAI-ARIA + roving-tabindex reference; app/globals.css --el-* tiers; /tokens route convention
  • motir-core/CLAUDE.md--el-* token rule
Status
Done
Type
Sub-task