Feature 05 task 2: Core UI primitives #34

Member

Implements Feature 05 task 2 (d90b6698). Done-condition: web/src/ui provides Button, IconButton, Tag, Chip (removable, accessible), TextInput, Segmented (radiogroup + arrow keys), Toggle (role=switch, aria-checked, ON teal-600), Checkbox (native styled, grape checked), Slider, Card and ListRow, CSS Modules tokens only; Vitest asserts roles/keyboard/aria and >=44px hit areas; lint:colors/typecheck/test/build pass.

Evidence (developer-run): lint:colors, typecheck, npm test (12 files/46 tests) and build pass; headless-Chrome measurement confirmed hit boxes (IconButton 44/62, Toggle 44, Chip remove 44, segments 164x44, Checkbox label 44, Slider 340x44, buttons 48).

Implements Feature 05 task 2 (d90b6698). Done-condition: web/src/ui provides Button, IconButton, Tag, Chip (removable, accessible), TextInput, Segmented (radiogroup + arrow keys), Toggle (role=switch, aria-checked, ON teal-600), Checkbox (native styled, grape checked), Slider, Card and ListRow, CSS Modules tokens only; Vitest asserts roles/keyboard/aria and >=44px hit areas; lint:colors/typecheck/test/build pass. Evidence (developer-run): lint:colors, typecheck, npm test (12 files/46 tests) and build pass; headless-Chrome measurement confirmed hit boxes (IconButton 44/62, Toggle 44, Chip remove 44, segments 164x44, Checkbox label 44, Slider 340x44, buttons 48).
dev_agent added 1 commit 2026-10-03 16:24:16 -04:00
Add core UI primitives in web/src/ui
CI / ci (push) Successful in 2m32s
Independent review Codex gpt-6-sol high: CHANGES_REQUIRED (2 medium)
CI / ci (pull_request) Successful in 1m35s
d9a26b81ec
Button, IconButton, Tag, Chip, TextInput, Segmented, Toggle, Checkbox,
Slider, Card and ListRow, styled with CSS Modules over the design tokens.
Every interactive primitive keeps a hit area of at least 44 px; visually
smaller controls draw their face inside a larger hit box.

Vitest now injects CSS Modules into jsdom (css: true) so tests assert the
sizes the stylesheets declare, alongside roles, aria states and keyboard
behaviour (Segmented arrow keys, Toggle Space/Enter, Chip "Remove X").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review_agent left a comment
Member

Independent review — Codex gpt-6-sol, reasoning high

Verdict: CHANGES_REQUIRED
Reviewed SHA: d9a26b81ec3e92289b0204763b39b9bb19174e45

{
  "verdict": "CHANGES_REQUIRED",
  "reviewed_sha": "d9a26b81ec3e92289b0204763b39b9bb19174e45",
  "summary": "All listed primitives and exports are present. Static review found two interaction and state defects. Using --on-accent for the near-white check and an inline SVG for the remove icon is acceptable under the token and dependency rules. Color lint passed. npm was available, but typecheck, tests, and build could not complete because node_modules is absent (tsc and vitest were not found).",
  "findings": [
    {
      "id": "F1",
      "severity": "medium",
      "location": "web/src/ui/ListRow.tsx:9",
      "failure_case": "A ListRow with onClick and a trailing Toggle or action nests a button inside the row button. Clicking the trailing control also bubbles to the row, triggering both actions.",
      "evidence": "The trailing slot explicitly permits a toggle or action; lines 24 and 30 render that slot inside a button whenever onClick is supplied.",
      "suggested_correction": "Keep the row action and trailing interactive control as separate, non-nested controls, or reject that prop combination."
    },
    {
      "id": "F2",
      "severity": "medium",
      "location": "web/src/ui/Slider.tsx:14",
      "failure_case": "For min=0, max=1, value=2, the component computes a 200% fill while the native range input clamps its exposed value to 1. The rendered control and supplied state disagree.",
      "evidence": "Only max > min is validated before the fill percentage is computed from value.",
      "suggested_correction": "Fail fast when value is outside [min, max], and test the invalid bounds."
    }
  ]
}

Posted unaltered by review_agent. This is transport, not a second review.

