# Slider

> Pick a number, or a range, by dragging or with the keyboard.

## Examples

### Basic

```vue
<script setup lang="ts">
const volume = ref(60);
</script>

<template>
  <UiSlider v-model="volume" label="Volume" :format-value="(v) => `${v}%`" />
</template>
```

### Range

Bind a `[start, end]` array for two thumbs. `commit` fires when a drag ends, for anything expensive.

```vue
<script setup lang="ts">
const price = ref<[number, number]>([200, 800]);
const toast = useToast();
</script>

<template>
  <div class="demo-stack">
    <UiSlider
      v-model="price"
      label="Price"
      :min="0"
      :max="1000"
      :step="10"
      :format-value="(v) => `$${v}`"
      @commit="([low, high]) => toast.info(`Filtering $${low}–$${high}`)"
    />
    <p class="demo-note">${{ price[0] }} – ${{ price[1] }}</p>
  </div>
</template>
```

### Vertical

```vue
<script setup lang="ts">
const bass = ref(4);
const treble = ref(-2);
</script>

<template>
  <div class="demo-row">
    <UiSlider v-model="bass" orientation="vertical" label="Bass" :min="-12" :max="12" />
    <UiSlider v-model="treble" orientation="vertical" label="Treble" :min="-12" :max="12" />
  </div>
</template>
```

## API

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `min` | `number` | `0` | Lowest value. |
| `max` | `number` | `100` | Highest value. |
| `step` | `number` | `1` | Arrow-key increment. Values snap to it. |
| `largeStep` | `number` | — | PageUp/PageDown increment. Defaults to ten steps. |
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Layout hook, exposed as `data-orientation` and `aria-orientation`. |
| `disabled` | `boolean` | `false` | Disables the slider. |
| `label` | `string` | — | Visible label, which names the thumb(s). |
| `thumbLabels` | `[string, string]` | — | Accessible names for the two thumbs of a range. Default to `rangeStart` / `rangeEnd`. |
| `formatValue` | `((value: number) => string)` | — | Text for `aria-valuetext`, e.g. `(v) => \`${v}%\``. |
| `name` | `string` | — | Form field name; renders a hidden input per value. |
| `modelValue` | `T` | — | A number, or `[start, end]` for a range. Empty starts at `min`. |

| Event | Payload | Description |
| --- | --- | --- |
| `commit` | `[value: T]` | A drag ended, or a key changed the value. Use it for expensive work. |
| `update:modelValue` | `[value: T \| undefined]` | `v-model:modelValue` update. |

| Slot | Props | Description |
| --- | --- | --- |
| `thumb` | `{ value: number; index: number; }` | Thumb content, e.g. a value bubble. |

## Styling

The range and thumbs are placed with `--ui-slider-start`, `--ui-slider-end` and `--ui-slider-value` (percentages).

- Parts (`[data-part="…"]`): `slider`, `slider-label`, `slider-control`, `slider-track`, `slider-range`, `slider-thumb`
- State attributes: `data-orientation`, `data-slider-disabled`, `data-slider-thumb`

## Keyboard

| Keys                    | Action                             |
| ----------------------- | ---------------------------------- |
| `←` / `→`, `↓` / `↑`    | One step                           |
| `Page Up` / `Page Down` | `largeStep` (ten steps by default) |
| `Home` / `End`          | Minimum / maximum                  |

## Accessibility

- Each thumb is named by `label`; a range's thumbs also get `thumb-labels` (“Minimum”, “Maximum”).
- Use `format-value` so screen readers hear units, e.g. “60%”.
- In right-to-left layouts, `←` / `→` follow the visual direction.
