fix(a11y): put role=slider on handles, not the wrapper (D5) - #17
Conversation
Move value attributes onto each thumb so range mode exposes a single aria-valuenow per handle and axe nested-interactive no longer fires. Co-authored-by: Cursor <cursoragent@cursor.com>
📝 WalkthroughWalkthroughThe numeric slider now places slider semantics on each handle instead of the wrapper. Handle ARIA values update with slider changes, and disabled handles expose synchronized disabled state and tab order. Keyboard listeners operate on active handles. Playwright tests cover single, range, and disabled sliders in light and dark themes, including axe checks and keyboard updates. Documentation now describes setup, semantics, and test coverage. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
components/numeric-slider/numeric-slider.js (1)
269-275: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winPrevent range handles from swapping values on
HomeandEnd.When
Endruns on the min handle,setValue([max, currentMax])reorders the range. WhenHomeruns on the max handle,setValue([currentMin, min])also reorders the range. Clamp the focused handle to the other handle instead. Add regression coverage for both cases.Proposed fix
if (this.config.type === 'range' && handleType === 'min') { this.setValue([this.config.min, this.values[1]], 'min'); } else if (this.config.type === 'range' && handleType === 'max') { - this.setValue([this.values[0], this.config.min], 'max'); + this.setValue([this.values[0], this.values[0]], 'max'); ... if (this.config.type === 'range' && handleType === 'min') { - this.setValue([this.config.max, this.values[1]], 'min'); + this.setValue([this.values[1], this.values[1]], 'min'); } else if (this.config.type === 'range' && handleType === 'max') { this.setValue([this.values[0], this.config.max], 'max');🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/numeric-slider/numeric-slider.js` around lines 269 - 275, The range keyboard handling in handleKeyDown must prevent Home and End from swapping handle values: clamp the focused min handle to the current max on End, and the focused max handle to the current min on Home, while preserving normal behavior for other keys and single sliders. Add regression tests covering both range-handle cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@components/numeric-slider/numeric-slider.js`:
- Around line 269-275: The range keyboard handling in handleKeyDown must prevent
Home and End from swapping handle values: clamp the focused min handle to the
current max on End, and the focused max handle to the current min on Home, while
preserving normal behavior for other keys and single sliders. Add regression
tests covering both range-handle cases.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 92dc4096-dc3c-402c-b28a-5d3d4140c2ba
📒 Files selected for processing (4)
components/numeric-slider/README.mdcomponents/numeric-slider/numeric-slider.jscomponents/numeric-slider/test.htmltests/numeric-slider-a11y.spec.js
Summary
Closes #10 ([a11y][D5]). Each slider handle is now the
role="slider"control; the wrapper is presentational only. Range mode exposes a single-numberaria-valuenowper thumb.Changes
In
components/numeric-slider/:role, notabindex, no value attributesrole="slider",aria-valuemin/max/now/valuetext,aria-orientation="horizontal",aria-labelaria-disabled="true"+tabindex="-1"(alongside nativedisabled)Note for consumers: DOM/ARIA for the slider changed (value attrs moved from
.numeric-slider-wrapperonto.numeric-slider-handle). Selectors that read wrapper aria attributes will need updating.Test plan
npm test— Playwright light + dark: single/range role placement, single-numberaria-valuenow, disabled attrs, keyboard updates, scoped axe (nonested-interactive)Made with Cursor