Slider
A range input you style yourself, with one thumb or several
import { Slider } from "@nyte-ai/ui/slider";A value picked by dragging along a track. No Nyte styling here.
Usage
- Name the control. Use
Slider.Labelwhen the label is visible, oraria-labelon eachSlider.Thumbwhen it is not. valuewithonValueChangecontrols the slider.defaultValueleaves it uncontrolled.- A range slider takes an array for
valueordefaultValueand oneSlider.Thumbper entry. For server rendering, give each thumb an explicitindex. stepsnaps the value.largeStepsets the jump for Page Up, Page Down, and Shift with an arrow key.- Set
orientation="vertical"onSlider.Rootfor a vertical slider. - Render tick marks yourself, positioning each along the track as a percentage of the value range.
Pair them with
stepso the thumb lands on each one.
Anatomy
<Slider.Root>
<Slider.Label />
<Slider.Value />
<Slider.Control>
<Slider.Track>
<Slider.Indicator />
<Slider.Thumb />
</Slider.Track>
</Slider.Control>
</Slider.Root>Examples
A labeled slider
<Slider.Root defaultValue={0.7} min={0} max={1} step={0.1}>
<div>
<Slider.Label>Temperature</Slider.Label>
<Slider.Value />
</div>
<Slider.Control>
<Slider.Track>
<Slider.Indicator />
<Slider.Thumb />
</Slider.Track>
</Slider.Control>
</Slider.Root>Without a visible label, name the thumb instead.
<Slider.Thumb aria-label="Volume" />Controlled
const [volume, setVolume] = useState(0.5);
<Slider.Root value={volume} onValueChange={setVolume} min={0} max={1} step={0.1}>
<Slider.Label>Volume</Slider.Label>
<Slider.Control>
<Slider.Track>
<Slider.Indicator />
<Slider.Thumb />
</Slider.Track>
</Slider.Control>
</Slider.Root>;A range
thumbCollisionBehavior decides what two thumbs do when a drag pushes one into the other. "push"
is the default, "swap" trades their places when one is dragged past the other, and "none" stops
them from passing.
<Slider.Root defaultValue={[25, 75]} thumbCollisionBehavior="swap">
<Slider.Label>Price range</Slider.Label>
<Slider.Control>
<Slider.Track>
<Slider.Indicator />
<Slider.Thumb index={0} aria-label="Minimum price" />
<Slider.Thumb index={1} aria-label="Maximum price" />
</Slider.Track>
</Slider.Control>
</Slider.Root>Thumb alignment
thumbAlignment="edge" insets the thumb so its edge lines up with the edge of the control at min
and max, instead of overflowing the control the way the default "center" does.
"edge-client-only" does the same but renders after hydration, which costs less bundle.
<Slider.Root thumbAlignment="edge" />In a form
<Slider.Root name="volume">
<Slider.Label>Volume</Slider.Label>
<Slider.Control>
<Slider.Track>
<Slider.Indicator />
<Slider.Thumb />
</Slider.Track>
</Slider.Control>
</Slider.Root>Props
The reference tables below come from Base UI, MIT, © Material-UI SAS.
Root
Groups all parts of the slider.
Renders a <div> element.
Root Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| name | string | - | Identifies the field when a form is submitted. |
| defaultValue | number | number[] | - | The uncontrolled value of the slider when it's initially rendered. To render a controlled slider, use the value prop instead. |
| value | number | number[] | - | The value of the slider. For range sliders, provide an array with one value per thumb. |
| onValueChange | ((value: number | number[], eventDetails: Slider.Root.ChangeEventDetails) => void) | - | Callback function that is fired when the slider's value changed.
Receives the new value as the first argument; the originating event is
available as eventDetails.event. The value is also reflected on
eventDetails.event.target.value for form integration. The eventDetails.reason indicates what triggered the change: 'input-change' when the hidden range input emits a change event (for example, via form integration)'track-press' when the control track is pressed'drag' while dragging a thumb'keyboard' for keyboard input'none' when the change is triggered without a specific interaction |
| onValueCommitted | ((value: number | number[], eventDetails: Slider.Root.CommitEventDetails) => void) | - | Callback function that is fired when a value change is committed.
Does not fire if the value did not change, or if the change was canceled.
Warning: This is a generic event, not a change event. The eventDetails.reason indicates what triggered the commit: 'drag' while dragging a thumb'track-press' when the control track is pressed'keyboard' for keyboard input'input-change' when the hidden range input emits a change event (for example, via form integration)'none' when the commit occurs without a specific interaction |
| form | string | - | Identifies the form that owns the slider inputs. Useful when the slider is rendered outside the form. |
| locale | Intl.LocalesArgument | - | The locale used by Intl.NumberFormat when formatting the value.
Defaults to the user's runtime locale. |
| thumbAlignment | 'center' | 'edge' | 'edge-client-only' | 'center' | How the thumb(s) are aligned relative to Slider.Control when the value is at min or max: center: The center of the thumb is aligned with the control edgeedge: The thumb is inset within the control such that its edge is aligned with the control edgeedge-client-only: Same as edge but renders after React hydration on the client, reducing bundle size in return |
| thumbCollisionBehavior | 'push' | 'swap' | 'none' | 'push' | Controls how thumbs behave when they collide during pointer interactions. 'push' (default): Thumbs push each other without restoring their previous positions when dragged back.'swap': Thumbs swap places when dragged past each other.'none': Thumbs cannot move past each other; excess movement is ignored. |
| step | number | 1 | The granularity with which the slider can step through values. (A "discrete" slider.)
The min prop serves as the origin for the valid values.
We recommend (max - min) to be evenly divisible by the step. |
| largeStep | number | 10 | The granularity with which the slider can step through values when using Page Up/Page Down or Shift + Arrow Up/Arrow Down. |
| minStepsBetweenValues | number | 0 | The minimum steps between values in a range slider. |
| min | number | 0 | The minimum allowed value of the slider. Should not be equal to max. |
| max | number | 100 | The maximum allowed value of the slider. Should not be equal to min. |
| format | Intl.NumberFormatOptions | - | Options to format the value. |
| disabled | boolean | false | Whether the slider should ignore user interaction. |
| orientation | Orientation | 'horizontal' | The component orientation. |
| className | string | ((state: Slider.Root.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: Slider.Root.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: Slider.Root.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Root Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-dragging | - | Present while the user is dragging. |
| data-orientation | 'horizontal' | 'vertical' | Indicates the orientation of the slider. |
| data-disabled | - | Present when the slider is disabled. |
| data-valid | - | Present when the slider is in a valid state (when wrapped in Field.Root). |
| data-invalid | - | Present when the slider is in an invalid state (when wrapped in Field.Root). |
| data-dirty | - | Present when the slider's value has changed (when wrapped in Field.Root). |
| data-touched | - | Present when the slider has been touched (when wrapped in Field.Root). |
| data-focused | - | Present when the slider is focused (when wrapped in Field.Root). |
Label
An accessible label that is automatically associated with the slider thumbs.
Renders a <div> element.
Label Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | ((state: Slider.Root.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: Slider.Root.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: Slider.Root.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Value
Displays the current value of the slider as text.
Renders an <output> element.
Value Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ((formattedValues: string[], values: number[]) => React.ReactNode) | null | - | - |
| className | string | ((state: Slider.Value.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: Slider.Value.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: Slider.Value.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Value Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-dragging | - | Present while the user is dragging. |
| data-orientation | 'horizontal' | 'vertical' | Indicates the orientation of the slider. |
| data-disabled | - | Present when the slider is disabled. |
| data-valid | - | Present when the slider is in a valid state (when wrapped in Field.Root). |
| data-invalid | - | Present when the slider is in an invalid state (when wrapped in Field.Root). |
| data-dirty | - | Present when the slider's value has changed (when wrapped in Field.Root). |
| data-touched | - | Present when the slider has been touched (when wrapped in Field.Root). |
| data-focused | - | Present when the slider is focused (when wrapped in Field.Root). |
Control
The clickable, interactive part of the slider.
Renders a <div> element.
Control Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | ((state: Slider.Control.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: Slider.Control.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: Slider.Control.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Control Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-dragging | - | Present while the user is dragging. |
| data-orientation | 'horizontal' | 'vertical' | Indicates the orientation of the slider. |
| data-disabled | - | Present when the slider is disabled. |
| data-valid | - | Present when the slider is in a valid state (when wrapped in Field.Root). |
| data-invalid | - | Present when the slider is in an invalid state (when wrapped in Field.Root). |
| data-dirty | - | Present when the slider's value has changed (when wrapped in Field.Root). |
| data-touched | - | Present when the slider has been touched (when wrapped in Field.Root). |
| data-focused | - | Present when the slider is focused (when wrapped in Field.Root). |
Track
Contains the slider indicator and represents the entire range of the slider.
Renders a <div> element.
Track Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | ((state: Slider.Track.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: Slider.Track.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: Slider.Track.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Track Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-dragging | - | Present while the user is dragging. |
| data-orientation | 'horizontal' | 'vertical' | Indicates the orientation of the slider. |
| data-disabled | - | Present when the slider is disabled. |
| data-valid | - | Present when the slider is in a valid state (when wrapped in Field.Root). |
| data-invalid | - | Present when the slider is in an invalid state (when wrapped in Field.Root). |
| data-dirty | - | Present when the slider's value has changed (when wrapped in Field.Root). |
| data-touched | - | Present when the slider has been touched (when wrapped in Field.Root). |
| data-focused | - | Present when the slider is focused (when wrapped in Field.Root). |
Indicator
Visualizes the current value of the slider.
Renders a <div> element.
Indicator Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | ((state: Slider.Indicator.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: Slider.Indicator.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: Slider.Indicator.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Indicator Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-dragging | - | Present while the user is dragging. |
| data-orientation | 'horizontal' | 'vertical' | Indicates the orientation of the slider. |
| data-disabled | - | Present when the slider is disabled. |
| data-valid | - | Present when the slider is in a valid state (when wrapped in Field.Root). |
| data-invalid | - | Present when the slider is in an invalid state (when wrapped in Field.Root). |
| data-dirty | - | Present when the slider's value has changed (when wrapped in Field.Root). |
| data-touched | - | Present when the slider has been touched (when wrapped in Field.Root). |
| data-focused | - | Present when the slider is focused (when wrapped in Field.Root). |
Thumb
The draggable part of the slider at the tip of the indicator.
Renders a <div> element and a nested <input type="range">.
Thumb Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| aria-valuetext | string | - | A string value forwarded to the aria-valuetext attribute of the input.
Ignored when getAriaValueText is provided. |
| getAriaLabel | ((index: number) => string) | null | - | A function which returns a string value for the aria-label attribute of the input. |
| getAriaValueText | ((formattedValue: string, value: number, index: number) => string) | null | - | A function which returns a string value for the aria-valuetext attribute of the input.
This is important for screen reader users. |
| index | number | - | The index of the thumb which corresponds to the index of its value in the
value or defaultValue array.
This prop is required to support server-side rendering for range sliders
with multiple thumbs. |
| onBlur | React.FocusEventHandler<HTMLInputElement> | - | A blur handler forwarded to the input. |
| onFocus | React.FocusEventHandler<HTMLInputElement> | - | A focus handler forwarded to the input. |
| onKeyDown | React.KeyboardEventHandler<HTMLInputElement> | - | A keydown handler forwarded to the input. |
| tabIndex | number | - | Optional tab index attribute forwarded to the input. |
| disabled | boolean | false | Whether the thumb should ignore user interaction. |
| inputRef | React.Ref<HTMLInputElement> | - | A ref to access the nested input element. |
| className | string | ((state: Slider.Thumb.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: Slider.Thumb.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: Slider.Thumb.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
index Prop Example:
<Slider.Root value={[10, 20]}>
<Slider.Thumb index={0} />
<Slider.Thumb index={1} />
</Slider.Root>Thumb Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-dragging | - | Present while the user is dragging. |
| data-orientation | 'horizontal' | 'vertical' | Indicates the orientation of the slider. |
| data-disabled | - | Present when the slider is disabled. |
| data-valid | - | Present when the slider is in a valid state (when wrapped in Field.Root). |
| data-invalid | - | Present when the slider is in an invalid state (when wrapped in Field.Root). |
| data-dirty | - | Present when the slider's value has changed (when wrapped in Field.Root). |
| data-touched | - | Present when the slider has been touched (when wrapped in Field.Root). |
| data-focused | - | Present when the slider is focused (when wrapped in Field.Root). |
| data-index | - | Indicates the index of the thumb in range sliders. |
Accessibility
- Each thumb renders a nested
<input type="range">. Arrow keys move bystep, and Home and End jump to the ends of the range. - Page Up, Page Down, and Shift with an arrow key move by
largeStep. Slider.Labelassociates itself with the thumbs. A multi-thumb slider still needsaria-labelon each thumb to tell them apart.aria-valuetexton a thumb replaces the announced number.getAriaValueTexttakes precedence over it.Slider.Valuerenders an<output>element.- The root reflects
data-dragginganddata-orientation.