apps/docs/content/docs/react/components/(controls)/slider.mdx
import { Slider } from '@heroui/react';
<ComponentPreview name="slider-default" />
Import the Slider component and access all parts using dot notation.
import { Slider, Label } from '@heroui/react';
export default () => (
<Slider>
<Label />
<Slider.Output />
<Slider.Track>
<Slider.Fill />
<Slider.Thumb />
</Slider.Track>
</Slider>
)
import { Slider, Label } from '@heroui/react';
export default () => (
<Slider defaultValue={[25, 75]}>
<Label />
<Slider.Output />
<Slider.Track>
{({state}) => (
<>
<Slider.Fill />
{state.values.map((_, i) => (
<Slider.Thumb key={i} index={i} />
))}
</>
)}
</Slider.Track>
</Slider>
)
<ComponentPreview name="slider-vertical" />
<ComponentPreview name="slider-range" />
<ComponentPreview name="slider-disabled" />
<ComponentPreview name="slider-custom-render-function" />
<RelatedComponents component="slider" />import { Slider, Label } from '@heroui/react';
function CustomSlider() {
return (
<Slider className="w-full">
<Label>Volume</Label>
<Slider.Output className="text-muted-fg text-sm" />
<Slider.Track className="h-2 rounded-full bg-surface-secondary">
<Slider.Fill className="bg-accent" />
<Slider.Thumb className="size-4 rounded-full bg-accent" />
</Slider.Track>
</Slider>
);
}
To customize the Slider component classes, you can use the @layer components directive.
@layer components {
.slider {
@apply flex flex-col gap-2;
}
.slider__output {
@apply text-muted-fg text-sm;
}
.slider-track {
@apply relative h-2 w-full rounded-full bg-surface-secondary;
}
.slider-fill {
@apply absolute h-full rounded-full bg-accent;
}
.slider-thumb {
@apply size-4 rounded-full bg-accent border-2 border-background;
}
}
HeroUI follows the BEM methodology to ensure component variants and states are reusable and easy to customize.
The Slider component uses these CSS classes (View source styles):
.slider - Base slider container.slider__output - Output element displaying current value(s).slider-track - Track element containing fill and thumbs.slider-fill - Fill element showing selected range.slider-thumb - Individual thumb element.slider[data-disabled="true"] - Disabled slider state.slider[data-orientation="vertical"] - Vertical orientation.slider-thumb[data-dragging="true"] - Thumb being dragged.slider-thumb[data-focus-visible="true"] - Thumb keyboard focused.slider-thumb[data-disabled="true"] - Disabled thumb state.slider-track[data-fill-start="true"] - Fill starts at beginning.slider-track[data-fill-end="true"] - Fill ends at endThe component supports both CSS pseudo-classes and data attributes for flexibility:
:hover or [data-hovered="true"] on thumb:focus-visible or [data-focus-visible="true"] on thumb[data-dragging="true"] on thumb:disabled or [data-disabled="true"] on slider or thumb| Prop | Type | Default | Description |
|---|---|---|---|
value | number | number[] | - | The current value (controlled) |
defaultValue | number | number[] | - | The default value (uncontrolled) |
onChange | (value: number | number[]) => void | - | Handler called when the value changes |
onChangeEnd | (value: number | number[]) => void | - | Handler called when dragging ends |
minValue | number | 0 | The slider's minimum value |
maxValue | number | 100 | The slider's maximum value |
step | number | 1 | The slider's step value |
formatOptions | Intl.NumberFormatOptions | - | The display format of the value label |
orientation | "horizontal" | "vertical" | "horizontal" | The orientation of the slider |
isDisabled | boolean | - | Whether the slider is disabled |
aria-label | string | - | Accessibility label for the slider |
aria-labelledby | string | - | ID of element that labels the slider |
className | string | - | Additional CSS classes |
children | ReactNode | RenderFunction | - | Slider content or render function |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, SliderRenderProps> | - | Overrides the default DOM element with a custom render function. |
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
children | ReactNode | RenderFunction | - | Output content or render function |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, SliderOutputRenderProps> | - | Overrides the default DOM element with a custom render function. |
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
children | ReactNode | RenderFunction | - | Track content or render function |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, SliderTrackRenderProps> | - | Overrides the default DOM element with a custom render function. |
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
style | CSSProperties | - | Inline styles |
| Prop | Type | Default | Description |
|---|---|---|---|
index | number | 0 | Index of the thumb within the slider |
isDisabled | boolean | - | Whether this thumb is disabled |
name | string | - | The name of the input element, used when submitting an HTML form |
className | string | - | Additional CSS classes |
children | ReactNode | RenderFunction | - | Thumb content or render function |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, SliderThumbRenderProps> | - | Overrides the default DOM element with a custom render function. |
When using render functions with Slider.Output or Slider.Track, these values are provided:
| Prop | Type | Description |
|---|---|---|
state | SliderState | The state of the slider |
values | number[] | Values managed by the slider by thumb index |
getThumbValueLabel | (index: number) => string | Returns the string label for the specified thumb's value |
orientation | "horizontal" | "vertical" | The orientation of the slider |
isDisabled | boolean | Whether the slider is disabled |
import { Slider, Label } from '@heroui/react';
<Slider defaultValue={30}>
<Label>Volume</Label>
<Slider.Output />
<Slider.Track>
<Slider.Fill />
<Slider.Thumb />
</Slider.Track>
</Slider>
import { Slider, Label } from '@heroui/react';
<Slider
defaultValue={[100, 500]}
formatOptions={{style: "currency", currency: "USD"}}
maxValue={1000}
minValue={0}
step={50}
>
<Label>Price Range</Label>
<Slider.Output />
<Slider.Track>
{({state}) => (
<>
<Slider.Fill />
{state.values.map((_, i) => (
<Slider.Thumb key={i} index={i} />
))}
</>
)}
</Slider.Track>
</Slider>
import { Slider, Label } from '@heroui/react';
import { useState } from 'react';
function ControlledSlider() {
const [value, setValue] = useState(25);
return (
<>
<Slider value={value} onChange={setValue}>
<Label>Volume</Label>
<Slider.Output />
<Slider.Track>
<Slider.Fill />
<Slider.Thumb />
</Slider.Track>
</Slider>
<p>Current value: {value}</p>
</>
);
}
import { Slider, Label } from '@heroui/react';
<Slider
defaultValue={60}
formatOptions={{style: "currency", currency: "USD"}}
>
<Label>Price</Label>
<Slider.Output />
<Slider.Track>
<Slider.Fill />
<Slider.Thumb />
</Slider.Track>
</Slider>
import { Slider, Label } from '@heroui/react';
<Slider defaultValue={30} orientation="vertical" aria-label="Volume">
<Label>Volume</Label>
<Slider.Output />
<Slider.Track>
<Slider.Fill />
<Slider.Thumb />
</Slider.Track>
</Slider>
import { Slider, Label } from '@heroui/react';
<Slider defaultValue={[25, 75]}>
<Label>Range</Label>
<Slider.Output>
{({state}) =>
state.values.map((_, i) => state.getThumbValueLabel(i)).join(' – ')
}
</Slider.Output>
<Slider.Track>
{({state}) => (
<>
<Slider.Fill />
{state.values.map((_, i) => (
<Slider.Thumb key={i} index={i} />
))}
</>
)}
</Slider.Track>
</Slider>
The Slider component implements the ARIA slider pattern and provides:
For more information, see the React Aria Slider documentation.