Skip to content

feat(Switch): add on/off toggle control (16th atom, D21)#153

Merged
dgraciac merged 1 commit into
mainfrom
feat/switch
Jul 15, 2026
Merged

feat(Switch): add on/off toggle control (16th atom, D21)#153
dgraciac merged 1 commit into
mainfrom
feat/switch

Conversation

@dgraciac

Copy link
Copy Markdown
Member

What

Adds Switch, the 16th Pharos atom — a single on/off toggle (the shadcn Switch contract) over Base UI's Switch. It completes the boolean form-control family opened by Checkbox (D20): Checkbox → Switch → Radio.

Built as the exact sibling of the Checkbox (PR #148): same wrapping pattern, same checked / onCheckedChange / disabled API, same label-less design, same two-stop focus ring.

Design (D21)

  • role="switch" (ARIA APG toggle semantics), Space to toggle, hidden form input — not a restyled checkbox.
  • Sibling API to Checkbox, minus a third state: a toggle is binary, so no indeterminate (Base UI's Switch exposes none either).
  • Label-less (Escuela 1, D11): pair with <label htmlFor>. Error via aria-invalid (inset 1px semantic.error ring — no layout shift). No size axis in v1 (shadcn ships none).
  • On track reuses neutral-900 (the Checkbox checked fill) for one "active control" color across the family; off track neutral-300 with a white/neutral-500 thumb as the perceivable state indicator (WCAG 1.4.11).
  • Fully token-derived geometry (40×24 track = spacing-10×spacing-6, 16px thumb = spacing-4, spacing-1 padding → clean spacing-4 travel) — no hardcoded pixels (NON-NEGOTIABLE chore: scaffold pharos-react (phase 1B.1-1B.3) #1). No icon dependency (the thumb is a plain <span>).

Changes

  • src/components/Switch.{tsx,module.css,stories.tsx} + tests/Switch.test.tsx (8 unit tests).
  • Export in src/index.ts; D21 entry in NAMING-decisions.md; minor changeset.
  • Rule chore(deps): batch apply open dependabot bumps #8 (harness): Settings form gains a "Send me a weekly digest" switch; settings.spec.ts toggles it (+ label-click).

Verification (all local, green)

  • pnpm build (+ verify:dist-types), pnpm typecheck, pnpm lint
  • pnpm test205/205 (Switch 8/8)
  • pnpm test:storybook (axe a11y) — 102/102 (+3 Switch stories)
  • pnpm build-storybook
  • pnpm --filter @examples/saas-demo test:e2e25/25 (incl. toggles the weekly-digest switch)

Notes

  • New atom → Chromatic will request approval of the new Switch snapshots (normal, reviewer action).
  • The unit Select 'closes on Escape…' flake is pre-existing (green in CI) — unrelated.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AgnovjGivnndpV7Yzt6AmY

Switch is the shadcn "Switch" contract over Base UI's Switch — a role="switch"
button + hidden form input, Space to toggle, shared Button/Input/Checkbox focus
ring. Second of the boolean form-control family, completing it next to Checkbox
(D20): Checkbox -> Switch -> Radio.

- Sibling API to Checkbox (checked/onCheckedChange/disabled), label-less
  (Escuela 1, D11): pair with <label htmlFor>; error via aria-invalid. No size
  axis in v1 (shadcn ships none). No indeterminate — a toggle is binary.
- role="switch" (ARIA APG toggle), not a restyled checkbox. On track reuses
  neutral-900 (the Checkbox checked fill) for one "active control" color; off
  track neutral-300 with a white/neutral-500 thumb as the perceivable state
  indicator (WCAG 1.4.11). Geometry fully token-derived (40x24 track, 16px
  thumb, spacing-4 travel) — no hardcoded pixels, no icon dep (thumb is a span).
- Stories (WithLabel + States matrix + Invalid), unit tests (8),
  NAMING-decisions D21, changeset minor.
- Harness (rule #8): Settings form gains a "Send me a weekly digest" switch;
  settings.spec toggles it (+ label-click) — 25 e2e specs.

Verified: build + dist-types, typecheck, lint, unit (Switch 8/8, 205 total),
test:storybook a11y (102 stories, +3), build-storybook, e2e 25/25.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AgnovjGivnndpV7Yzt6AmY
@chromatic-com

chromatic-com Bot commented Jul 15, 2026

Copy link
Copy Markdown

Tip

All tests passed and all changes approved!

🟢 UI Tests: 3 visual and accessibility changes accepted as baselines
🟢 UI Review: Approved by David Gracia
Storybook icon Storybook Publish: 102 stories published

@dgraciac
dgraciac merged commit 414d5a0 into main Jul 15, 2026
12 checks passed
@dgraciac
dgraciac deleted the feat/switch branch July 15, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant