Slider
Use slider with the current published Askr packages.
@askrjs/ui/slider0.0.13@askrjs/themes/slider0.0.13
How to use slider
Slider should use the standard themed surface unless the application is deliberately implementing its own design system on top of @askrjs/ui.
- Import the themed component from @askrjs/themes/components; use @askrjs/ui directly only when building a custom visual system.
- Keep slider labels, state, and application actions visible at the call site instead of styling internal DOM nodes.
- Verify keyboard behavior, focus movement or return, disabled state, and both standard themes.
import { Field, FieldLabel, Slider } from '@askrjs/themes/components';
<Field>
<FieldLabel for="capacity">Capacity: {capacity()}</FieldLabel>
<Slider id="capacity" min={1} max={100} value={[capacity()]} />
</Field>Purpose
Drag a thumb along a track to pick a number within `min`/`max` — that's what `Slider` renders and manages, from volume controls to price filters. Pointer dragging, keyboard stepping, and value snapping are all handled internally, so you never have to write pointer-move math by hand. Multiple parts (`SliderTrack`, `SliderRange`, `SliderThumb`) share state through a compound id rather than props drilling.
Install and import
Install `@askrjs/ui` for the behavior and `@askrjs/themes` for the default track/range/thumb visuals, then import from `@askrjs/ui/slider` and `@askrjs/themes/slider`. Both subpaths are real exports, so there's no need to pull in the package roots just to use a slider.
Live examples
The examples show single-thumb sliders at different `min`, `max`, and `step` configurations, including a disabled variant. Each one is built from the same four parts — `Slider`, `SliderTrack`, `SliderRange`, `SliderThumb` — so you can trace exactly which prop changed the behavior you're looking at.
Anatomy
`Slider` is the state-owning root; inside it you compose `SliderTrack` (the full-length background), `SliderRange` (the filled portion between the minimum and the current value), and `SliderThumb` (the draggable, focusable handle). All three children are plain `div` wrappers with no required props beyond what `BoxProps` already gives you.
State model
The numeric `value` can be left uncontrolled with `defaultValue` or driven externally through `value` and `onValueChange`, alongside `min`, `max`, `step`, `orientation` (`horizontal` or `vertical`), and `disabled`. Dragging the thumb or pressing arrow keys calls the same internal setter that feeds `onValueChange`, so there's no separate internal-vs-external value to reconcile. A per-slider registry keyed by `sliderId` tracks the track and thumb DOM nodes needed for pointer math.
Keyboard and accessibility
The thumb carries `role="slider"` with `aria-valuenow`, `aria-valuemin`, `aria-valuemax`, and `aria-orientation` kept in sync automatically, matching the `SLIDER_A11Y_CONTRACT` export. Dragging is handled with `pointermove`/`pointerup` listeners attached only while a drag is active, and every drag ends by returning focus to the thumb so keyboard users can immediately take over with arrow keys.
Styling and tokens
Track, range, and thumb each expose `data-slot` for targeted styling, and the root forwards `data-disabled` and `data-orientation` so vertical sliders and disabled states can be styled without JavaScript branching. `@askrjs/themes/slider` ships sensible defaults for all of this; override the CSS custom properties rather than fighting the generated class names.
API
Beyond the value props, `Slider` takes `id` and `name` — set `name` if you want the current value to participate in a surrounding `<form>`. Values are snapped to the nearest valid `step` before `onValueChange` fires, and if `max` is configured at or below `min` the library quietly falls back to `min + step` rather than producing a zero-width or inverted track.
Edge cases
Dragging outside the track's bounding box still resolves to a valid value — pointer coordinates are clamped through `min`/`max` before being snapped, so users don't lose the drag by moving the cursor too far. Because listeners are attached per active drag and torn down on `pointerup`, unmounting a `Slider` mid-drag doesn't leave stray global listeners behind.
Related pages
For a fixed, non-interactive value indicator rather than an input, use Progress instead — Slider is specifically for values the user changes. If you need a numeric input that also supports typing an exact value, pair it with Input rather than trying to make the thumb double as a text field.