Repository navigation
feat(ui): enlarge checkbox hit area and add hover state - #9867
Conversation
Checkboxes take clicks within 6px of the visible box, giving the small list checkbox a 24px target. Hovering the label, box, or surrounding area strengthens the border or shifts the checked fill; disabled and invalid controls are unchanged.
lstein
left a comment
There was a problem hiding this comment.
Reviewed at a0b7767 and tested in the UI: the larger hit area and the hover state work as described. The two browser test files pass locally (20/20).
I tried to break it and found no blockers. These held up:
- Disabled checkboxes: Chakra's
_hoveralready excludes:disabled/[data-disabled]. A busyListItemrow just stops toggling from the surrounding area. - Clicks in the outset reach the input through the
<label>root. InListItem, a click about 8px past the box still goes to the primary button, and no row-levelonClicksees the outset. - Row overlap: the smallest row is
compact(minH: '7', 28px), taller than the 24px target. Spacing isn't rebased, so the outset really is 7px (checked in the browser). - The workflow node footer is
nodrag, so the larger area can't start a node drag.ClearDialog's acknowledge checkbox stays 8px clear of the type-to-confirm label. - Reduced motion: the transition uses the
fasttoken, which becomes 1ms.
Non-blocking findings:
-
The outset can add scroll height. The
::beforeis absolutely positioned, so it counts toward a scroll container's scrollable overflow on the bottom and right edges. Repro: anoverflow:autobox 40px tall holding a 28px spacer and a label-lesssmcheckbox givesscrollHeight46 vsclientHeight40, so a scrollbar appears that wasn't there before. No current call site hits this; the tightest is theOrphanedModelsDialogrow (p="2"), with 1px to spare. Worth a line in the recipe comment for future checkboxes placed at the edge of a scroller with no padding. -
Checked + invalid still changes on hover. The checked-hover selector
&:is([data-state=checked], [data-state=indeterminate])has no:not([data-invalid]). Hovering a checked invalid checkbox shifts its fill fromrgb(220,38,38)to the same red at 90% opacity, which contradicts "invalid controls are unchanged" in the description and the test file comment. No caller passesinvalidto a checkbox today. Fix: add:not([data-invalid])and a checked+invalid sample inCheckboxHover.browser.test.tsx. -
"Never reaches a neighbour" depends on paint order as well as spacing. When a neighbour is closer than 7px, a positioned element after the checkbox wins the overlap: a Chakra
Button4px away (gap="1") still got the click. A non-positioned element before the checkbox loses its edge pixels to the outset. Nothing is that close today; the closest isPositivePromptActions(image at 8px). It only matters if someone later puts a checkbox in a tight group.
Exclude invalid checked and indeterminate controls from hover styling. Cover error appearance when hovering labels and surrounding hit areas.
Summary
Checkboxes only toggled from their visible box, which is 12px in list rows such as the Model Manager. Every checkbox now accepts clicks within 6px of its box: an invisible absolutely positioned
::beforeon the control, inside the<label>root. The small list checkbox gets a 24px target (WCAG 2.5.8); 6px stays under the 8px minimum spacing between neighbouring controls.Checkboxes also gain a hover state so the larger target reads as clickable. Hovering the label, the box, or the surrounding area strengthens an unchecked border or shifts a checked fill. Disabled and invalid controls are unchanged, and the transition follows reduced motion.
Both changes live in one theme-level checkbox slot recipe, so no call sites change.
Related Issues / Discussions
Closes #9785
QA Instructions
pnpm check:release: passed. The final change (hover excludes invalid controls, plus a comment) landed after that run;pnpm lintand the focused browser tests below passed on the final change.pnpm test:browser src/platform/ui/list/ListItem.browser.test.tsx src/platform/ui/theme/CheckboxHover.browser.test.tsx: passes.Review
solidvariant only, the default every checkbox uses.Checklist
What's Newcopy (if doing a release after this PR)Need help on this PR? Tag
@codesmith-botwith what you need.