Lane 0, second PR: the design system's controls, content and overlays (#364) #740

Merged
claude-bot merged 1 commit from build/lane0-components into main 2026-09-22 02:18:58 +00:00
Collaborator

Lane 0's second PR: twenty-six components on /design now, 138 states, each with a test. Nothing in the app uses the library yet.

Controls: Field, Select, Textarea (a real label; hint and error joined by aria-describedby; aria-invalid); Toggle (role="switch"; a disabled switch says why); Chip and ChipButton; Segmented (a radiogroup with a roving tabindex); Tabs and TabPanel (arrows, Home and End); InlineError; AudiencePicker (#593's five audiences as one control, anything narrower than the table in the GM tint); DateTime (the structured picker of CA-214: a wall clock in the campaign's own time, quarter hours that never snap an odd minute, the time waits on the day and says so).

Content: Card and Panel; List and ListRow (a clickable title, never a clickable row); Label; Meter (role="meter"); Fold; PersonDisc and Person (a member's colour and initial, the GM mark, a person's pronouns and never a character's); Doc, Section, KV, StatRow; Table, with the roll-table look as a roll variant rather than every table's first column.

Feedback and overlays: SaveState (D40's four states, one live region so the change is announced); Menu, MenuGroup, MenuItem (role="menu" on an anchored popover: Escape and Tab close and return focus, arrows and Home/End move, outside click closes, a disabled item says why); useOnClickOutside.

The modal's typed name now goes through Field, and Modal.css drops its temporary copy of the form rules. index.js exports all of it.

Two decisions for the record, from the delegates' reports: the kit keys the switch and the segmented control on aria-pressed; here they carry aria-checked (the right attribute for role="switch" and role="radio") and the CSS keys on that. Menu is role="menu", so Tab closes it; the bell's panel, which has its own head and foot controls, will want a role="dialog" variant when lane 1 builds it.

Lint clean under jsx-a11y at error and the React Compiler rules; 1,041 tests pass; render-checked at /design in both themes.

Next in the series: the shell components (app bar, Contents, account menu, bell, search, footer, live bar).

🤖 Generated with Claude Code

Lane 0's second PR: twenty-six components on `/design` now, 138 states, each with a test. Nothing in the app uses the library yet. **Controls**: `Field`, `Select`, `Textarea` (a real label; hint and error joined by `aria-describedby`; `aria-invalid`); `Toggle` (`role="switch"`; a disabled switch says why); `Chip` and `ChipButton`; `Segmented` (a radiogroup with a roving tabindex); `Tabs` and `TabPanel` (arrows, Home and End); `InlineError`; `AudiencePicker` (#593's five audiences as one control, anything narrower than the table in the GM tint); `DateTime` (the structured picker of CA-214: a wall clock in the campaign's own time, quarter hours that never snap an odd minute, the time waits on the day and says so). **Content**: `Card` and `Panel`; `List` and `ListRow` (a clickable title, never a clickable row); `Label`; `Meter` (`role="meter"`); `Fold`; `PersonDisc` and `Person` (a member's colour and initial, the GM mark, a person's pronouns and never a character's); `Doc`, `Section`, `KV`, `StatRow`; `Table`, with the roll-table look as a `roll` variant rather than every table's first column. **Feedback and overlays**: `SaveState` (D40's four states, one live region so the change is announced); `Menu`, `MenuGroup`, `MenuItem` (`role="menu"` on an anchored popover: Escape and Tab close and return focus, arrows and Home/End move, outside click closes, a disabled item says why); `useOnClickOutside`. The modal's typed name now goes through `Field`, and `Modal.css` drops its temporary copy of the form rules. `index.js` exports all of it. Two decisions for the record, from the delegates' reports: the kit keys the switch and the segmented control on `aria-pressed`; here they carry `aria-checked` (the right attribute for `role="switch"` and `role="radio"`) and the CSS keys on that. `Menu` is `role="menu"`, so Tab closes it; the bell's panel, which has its own head and foot controls, will want a `role="dialog"` variant when lane 1 builds it. Lint clean under jsx-a11y at error and the React Compiler rules; 1,041 tests pass; render-checked at `/design` in both themes. Next in the series: the shell components (app bar, Contents, account menu, bell, search, footer, live bar). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(frontend): the design system's controls, content and overlays (#364)
All checks were successful
CI / Backend lint (ruff) (pull_request) Successful in 56s
CI / Feedback site tests (pull_request) Successful in 51s
CI / Bot/backend version sync (pull_request) Successful in 52s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m50s
CI / Bot tests and audit (pull_request) Successful in 1m58s
CI / Frontend tests, audit, and build (pull_request) Successful in 4m38s
CI / Docker image build (pull_request) Successful in 5m11s
CI / Backend migration, tests, and audit (pull_request) Successful in 14m26s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 18m10s
abfef5809a
Lane 0, second PR. Twenty-six components on /design now, 138 states, each
with a test; nothing in the app uses the library yet.

Controls: Field, Select and Textarea (a real label, hint and error joined
by aria-describedby, aria-invalid); Toggle (role=switch; a disabled switch
says why); Chip and ChipButton; Segmented (a radiogroup with a roving
tabindex); Tabs and TabPanel (arrows, Home and End); InlineError;
AudiencePicker (#593's five audiences as one control; anything narrower
than the table in the GM tint); DateTime (the structured picker, CA-214: a
wall clock in the campaign's own time, quarter hours that never snap an
odd minute, the time waits on the day and says so).

Content: Card and Panel; List and ListRow (a clickable title, never a
clickable row); Label; Meter (role=meter); Fold; PersonDisc and Person (a
member's colour and initial, the GM mark, a person's pronouns and never a
character's); Doc, Section, KV and StatRow; Table, with the roll-table
look as a variant rather than every table's first column.

Feedback and overlays: SaveState (D40's four states, one live region so
the change is announced); Menu, MenuGroup and MenuItem (role=menu on an
anchored popover: Escape and Tab close and return focus, arrows and
Home/End move, outside click closes, a disabled item says why);
useOnClickOutside.

The modal's typed name now goes through Field, and Modal.css drops its
temporary copy of the form rules. index.js exports all of it.

Lint clean under jsx-a11y at error and the React Compiler rules; 1,041
tests pass; render-checked at /design in both themes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign in to join this conversation.
No description provided.