Skip to content

🎨 Palette: associate the shared gear Field label with its input - #507

Merged
jnnngs merged 2 commits into
mainfrom
claude/sharp-cannon-uznqv9
Sep 18, 2026
Merged

jnnngs merged 2 commits into
mainfrom
claude/sharp-cannon-uznqv9

Conversation

@jnnngs

@jnnngs jnnngs commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

What and why

💡 What: Field, the shared label wrapper used across the rifle/pellet forms in QuickCapture.tsx (quick score capture's add-gear flow) and Gear.tsx, rendered its <label> as a plain sibling of the <input> it labels — no htmlFor/id pairing. Fixed by wrapping the input inside the label instead, which gives it an implicit programmatic association (the same effect as htmlFor, with no id plumbing needed since Field's children is an arbitrary ReactNode).

🎯 Why: These are the Make/Model/Calibre/Power (rifle) and Brand/Model/Head size/Weight/Batch code (pellet) inputs used whenever someone adds gear — including mid-flow from Quick Capture, one of the app's highest-traffic screens. Every other input in the app already gets a real label association (per .jules/palette.md); this one component was the outlier.

Accessibility: A screen reader user focusing one of these inputs previously heard only the placeholder text (or nothing, once a value was typed) instead of the field name ("Make", "Head size (mm)", etc.). It also means clicking the label text now focuses its input, per normal browser label behaviour.

How you tested it

  • cd frontend && npm run check — passes (tsc -b)
  • cd frontend && npm run lint — passes
  • cd frontend && npx vitest run src/pages/__tests__/QuickCapture.test.tsx — 6/6 passing (Gear.tsx has no dedicated page test file)
  • Manual read-through confirmed every <Field> usage in both files wraps exactly one plain <input> (no nested comboboxes/multi-control children that implicit labelling could break)

Checklist

  • cd frontend && npm run check && npm run lint passes (full npm test/npm run build not run — see above for the scoped test run instead, per this task's scope)
  • I read the relevant sections of CLAUDE.md (Frontend conventions, Frontend Design System) and followed its conventions — no new tokens/classes added, reused existing utility classes
  • No unrelated refactoring, renames or comment additions in this diff

Notes for reviewers

Small, mechanical, single-component change (net +6/-6 lines across 2 files) — no visual change, since .block on the outer <label> preserves the original layout.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Gm6wVPhe2babySKKVDq5jL


Generated by Claude Code

Field was rendering the label as an unassociated sibling of the input
it labels, so a screen reader announced only the input's placeholder
(or nothing once typed) rather than the field name. Wrapping the input
in the label gives it an implicit association, matching what every
other input in the app already gets. Affects the rifle/pellet forms in
QuickCapture (quick score capture's add-gear flow) and Gear.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gm6wVPhe2babySKKVDq5jL
@jnnngs
jnnngs marked this pull request as ready for review September 18, 2026 16:15
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@jnnngs
jnnngs merged commit 84f5dee into main Sep 18, 2026
10 checks passed
@jnnngs
jnnngs deleted the claude/sharp-cannon-uznqv9 branch September 18, 2026 16:15
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.

2 participants