Slider
An input where the user selects a value from within a given range.
import * as React from 'react'; import { Slider } from 'gnome-ui/slider'; import { Volume2 } from 'lucide-react'; export function SliderDefault() { return ( <div className="flex w-full max-w-sm flex-col gap-4"> <div className="flex items-center justify-between text-sm font-medium text-foreground"> <label className="flex items-center gap-2"> <Icons.Volume2 className="size-4 text-muted-foreground" /> System volume </label> <Slider.Value /> </div> <Slider.Root defaultValue={75} className="flex w-full items-center"> <Slider.Control className="relative flex w-full items-center py-2"> <Slider.Track className="h-1.5 w-full overflow-hidden rounded-full bg-secondary"> <Slider.Indicator className="h-full bg-primary" /> </Slider.Track> <Slider.Thumb className="block size-4 rounded-full border border-primary bg-background shadow-sm transition-transform hover:scale-110 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50" /> </Slider.Control> </Slider.Root> </div> ); }
Anatomy
import { Slider } from 'gnome-ui/slider'; <Slider.Root> <Slider.Value /> <Slider.Control> <Slider.Track> <Slider.Indicator /> </Slider.Track> <Slider.Thumb /> </Slider.Control> </Slider.Root>
Examples
Range Slider
Provide an array to the defaultValue or value prop to create a range slider with multiple thumbs. When doing this, ensure you pass an index to <Slider.Thumb> and <Slider.Value> if you want to display individual thumb values.
import * as React from 'react'; import { Slider } from 'gnome-ui/slider'; import { Monitor } from 'lucide-react'; export function SliderRange() { return ( <div className="flex w-full max-w-sm flex-col gap-4"> <div className="flex items-center justify-between text-sm font-medium text-foreground"> <label className="flex items-center gap-2"> <Icons.Monitor className="size-4 text-muted-foreground" /> Workspace (GB) </label> <div className="flex gap-1 text-muted-foreground"> <Slider.Value index={0} /> - <Slider.Value index={1} /> </div> </div> <Slider.Root defaultValue={[20, 80]} className="flex w-full items-center"> <Slider.Control className="relative flex w-full items-center py-2"> <Slider.Track className="h-1.5 w-full overflow-hidden rounded-full bg-secondary"> <Slider.Indicator className="h-full bg-[oklch(0.55_0.12_250)]" /> </Slider.Track> <Slider.Thumb index={0} className="block size-4 rounded-full border border-[oklch(0.55_0.12_250)] bg-background shadow-sm transition-transform hover:scale-110 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[oklch(0.55_0.12_250)]" /> <Slider.Thumb index={1} className="block size-4 rounded-full border border-[oklch(0.55_0.12_250)] bg-background shadow-sm transition-transform hover:scale-110 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[oklch(0.55_0.12_250)]" /> </Slider.Control> </Slider.Root> </div> ); }
Vertical Slider
Use orientation="vertical" on the root component to create a vertical slider. Make sure to adjust the width and height of the track, indicator, and control accordingly.
import * as React from 'react'; import { Slider } from 'gnome-ui/slider'; import { Sun } from 'lucide-react'; export function SliderVertical() { return ( <div className="flex h-48 flex-col items-center gap-4"> <Icons.Sun className="size-4 text-muted-foreground" /> <Slider.Root orientation="vertical" defaultValue={60} className="flex h-full items-center"> <Slider.Control className="relative flex h-full items-center px-2"> <Slider.Track className="w-1.5 h-full overflow-hidden rounded-full bg-secondary"> <Slider.Indicator className="w-full bg-[oklch(0.75_0.15_50)]" /> </Slider.Track> <Slider.Thumb className="block size-4 rounded-full border border-[oklch(0.75_0.15_50)] bg-background shadow-sm transition-transform hover:scale-110 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[oklch(0.75_0.15_50)]" /> </Slider.Control> </Slider.Root> </div> ); }
SliderControl
The clickable, interactive part of the slider.
Renders a <div> element.
Documentation: Base UI Slider
API reference
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 ranged sliders, provide an array with two values. |
| onValueChange | ((value: number | number[], eventDetails: Slider.Root.ChangeEventDetails) => void) | - | Callback function that is fired when the slider's value changed.
You can pull out the new value by accessing event.target.value (any).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 thepointerupis triggered. Warning: This is a generic event not a change event.TheeventDetails.reasonindicates 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 | | locale |Intl.LocalesArgument| - | The locale used byIntl.NumberFormatwhen formatting the value. Defaults to the user's runtime locale. | | thumbAlignment |'center' \| 'edge' \| 'edge-client-only'|'center'| How the thumb(s) are aligned relative toSlider.Controlwhen the value is atminormax:*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 asedgebut 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.) Theminprop 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 input 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 |CSSProperties \| ((state: Slider.Root.State) => CSSProperties \| undefined)| - | - | | 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 aReactElementor 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 valid state (when wrapped in Field.Root). |
| data-invalid | - | Present when the slider is in 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). |
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[]) => ReactNode) | null | - | - |
| 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 | CSSProperties | ((state: Slider.Root.State) => CSSProperties | undefined) | - | * |
| 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 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 valid state (when wrapped in Field.Root). |
| data-invalid | - | Present when the slider is in 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.Root.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component’s state. |
| style | CSSProperties | ((state: Slider.Root.State) => CSSProperties | undefined) | - | - |
| 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. |
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 valid state (when wrapped in Field.Root). |
| data-invalid | - | Present when the slider is in 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.Root.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component’s state. |
| style | CSSProperties | ((state: Slider.Root.State) => CSSProperties | undefined) | - | - |
| 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. |
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 valid state (when wrapped in Field.Root). |
| data-invalid | - | Present when the slider is in 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.Root.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component’s state. |
| style | CSSProperties | ((state: Slider.Root.State) => CSSProperties | undefined) | - | - |
| 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. |
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 valid state (when wrapped in Field.Root). |
| data-invalid | - | Present when the slider is in 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 |
|---|---|---|---|
| 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 | FocusEventHandler<HTMLInputElement> | - | A blur handler forwarded to the input. |
| onFocus | FocusEventHandler<HTMLInputElement> | - | A focus 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 | 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 | CSSProperties | ((state: Slider.Thumb.State) => CSSProperties | undefined) | - | - |
| 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. |
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 valid state (when wrapped in Field.Root). |
| data-invalid | - | Present when the slider is in 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. |