> Native Solid 2 fork. Original documentation and designs © WorkOS; historical posts retain their original context.

# Slider

An input where the user selects a value from within a given range.

## Features

- 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.

## Anatomy

Import all parts and piece them together.

```jsx
import { Slider } from "@radix-solid/primitives";

export default () => <Slider.Root>

		<Slider.Track>

			<Slider.Range />

		</Slider.Track>

		<Slider.Thumb />

	</Slider.Root>;
```

## API Reference

### 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.

| Prop                                                                                                                                                                          | Type       | Default        |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -------------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details.       | `boolean`  | `false`        |
| `defaultValue`The value of the slider when initially rendered. Use when you do not need to control the state of the slider.                                                   | `number[]` | —              |
| `value`The controlled value of the slider. Must be used in conjunction with `onValueChange`.                                                                                  | `number[]` | —              |
| `onValueChange`Event handler called when the value changes.                                                                                                                   | `function` | —              |
| `onValueCommit`Event handler called when the value changes at the end of an interaction. Useful when you only need to capture a final value e.g. to update a backend service. | `function` | —              |
| `name`The name of the slider. Submitted with its owning form as part of a name/value pair.                                                                                    | `string`   | —              |
| `disabled`When `true`, prevents the user from interacting with the slider.                                                                                                    | `boolean`  | `false`        |
| `orientation`The orientation of the slider.                                                                                                                                   | `enum`     | `"horizontal"` |
| `dir`The reading direction of the slider. If omitted, inherits globally from `DirectionProvider` or assumes LTR (left-to-right) reading mode.                                 | `enum`     | —              |
| `inverted`Whether the slider is visually inverted.                                                                                                                            | `boolean`  | `false`        |
| `min`The minimum value for the range.                                                                                                                                         | `number`   | `0`            |
| `max`The maximum value for the range.                                                                                                                                         | `number`   | `100`          |
| `step`The stepping interval.                                                                                                                                                  | `number`   | `1`            |
| `minStepsBetweenThumbs`The minimum permitted `step`s between multiple thumbs.                                                                                                 | `number`   | `0`            |
| `form`The ID of the form that the slider belongs to. If omitted, the slider will be associated with a parent form if one exists.                                              | `string`   | —              |

| Data attribute       | Values                       |
| -------------------- | ---------------------------- |
| `[data-disabled]`    | Present when disabled        |
| `[data-orientation]` | `"vertical" \| "horizontal"` |

### Track

The track that contains the `Slider.Range`.

| Prop                                                                                                                                                                    | Type      | Default |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details. | `boolean` | `false` |

| Data attribute       | Values                       |
| -------------------- | ---------------------------- |
| `[data-disabled]`    | Present when disabled        |
| `[data-orientation]` | `"vertical" \| "horizontal"` |

### Range

The range part. Must live inside `Slider.Track`.

| Prop                                                                                                                                                                    | Type      | Default |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details. | `boolean` | `false` |

| Data attribute       | Values                       |
| -------------------- | ---------------------------- |
| `[data-disabled]`    | Present when disabled        |
| `[data-orientation]` | `"vertical" \| "horizontal"` |

### Thumb

A draggable thumb. You can render multiple thumbs.

| Prop                                                                                                                                                                    | Type      | Default |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details. | `boolean` | `false` |

| Data attribute       | Values                       |
| -------------------- | ---------------------------- |
| `[data-disabled]`    | Present when disabled        |
| `[data-orientation]` | `"vertical" \| "horizontal"` |

## Examples

### Vertical orientation

Use the `orientation` prop to create a vertical slider.

```jsx
// index.tsx

import { Slider } from "@radix-solid/primitives";

import "./styles.css";

export default () => <Slider.Root class="SliderRoot" defaultValue={[50]} orientation="vertical">

		<Slider.Track class="SliderTrack">

			<Slider.Range class="SliderRange" />

		</Slider.Track>

		<Slider.Thumb class="SliderThumb" />

	</Slider.Root>;
```

```css
/* 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;

}
```

### Create a range

Add multiple thumbs and values to create a range slider.

```jsx
import { Slider } from "@radix-solid/primitives";

export default () => <Slider.Root defaultValue={[25, 75]}>

		<Slider.Track>

			<Slider.Range />

		</Slider.Track>

		<Slider.Thumb />

		<Slider.Thumb />

	</Slider.Root>;
```

