# Slider

Selects a value or range by dragging.

Source: [slider.tsx](https://github.com/jakejarvis/jarvis-ui/blob/main/src/components/ui/slider.tsx)

```tsx
import * as React from "react";

import { Field, FieldLabel } from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";

export default function SliderBasic() {
  const [volume, setVolume] = React.useState(60);

  return (
    <Field className="max-w-sm">
      <div className="flex items-center justify-between">
        <FieldLabel>Volume</FieldLabel>
        <span className="text-sm text-muted-foreground tabular-nums">{volume}%</span>
      </div>
      <Slider value={volume} onValueChange={setVolume} />
    </Field>
  );
}
```

## Installation

Add the registry, once per project:

```bash
npx shadcn@latest registry add @jarvis=https://ui.jarv.is/r/{name}.json
```

Then add the component:

```bash
npx shadcn@latest add @jarvis/slider
```

## Usage

```tsx
import { Field, FieldLabel } from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";

export function ZoomSlider() {
  return (
    <Field>
      <FieldLabel>Zoom</FieldLabel>
      <Slider defaultValue={100} min={25} max={400} />
    </Field>
  );
}
```

The range is 0 to 100 unless you set `min` and `max`. Name the slider with a `FieldLabel` in the
same [Field](https://ui.jarv.is/components/field.md), or an `aria-label`.

## Examples

### Range

Pass an array of two values for two thumbs. Name each one with `getAriaLabel`.

```tsx
import * as React from "react";

import { Field, FieldLabel } from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";

export default function SliderRange() {
  const [range, setRange] = React.useState([20, 75]);

  return (
    <Field className="max-w-sm">
      <div className="flex items-center justify-between">
        <FieldLabel>Budget</FieldLabel>
        <span className="text-sm text-muted-foreground tabular-nums">
          ${range[0]}k – ${range[1]}k
        </span>
      </div>
      <Slider
        value={range}
        onValueChange={setRange}
        getAriaLabel={(index) => (index === 0 ? "Minimum budget" : "Maximum budget")}
      />
    </Field>
  );
}
```

### Steps

`step` sets the increment.

```tsx
import { Field, FieldLabel } from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";

export default function SliderStep() {
  return (
    <Field className="max-w-sm">
      <FieldLabel>Quality</FieldLabel>
      <Slider defaultValue={50} step={25} />
    </Field>
  );
}
```

### Vertical

Set `orientation="vertical"` and give the parent a height.

```tsx
import { Field, FieldLabel } from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";

export default function SliderVertical() {
  return (
    <div className="flex gap-8">
      <Field className="h-44 w-fit items-center gap-3">
        <Slider orientation="vertical" defaultValue={40} />
        <FieldLabel>Bass</FieldLabel>
      </Field>
      <Field className="h-44 w-fit items-center gap-3">
        <Slider orientation="vertical" defaultValue={[25, 70]} />
        <FieldLabel>Band</FieldLabel>
      </Field>
    </div>
  );
}
```

### Disabled

```tsx
import { Field, FieldLabel } from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";

export default function SliderDisabled() {
  return (
    <Field className="max-w-sm">
      <FieldLabel>Brightness</FieldLabel>
      <Slider defaultValue={30} disabled />
    </Field>
  );
}
```

## Props

`onValueChange` receives the same shape as `value`: a number, or an array of numbers.

| Part | Extends |
| --- | --- |
| `Slider` | [`Slider.Root`](https://base-ui.com/react/components/slider#root) |

The tables leave out `className`, `style` and `render`. Parts built on Base UI take them as its [styling](https://base-ui.com/react/handbook/styling) and [composition](https://base-ui.com/react/handbook/composition) guides describe.

### Slider

| Prop                      | Type                                                                                           | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| ------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `defaultValue?`           | `number \| readonly number[]`                                                                  | The uncontrolled value of the slider when it's initially rendered. To render a controlled slider, use the `value` prop instead.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `disabled?`               | `boolean`                                                                                      | Whether the slider should ignore user interaction. Default: `false`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `format?`                 | `Intl.NumberFormatOptions`                                                                     | Options to format the value.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `locale?`                 | `Intl.LocalesArgument`                                                                         | The locale used by `Intl.NumberFormat` when formatting the value. Defaults to the user's runtime locale.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `max?`                    | `number`                                                                                       | The maximum allowed value of the slider. Should not be equal to min. Default: `100`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `min?`                    | `number`                                                                                       | The minimum allowed value of the slider. Should not be equal to max. Default: `0`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `minStepsBetweenValues?`  | `number`                                                                                       | The minimum steps between values in a range slider. Default: `0`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `name?`                   | `string`                                                                                       | Identifies the field when a form is submitted.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `form?`                   | `string`                                                                                       | Identifies the form that owns the slider inputs. Useful when the slider is rendered outside the form.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `orientation?`            | `"horizontal" \| "vertical"`                                                                   | The component orientation. Default: `'horizontal'`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `step?`                   | `number`                                                                                       | The granularity with which the slider can step through values. (A "discrete" slider.) The `min` prop serves as the origin for the valid values. We recommend (max - min) to be evenly divisible by the step. Default: `1`                                                                                                                                                                                                                                                                                                                                                                                                               |
| `largeStep?`              | `number`                                                                                       | The granularity with which the slider can step through values when using Page Up/Page Down or Shift + Arrow Up/Arrow Down. Default: `10`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `thumbAlignment?`         | `"center" \| "edge" \| "edge-client-only"`                                                     | How the thumb(s) are aligned relative to `Slider.Control` when the value is at `min` or `max`: - `center`: The center of the thumb is aligned with the control edge - `edge`: The thumb is inset within the control such that its edge is aligned with the control edge - `edge-client-only`: Same as `edge` but renders after React hydration on the client, reducing bundle size in return Default: `"edge"`                                                                                                                                                                                                                          |
| `thumbCollisionBehavior?` | `"none" \| "push" \| "swap"`                                                                   | 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. Default: `'push'`                                                                                                                                                                                                                                                                                         |
| `value?`                  | `number \| readonly number[]`                                                                  | The value of the slider. For range sliders, provide an array with one value per thumb.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `onValueChange?`          | `((value: number \| readonly number[], eventDetails: Slider.Root.ChangeEventDetails) => void)` | Callback function that is fired when the slider's value changed. Receives the new value as the first argument; the originating event is available as `eventDetails.event`. The value is also reflected on `eventDetails.event.target.value` for form integration. 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 \| readonly number[], eventDetails: Slider.Root.CommitEventDetails) => void)` | Callback function that is fired when a value change is committed. Does not fire if the value did not change, or if the change was canceled. **Warning**: This is a generic event, not a change event. The `eventDetails.reason` indicates 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                                                                   |
| `getAriaLabel?`           | `((index: number) => string) \| null`                                                          | Names each thumb by its index, such as "Minimum" and "Maximum" on a range. Without it, `aria-label` names every thumb.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `getAriaValueText?`       | `((formattedValue: string, value: number, index: number) => string) \| null`                   | Describes each thumb's value to screen readers, such as "50%" as "Half volume".                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
