An input where the user selects a value from within a given range.
Can be controlled or uncontrolled.
Supports multiple thumbs.
Supports a minimum value between thumbs.
Supports touch or click on track to update value.
Supports Right to Left direction.
Full keyboard navigation.
Install the component from your command line.
npm install @radix-ui/react-slider
Import all parts and piece them together.
import * as Slider from '@radix-ui/react-slider';
export default () => (
  <Slider.Root>
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>
    <Slider.Thumb />
  </Slider.Root>
);
Contains all the parts of a slider. It will render an input for each thumb when used within a form to ensure events propagate correctly.
The track that contains the Slider.Range.
The range part. Must live inside Slider.Track.
A draggable thumb. You can render multiple thumbs.
Use the orientation prop to create a vertical slider.
// index.jsx
import * as Slider from '@radix-ui/react-slider';
import './styles.css';
export default () => (
  <Slider.Root
    className="SliderRoot"
    defaultValue={[50]}
    orientation="vertical"
  >
    <Slider.Track className="SliderTrack">
      <Slider.Range className="SliderRange" />
    </Slider.Track>
    <Slider.Thumb className="SliderThumb" />
  </Slider.Root>
);
/* styles.css */
.SliderRoot {
  position: relative;
  display: flex;
  align-items: center;
}
.SliderRoot[data-orientation='vertical'] {
  flex-direction: column;
  width: 20px;
  height: 100px;
}
.SliderTrack {
  position: relative;
  flex-grow: 1;
  background-color: grey;
}
.SliderTrack[data-orientation='vertical'] {
  width: 3px;
}
.SliderRange {
  position: absolute;
  background-color: black;
}
.SliderRange[data-orientation='vertical'] {
  width: 100%;
}
.SliderThumb {
  display: block;
  width: 20px;
  height: 20px;
  background-color: black;
}
Add multiple thumbs and values to create a range slider.
import * as Slider from '@radix-ui/react-slider';
export default () => (
  <Slider.Root defaultValue={[25, 75]}>
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>
    <Slider.Thumb />
    <Slider.Thumb />
  </Slider.Root>
);
Use the step prop to increase the stepping interval.
import * as Slider from '@radix-ui/react-slider';
export default () => (
  <Slider.Root defaultValue={[50]} step={10}>
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>
    <Slider.Thumb />
  </Slider.Root>
);
Use minStepsBetweenThumbs to avoid thumbs with equal values.
import * as Slider from '@radix-ui/react-slider';
export default () => (
  <Slider.Root defaultValue={[25, 75]} step={10} minStepsBetweenThumbs={1}>
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>
    <Slider.Thumb />
    <Slider.Thumb />
  </Slider.Root>
);
Adheres to the Slider WAI-ARIA design pattern.
Create your own API by abstracting the primitive parts into your own component.
This example abstracts all of the Slider parts so it can be used as a self closing element.
import { Slider } from './your-slider';
export default () => <Slider defaultValue={[25]} />;
// your-slider.jsx
import * as SliderPrimitive from '@radix-ui/react-slider';
export const Slider = React.forwardRef((props, forwardedRef) => {
  const value = props.value || props.defaultValue;
  return (
    <SliderPrimitive.Slider {...props} ref={forwardedRef}>
      <SliderPrimitive.Track>
        <SliderPrimitive.Range />
      </SliderPrimitive.Track>
      {value.map((_, i) => (
        <SliderThumb key={i} />
      ))}
    </SliderPrimitive.Slider>
  );
});
Because of a limitation we faced during implementation, the following example won't work as expected and the onMouseDown and onMouseUp event handlers won't be fired:
<Slider.Root
  onMouseDown={() => console.log('onMouseDown')}
  onMouseUp={() => console.log('onMouseUp')}
>
  …
</Slider.Root>
We recommend using pointer events instead (eg. onPointerDown, onPointerUp). Regardless of the above limitation, these events are better suited for cross-platform/device handling as they are fired for all pointer input types (mouse, touch, pen, etc.).