# Slider

An accessible React slider for Next.js and Tailwind: one value or a range, with a thumb that grows into a pill showing its value as you reach for it.

Source: https://ui.fewtone.com/components/slider

## Installation

```bash
npx shadcn@latest add https://ui.fewtone.com/r/slider.json
```

## Usage

```tsx
import { Slider } from "@/components/ui/slider"

export function Volume() {
  return <Slider aria-label="Volume" defaultValue={[60]} max={100} step={1} />
}
```

## API reference

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `number[]` | – | The values, when you control them: one per thumb. |
| `defaultValue` | `number[]` | `[min]` | The values at first. Two numbers make a range. |
| `onValueChange` | `(value: number[]) => void` | – | Called on every change, while dragging too. |
| `onValueCommit` | `(value: number[]) => void` | – | Called once a drag ends or a key changes the value. |
| `min` | `number` | `0` | The lowest value. |
| `max` | `number` | `100` | The highest value. |
| `step` | `number` | `1` | The values snap to steps of this size. |
| `minStepsBetweenThumbs` | `number` | `0` | How many steps a range's thumbs keep apart. |
| `format` | `Intl.NumberFormatOptions` | – | How the value is written in the thumb's pill and for screen readers (aria-valuetext), for example { style: "currency", currency: "USD" }. |
| `locale` | `string` | `"en-US"` | The locale to format in. Fixed by default so the server and the browser agree. |
| `thumbLabels` | `string[]` | – | A name for each thumb. Without it a range's thumbs are named from aria-label, for example “Price, minimum”. |
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Vertical is at least 11rem tall and fills a taller container. |
| `inverted` | `boolean` | `false` | Puts the lowest value at the other end. |
| `disabled` | `boolean` | `false` | Prevents interaction. |
| `name` | `string` | – | Submits the values with a form, through a hidden input per thumb. |

**When to use it:** Use Slider to pick a value or a range where its place between a minimum and a maximum matters more than the exact number: volume, price filters, sizes. Use NumberInput when people need to type or nudge an exact number.
**Built on:** WAI-ARIA slider pattern.
**Accessibility pattern:** https://www.w3.org/WAI/ARIA/apg/patterns/slider/
**npm packages (installed by the CLI):** motion@^14.0.0.
**Installs these FewTone UI components with it:** `number-ticker`.

## Examples

### Single and range

Reach for a thumb (hover, Tab, drag) and it grows from a dot into a pill with its value inside, the number flowing as it changes, while the track thickens. Click the track and the thumb glides there; drag and it follows the pointer, the pill stretching with its speed.

```tsx
"use client";

import { Slider } from "@/components/ui/slider";

const percent = { style: "unit", unit: "percent" } as const;
const dollars = { style: "currency", currency: "USD", maximumFractionDigits: 0 } as const;

/**
 * One value and a range side by side, named underneath. Reach for a thumb (hover, Tab, drag) and it grows into
 * a pill with its value inside, flowing as it changes.
 */
export default function SliderSingleAndRange() {
  return (
    <ul className="flex w-full flex-wrap items-center justify-center gap-x-12 gap-y-10 pt-6">
      <li className="flex w-full max-w-48 flex-col items-center gap-4">
        <Slider aria-label="Volume" defaultValue={[60]} format={percent} />
        <span className="text-xs text-muted-foreground">Single</span>
      </li>
      <li className="flex w-full max-w-48 flex-col items-center gap-4">
        <Slider
          aria-label="Price"
          defaultValue={[200, 750]}
          max={1000}
          step={10}
          minStepsBetweenThumbs={5}
          format={dollars}
        />
        <span className="text-xs text-muted-foreground">Range</span>
      </li>
    </ul>
  );
}
```

### With a label

A visible label names the thumb through aria-labelledby, with the value beside it. An Intl format (hours) shows in the pill and gives screen readers the same text.

```tsx
"use client";

import { Slider } from "@/components/ui/slider";
import { useId, useState } from "react";

/*
 * A visible label with the value beside it, controlled. aria-labelledby names the thumb from the label, and
 * the Intl format ("24 hours") shows in the thumb's pill and reaches screen readers as aria-valuetext.
 */
export default function SliderLabelled() {
  const id = useId();
  const [value, setValue] = useState([24]);
  const hours = { style: "unit", unit: "hour", unitDisplay: "long" } as const;
  const format = (value: number) => new Intl.NumberFormat("en-US", hours).format(value);

  return (
    <div className="grid w-full max-w-xs gap-3">
      <div className="flex items-center justify-between gap-4">
        <span id={id} className="text-sm font-medium">
          Keep backups for
        </span>
        <span className="text-sm text-muted-foreground tabular-nums">{format(value[0] ?? 0)}</span>
      </div>
      <Slider aria-labelledby={id} value={value} onValueChange={setValue} min={1} max={72} format={hours} />
    </div>
  );
}
```

### Vertical

orientation="vertical": at least 11rem tall, filling a taller container. Up and Right raise the value, and the pill grows from the thumb just the same.

```tsx
import { Slider } from "@/components/ui/slider";

const bands = [
  { label: "Bass", value: 60 },
  { label: "Mid", value: 40 },
  { label: "Treble", value: 70 },
];

/**
 * orientation="vertical": at least 11rem tall, filling a taller container. Up and Right raise the value,
 * and the thumb's pill shows the value.
 */
export default function SliderVertical() {
  return (
    <ul className="flex items-start justify-center gap-16">
      {bands.map((band) => (
        <li key={band.label} className="flex flex-col items-center gap-3">
          <Slider orientation="vertical" aria-label={band.label} defaultValue={[band.value]} />
          <span className="text-xs text-muted-foreground">{band.label}</span>
        </li>
      ))}
    </ul>
  );
}
```

## Related

- [Number Input](https://ui.fewtone.com/components/number-input.md): An accessible React number input for Next.js and Tailwind with step buttons, keyboard control, min and max, and Intl number formatting.
- [Switch](https://ui.fewtone.com/components/switch.md): An accessible React switch for on/off settings, with a spring-animated thumb, built on Radix Switch.
- [Input](https://ui.fewtone.com/components/input.md): An accessible React text input with three sizes and clear invalid, disabled and file states, built on a native input.
