Skip to content

feat(slider): add Slider, with iOS's knob, Material 3's handle or a range input - #81

Merged
elik56a merged 3 commits into
masterfrom
feat/slider
Oct 29, 2026
Merged

elik56a merged 3 commits into
masterfrom
feat/slider

Conversation

@eliyahu-kriel

Copy link
Copy Markdown
Collaborator

What

A new Slider component that looks native in each design:

iOS Material 3 Web
White 28pt knob with a shadow on a thin 4pt track (UISlider) 4dp bar handle with gaps on a 16dp track, stop dots, a value bubble while dragging; the handle narrows when pressed 18px dot on a 6px track, a pointer cursor, and a halo on hover and focus that grows while pressed
<Slider value={volume} onChange={setVolume} minimumIcon={<Text>🔈</Text>} maximumIcon={<Text>🔊</Text>} />
<Slider range min={0} max={600} step={10} value={price} onChange={setPrice} formatValue={(v) => `$${v}`} />
<Slider marks={[{ value: 0, label: '0°C' }, { value: 37, label: '37°C' }, { value: 100, label: '100°C' }]} snapToMarks valueLabel="always" />

Features

  • Callbacks: onChange fires once on release, or on a key or screen-reader step. onValueChanging fires on every step of a drag, for haptics and live previews. This matches the library's wheel convention. Tapping the current value fires neither.
  • Values: min, max and step (step={0} for any value). range gives two thumbs: a touch grabs the nearest one, and they can't cross.
  • Marks:
    • showSteps draws a dot per step, and drops them when they'd be too close together.
    • marks takes dots with optional labels under the track.
    • snapToMarks restricts the value to the marks, like MUI's step={null}.
  • Value bubble: valueLabel is 'never' | 'drag' | 'always'. 'always' keeps room above the track for it.
  • Other props: formatValue, minimumIcon / maximumIcon, disabled, and slot styles (container track activeTrack thumb mark markLabel valueLabel valueLabelText).
  • Accessibility: each thumb is adjustable. Arrow keys step it, Page Up / Page Down move a tenth of the range, and Home / End jump to the ends. The touch area is 44pt tall.
  • RTL: the track fills from the right.

Shared with ColorPicker

These moved into core, and ColorPicker's sliders and pad use them now:

  • useTrackPan: moved from color; it now takes options and adds onStart and onEnd.
  • adjustableProps: one helper for the adjustable role, screen-reader actions and keys.
  • Track math: clamp, clamp01 and toFraction.
  • Constants: the knob (KNOB_SIZE, KNOB_COLOR, KNOB_SHADOW), TOUCH_TARGET, A11Y_ACTION / ADJUSTABLE_ACTIONS, and the Page Up / Page Down keys.

Docs and showcase

  • Slider page: live examples, a prop playground and a props table. It's registered in the catalog, so it also appears in the sidebar and the example app's drawer.
  • Other updates: the API reference, the designs, styling and TypeScript guides, the AI cheat sheet, the README, the home page, the hero text, and the SEO descriptions and keywords.
  • Showcase: a new "Display & text" screen. Brightness and text size preview live while dragging, text size snaps to labelled marks, and focus hours are a range.

Tests

pnpm lint && pnpm typecheck && pnpm test pass (676 tests), and so do pnpm build and pnpm docs:build. New tests cover:

  • the slider utils: snapping, segments, marks, nearest thumb, halo level and mark stepping;
  • Slider itself: drag then commit, keys and screen-reader actions, range ordering, controlled values, the Material bubble, disabled, snap-to-marks, and the always-on bubble;
  • adjustableProps, useTrackPan's new onStart / onEnd, the track math, and the showcase utils.

Writing the tests caught a bug, now fixed: a range's end thumb could be dragged below its start thumb.

I haven't checked it by hand on a device or in a browser yet.

🤖 Generated with Claude Code

elik56a and others added 3 commits October 29, 2026 22:02
…ange input

Slider picks a number by tapping or dragging along a track, drawn each design's
way: iOS's white knob on a thin track, Material 3's slim handle with gaps, stop
dots and a value bubble, or a browser's range input with a hover and press halo.
onChange fires on release and onValueChanging on every step of a drag. It takes
min, max and step, two thumbs with range, step dots, labelled marks and
snapToMarks, a value bubble while dragging or always, icons beside the track,
keyboard and screen-reader steps, and RTL.

The track pan, the adjustable a11y and key props, and the knob move into core,
shared with ColorPicker's sliders. The showcase gains a Display & text screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	package.json
#	website/docusaurus.config.ts
…re constants and types

EDGE_TOLERANCE and CROSS_WEIGHT move to core.constants and WebElement to
core.types, as the repo keeps magic values and types; keyboard.utils keeps only
its functions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@elik56a
elik56a merged commit 8f88b00 into master Oct 29, 2026
5 checks passed
@github-actions github-actions Bot mentioned this pull request Oct 29, 2026
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