## Independent review — Codex `gpt-6-sol`, reasoning high Verdict: **CHANGES_REQUIRED** Reviewed SHA: `d9a26b81ec3e92289b0204763b39b9bb19174e45` ```json { "verdict": "CHANGES_REQUIRED", "reviewed_sha": "d9a26b81ec3e92289b0204763b39b9bb19174e45", "summary": "All listed primitives and exports are present. Static review found two interaction and state defects. Using --on-accent for the near-white check and an inline SVG for the remove icon is acceptable under the token and dependency rules. Color lint passed. npm was available, but typecheck, tests, and build could not complete because node_modules is absent (tsc and vitest were not found).", "findings": [ { "id": "F1", "severity": "medium", "location": "web/src/ui/ListRow.tsx:9", "failure_case": "A ListRow with onClick and a trailing Toggle or action nests a button inside the row button. Clicking the trailing control also bubbles to the row, triggering both actions.", "evidence": "The trailing slot explicitly permits a toggle or action; lines 24 and 30 render that slot inside a button whenever onClick is supplied.", "suggested_correction": "Keep the row action and trailing interactive control as separate, non-nested controls, or reject that prop combination." }, { "id": "F2", "severity": "medium", "location": "web/src/ui/Slider.tsx:14", "failure_case": "For min=0, max=1, value=2, the component computes a 200% fill while the native range input clamps its exposed value to 1. The rendered control and supplied state disagree.", "evidence": "Only max > min is validated before the fill percentage is computed from value.", "suggested_correction": "Fail fast when value is outside [min, max], and test the invalid bounds." } ] } ``` --- Posted unaltered by `review_agent`. This is transport, not a second review.
dev_agent added 1 commit 2026-10-03 16:29:24 -04:00
Separate ListRow trailing control and fail fast on out-of-range Slider
Independent review Codex gpt-6-sol high: APPROVED (0 findings)
CI / ci (push) Successful in 1m30s
CI / ci (pull_request) Successful in 1m32s
92ffaae1de
ListRow with onClick now renders a container whose leading slot, title
and meta form one button, with the trailing slot as a sibling outside
it, so a trailing toggle or action is never nested in the row button
and never triggers the row's action.

Slider throws when value is outside [min, max] (including NaN) instead
of rendering a fill that disagrees with the clamped native input.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review_agent left a comment
Member

Independent review — Codex gpt-6-sol, reasoning high

Verdict: APPROVED
Reviewed SHA: 92ffaae1de3e8df50576e043bbd4b376c231f754

{
  "verdict": "APPROVED",
  "reviewed_sha": "92ffaae1de3e8df50576e043bbd4b376c231f754",
  "summary": "All listed primitives are exported, and the two prior findings are fixed: ListRow separates its trailing control from the row button, and Slider rejects out-of-range values. The tests cover roles, keyboard behavior, aria states, and hit areas using computed CSS. The Checkbox check uses the existing --on-accent token, and the inline SVG uses token-derived color; both are acceptable under the tokens-only rule. lint:colors passed. Typecheck, tests, and build could not run because this checkout lacks node_modules (tsc and vitest were not found).",
  "findings": []
}

Posted unaltered by review_agent. This is transport, not a second review.

## Independent review — Codex `gpt-6-sol`, reasoning high Verdict: **APPROVED** Reviewed SHA: `92ffaae1de3e8df50576e043bbd4b376c231f754` ```json { "verdict": "APPROVED", "reviewed_sha": "92ffaae1de3e8df50576e043bbd4b376c231f754", "summary": "All listed primitives are exported, and the two prior findings are fixed: ListRow separates its trailing control from the row button, and Slider rejects out-of-range values. The tests cover roles, keyboard behavior, aria states, and hit areas using computed CSS. The Checkbox check uses the existing --on-accent token, and the inline SVG uses token-derived color; both are acceptable under the tokens-only rule. lint:colors passed. Typecheck, tests, and build could not run because this checkout lacks node_modules (tsc and vitest were not found).", "findings": [] } ``` --- Posted unaltered by `review_agent`. This is transport, not a second review.
approver_agent merged commit 02f1dd6491 into feature/64e5bb19-c9a2-4c6a-8f0c-aceae43fb732-frontend-foundation 2026-10-03 16:35:02 -04:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Maniacs_Mansion/MealQuest#34