### Define step size

Use the `step` prop to increase the stepping interval.

```jsx
import { Slider } from "@radix-solid/primitives";

export default () => <Slider.Root defaultValue={[50]} step={10}>

		<Slider.Track>

			<Slider.Range />

		</Slider.Track>

		<Slider.Thumb />

	</Slider.Root>;
```

### Prevent thumb overlap

Use `minStepsBetweenThumbs` to avoid thumbs with equal values.

```jsx
import { Slider } from "@radix-solid/primitives";

export default () => <Slider.Root defaultValue={[25, 75]} step={10} minStepsBetweenThumbs={1}>

		<Slider.Track>

			<Slider.Range />

		</Slider.Track>

		<Slider.Thumb />

		<Slider.Thumb />

	</Slider.Root>;
```

### Decoupling the hidden input

By default, `Slider.Thumb` renders a visually hidden `input` for form submission. To recompose, move, or exclude that input, you can build each thumb from its lower-level parts instead.

> **Important:** These parts are unstable and prefixed with `unstable_`, so their API may change in a future release.

- `Slider.unstable_ThumbProvider` provides the thumb state and accepts an optional `name` for the submitted value.
- `Slider.unstable_ThumbTrigger` is the draggable thumb element.
- `Slider.unstable_BubbleInput` is the visually hidden input that `Slider.Thumb` renders by default. Omit it when you don't need form submission.

```jsx
import { Slider } from "@radix-solid/primitives";

export default () => <Slider.Root defaultValue={[25, 75]}>

		<Slider.Track>

			<Slider.Range />

		</Slider.Track>



		<Slider.unstable_ThumbProvider name="price[min]">

			<Slider.unstable_ThumbTrigger />

			<Slider.unstable_BubbleInput />

		</Slider.unstable_ThumbProvider>



		<Slider.unstable_ThumbProvider name="price[max]">

			<Slider.unstable_ThumbTrigger />

			<Slider.unstable_BubbleInput />

		</Slider.unstable_ThumbProvider>

	</Slider.Root>;
```

## Accessibility

Adheres to the [Slider WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/slider-multithumb).

### Keyboard Interactions

| Key                 | Description                                                           |
| ------------------- | --------------------------------------------------------------------- |
| `ArrowRight`        | Increments/decrements by the `step` value depending on `orientation`. |
| `ArrowLeft`         | Increments/decrements by the `step` value depending on `orientation`. |
| `ArrowUp`           | Increases the value by the `step` amount.                             |
| `ArrowDown`         | Decreases the value by the `step` amount.                             |
| `PageUp`            | Increases the value by a larger `step`.                               |
| `PageDown`          | Decreases the value by a larger `step`.                               |
| `Shift + ArrowUp`   | Increases the value by a larger `step`.                               |
| `Shift + ArrowDown` | Decreases the value by a larger `step`.                               |
| `Home`              | Sets the value to its minimum.                                        |
| `End`               | Sets the value to its maximum.                                        |

## Custom APIs

Create your own API by abstracting the primitive parts into your own component.

### Abstract all parts

This example abstracts all of the `Slider` parts so it can be used as a self closing element.

#### Usage

```jsx
import { Slider } from "./your-slider";

export default () => <Slider defaultValue={[25]} />;
```

#### Implementation

```jsx
import { type ComponentProps } from "solid-js";

// your-slider.tsx

import { Slider as SliderPrimitive } from "@radix-solid/primitives";

export const Slider = (p: Extract<ComponentProps<typeof SliderPrimitive.Root>, {

  asChild?: false;

}>) => {

  const value = () => p.value ?? p.defaultValue ?? [0];

  return <SliderPrimitive.Root {...p} ref={p.ref}>

			<SliderPrimitive.Track>

				<SliderPrimitive.Range />

			</SliderPrimitive.Track>

			{value().map(() => <SliderPrimitive.Thumb />)}

		</SliderPrimitive.Root>;

};
```

## Caveats

### Mouse events are not fired

Because of [a limitation](https://github.com/radix-ui/primitives/blob/83a8c13bf66f3d9f17d77caeb187a69eb146930b/packages/react/slider/src/Slider.tsx#L383-L384) we faced during implementation, the following example won't work as expected and the `onMouseDown` and `onMouseUp` event handlers won't be fired:

```jsx
<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.).
