import Slider from "@registry/components/ui/slider";

export function SliderExample() {
  return (
    <div className="flex flex-wrap items-center gap-4">
      <Slider aria-label="Volume" defaultValue={40} />
    </div>
  );
}

Examples

Range

Pass an array to defaultValue to render a range slider with multiple thumbs.

import Slider from "@registry/components/ui/slider";

export function RangeSliderExample() {
  return (
    <div className="flex flex-wrap items-center gap-4">
      <Slider aria-label="Price range" defaultValue={[25, 75]} />
    </div>
  );
}

Step

Use step to control the increment between values.

import Slider from "@registry/components/ui/slider";

export function SteppedSliderExample() {
  return (
    <div className="flex flex-wrap items-center gap-4">
      <Slider aria-label="Brightness" defaultValue={50} step={10} />
    </div>
  );
}

Disabled

Use the disabled prop to prevent interaction.

import Slider from "@registry/components/ui/slider";

export function DisabledSliderExample() {
  return (
    <div className="flex flex-wrap items-center gap-4">
      <Slider aria-label="Disabled volume" defaultValue={40} disabled />
    </div>
  );
}

Controlled

Manage the slider value with React state using value and onValueChange.

Volume: 40
import { useState } from "react";
import Slider from "@registry/components/ui/slider";

export function ControlledSliderExample() {
  const [value, setValue] = useState(40);

  return (
    <div className="flex flex-col gap-4">
      <Slider
        aria-label="Volume"
        value={value}
        onValueChange={(nextValue) => {
          setValue(Array.isArray(nextValue) ? (nextValue[0] ?? 0) : nextValue);
        }}
      />
      <span className="text-sm text-gray-600 dark:text-gray-400">Volume: {value}</span>
    </div>
  );
}

Installation

Copy the source code below into your project:

import { cn } from "@registry/lib/utils";
import { Slider as BaseSlider } from "@base-ui/react";
import React from "react";

export default function Slider({
  className,
  value,
  defaultValue,
  min,
  max,
  ...props
}: BaseSlider.Root.Props) {
  const _values = React.useMemo(
    () =>
      Array.isArray(value)
        ? value
        : typeof value === "number"
          ? [value]
          : Array.isArray(defaultValue)
            ? defaultValue
            : typeof defaultValue === "number"
              ? [defaultValue]
              : [min ?? 0],
    [value, defaultValue, min],
  );

  return (
    <BaseSlider.Root
      data-slot="slider"
      defaultValue={defaultValue}
      value={value}
      min={min}
      max={max}
      thumbAlignment="edge"
      {...props}
    >
      <BaseSlider.Control
        className={cn("flex w-32 touch-none items-center select-none", className)}
        data-slot="slider-control"
      >
        <BaseSlider.Track
          className={cn("h-1 w-full rounded-full bg-muted inset-ring inset-ring-input select-none")}
          data-slot="slider-track"
        >
          <BaseSlider.Indicator
            className={cn(
              "bg-accent select-none data-disabled:opacity-50",
              _values.length === 1 ? "rounded-l-full" : "",
            )}
            data-slot="slider-indicator"
          />
          {Array.from({ length: _values.length }).map((_, index) => (
            <BaseSlider.Thumb
              key={index}
              className={(state) =>
                cn(
                  "size-4 rounded-full bg-white shadow-xs ring ring-input transition-transform select-none before:hidden data-disabled:cursor-not-allowed data-disabled:bg-muted",
                  state.dragging && state.activeThumbIndex === index && "scale-110",
                )
              }
              data-slot="slider-thumb"
              index={index}
            />
          ))}
        </BaseSlider.Track>
      </BaseSlider.Control>
    </BaseSlider.Root>
  );
}

API Reference

This component does not add any props on top of Base UI Slider.Root . See the Base UI docs for the full API reference.