Skip to content

fix(Slider): keep max reachable when step does not divide the range - #6399

Open
korkt-kim wants to merge 1 commit into
facebook:mainfrom
korkt-kim:fix/slider-step-endpoint
Open

korkt-kim wants to merge 1 commit into
facebook:mainfrom
korkt-kim:fix/slider-step-endpoint

Conversation

@korkt-kim

Copy link
Copy Markdown
Contributor

User impact

With min={0}, max={100} and step={3}, Slider stops at 99 when dragged to the right endpoint or operated with End. Its accessible maximum is still 100, but neither input method can select it.

Problem and solution fit

The value is rounded to the step grid before it is clamped. At the endpoint, 100 rounds to 99; clamping leaves it there because it is already within bounds. A second edge case appears when the current value is an off-grid maximum: subtracting a step and then rounding takes 100 → 97 → 96, skipping the adjacent value 99.

The fix includes the explicit maximum in nearest-value selection and makes arrow keys choose the adjacent step in their direction. The final interval may be shorter than step: 96 → 99 → 100, and back through 99 rather than skipping it.

Expected behavior and authority

  • Slider documents max as its maximum value. The existing implementation already permits an off-grid maximum when rounding overshoots and clamping brings it back: min=0, max=100, step=6 reaches 100 today. This restores consistent endpoint reachability rather than making it depend on the remainder.
  • The APG Slider pattern assigns End to the last allowed value. This fix treats the explicit max as allowed; it does not claim that WCAG requires this particular step policy or that it matches native HTML range sanitization.

Smallest restoration

Slider.tsx: share nearest-step/endpoint selection across pointer and keyboard updates, and select the adjacent step before applying bounds on arrow-key movement. Existing decimal cleanup, range separation, and callback handling stay in place. No new props, styling, dependencies, or default values.

Three regression tests cover single-value keyboard/callback behavior, range separation and ARIA bounds, and pointer dragging to both 100 and the neighboring 99.

Evidence

Reproduce

  1. Open Custom Step with step=3.
  2. Drag to the right endpoint: the value stops at 99.
  3. Focus the thumb and press End: it still reads 99, with aria-valuemax="100".
  4. On this branch, open the same story/args locally: both actions reach 100. ArrowLeft then ArrowRight visits 99 → 100.

AS-IS / TO-BE: real Chrome 153 keyboard and mouse input, published Storybook versus this branch at b46a9c0ec8. The diagnostic panels are injected by the probe; their values are read from the live DOM after each action. They are not product UI.

AS-IS TO-BE
Published Slider: End and right-endpoint drag both stop at 99 while aria-valuemax is 100 Fixed Slider: End and drag reach 100; arrow keys visit 99 and return to 100

Before recording · After recording · Probe, raw observations, and test logs

Representative unchanged keyboard paths, checked on both builds:

Configuration End → ArrowLeft
min=0, max=100, step=10 100 → 90
min=0, max=100, step=6 100 → 96
min=1, max=100, step=3 100 → 97
min=-1, max=100, step=3 100 → 98

The published deployment is not asserted to be the exact base commit. For regression proof, the same new tests were run with a temporary Vite hook substituting only Slider's source:

Source under test Result
Base f138ed997b 3 failed, 65 passed — new tests receive 99 instead of 100
Endpoint fix, but old currentValue ± step arrow logic 2 failed, 66 passed — keyboard tests receive 96 instead of 99
This fix 68 passed

The probe configs and logs are linked above. No live source was swapped, and the tested source hashes match the committed files. These are scoped Chromium checks, not a full assistive-technology or cross-browser audit.

Scope

  • One endpoint-reachability defect and its adjacent-step consequence are addressed.
  • No unrelated API, visual, layout, or cleanup changes are included.
  • The off-grid endpoint policy is explicit above; no new public API is introduced.
  • Public text and artifacts contain no internal Meta context. Evidence lives on a separate fork branch; this PR changes only Slider, its tests, and a changeset.

Testing

  • pnpm exec vitest run packages/core/src/Slider/Slider.test.tsx — 68 passed.
  • Full test suite — pnpm test --maxWorkers=4 — 17,113 passed, 50 skipped (GNU cp on PATH; see note below).
  • pnpm -F @astryxdesign/core typecheck — passed.
  • pnpm -F @astryxdesign/core typecheck:docs — passed.
  • pnpm build — passed.
  • pnpm lint:strict — 0 errors; 84 warnings outside Slider.
  • Real-browser pointer/keyboard checks and unchanged paths above.

The first full run on macOS passed 17,105 tests but hit two unrelated setup-fixture failures because BSD cp does not support --reflink=auto. The entire suite was rerun with GNU cp 9.11 on PATH using pnpm test --maxWorkers=4; no test exclusions or repository fixes were added for that environment issue.

@vercel

vercel Bot commented Sep 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Sep 20, 2026 7:08pm UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Sep 20, 2026
@astracat-bot

astracat-bot Bot commented Sep 20, 2026

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
Waiting for review (for maintainers only) Sep 22, 2026, 1:38 AM UTC

@github-actions github-actions Bot added community Authored by a community contributor (not on the eng/design team) needs:code-review High-risk change (new package/component/API) — needs human code review before merge labels Sep 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot. community Authored by a community contributor (not on the eng/design team) needs:code-review High-risk change (new package/component/API) — needs human code review before merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant