> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Slider

> Choose a numeric value or range with draggable, keyboard-accessible thumbs.

export const StoryEmbed = ({storyId, title, height = 240}) => <>
    <Tabs>
      <Tab title="Light">
        <iframe title={`${title} (light)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:light`} width="100%" height={height} loading="lazy" style={{
  border: 0
}} />
      </Tab>
      <Tab title="Dark">
        <iframe title={`${title} (dark)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:dark`} width="100%" height={height} loading="lazy" style={{
  border: 0
}} />
      </Tab>
    </Tabs>
    <a href={`https://storybook.twenty.com/?path=/story/${storyId}`}>
      Open in Storybook
    </a>
  </>;

`Slider` supports a single number or an array of numbers for a range. Compose its label, track, indicator, and thumbs inside `Root`.

<StoryEmbed storyId="ui-input-slider--default" title="Slider example" height={240} />

## Anatomy

Put the track and thumbs inside `Slider.Control`, which handles pointer interaction. This tree shows a single-thumb slider.

```text theme={null}
Slider.Root
├── Slider.Label
├── Slider.Value
└── Slider.Control
    └── Slider.Track
        ├── Slider.Indicator
        └── Slider.Thumb
```

| Part        | Requirement                   | Purpose                                                         |
| ----------- | ----------------------------- | --------------------------------------------------------------- |
| `Root`      | Required                      | Owns the value, bounds, step, and orientation.                  |
| `Control`   | Required                      | Handles pointer interaction and positions the thumbs.           |
| `Track`     | Required for the styled track | Shows the full value range.                                     |
| `Thumb`     | One per adjustable value      | Provides a focusable handle with keyboard interaction.          |
| `Label`     | Recommended                   | Supplies a visible label; every thumb needs an accessible name. |
| `Value`     | Optional                      | Displays the current numeric value.                             |
| `Indicator` | Optional                      | Shows the selected portion of the track.                        |

For a range, add a thumb for each value with its matching `index` and a distinct accessible name. Labels and numeric output stay outside `Control`, so they do not become part of the draggable area.

## Uncontrolled state

Use `defaultValue` to set the initial volume. The slider owns subsequent changes.

```tsx theme={null}
import { Slider } from 'twenty-ui/primitives/input';

export const VolumeSlider = () => (
  <Slider.Root name="volume" defaultValue={40} min={0} max={100} step={1}>
    <Slider.Label>Volume</Slider.Label>
    <Slider.Value />
    <Slider.Control>
      <Slider.Track>
        <Slider.Indicator />
        <Slider.Thumb />
      </Slider.Track>
    </Slider.Control>
  </Slider.Root>
);
```

## Controlled state

Pass `value` and update it with `onValueChange` to own the same volume in React state. The callback receives the next value and event details.

```tsx theme={null}
import { useState } from 'react';
import { Slider } from 'twenty-ui/primitives/input';

export const VolumeSlider = () => {
  const [volume, setVolume] = useState(40);

  return (
    <Slider.Root
      name="volume"
      value={volume}
      onValueChange={setVolume}
      min={0}
      max={100}
      step={1}
    >
      <Slider.Label>Volume</Slider.Label>
      <Slider.Value />
      <Slider.Control>
        <Slider.Track>
          <Slider.Indicator />
          <Slider.Thumb />
        </Slider.Track>
      </Slider.Control>
    </Slider.Root>
  );
};
```

Use `onValueChange` to keep the controlled value current during an interaction. `onValueCommitted` handles the final value when the interaction finishes, for example to save it. Both callbacks are also available in uncontrolled mode without taking ownership of the value.

## Range

```tsx theme={null}
import { Slider } from 'twenty-ui/primitives/input';

export const PriceRange = () => (
  <Slider.Root
    defaultValue={[25, 75]}
    min={0}
    max={100}
    minStepsBetweenValues={10}
  >
    <Slider.Label>Price range</Slider.Label>
    <Slider.Value />
    <Slider.Control>
      <Slider.Track>
        <Slider.Indicator />
        <Slider.Thumb index={0} aria-label="Minimum price" />
        <Slider.Thumb index={1} aria-label="Maximum price" />
      </Slider.Track>
    </Slider.Control>
  </Slider.Root>
);
```

Give range thumbs distinct accessible names and an `index` corresponding to their value. `minStepsBetweenValues` sets the minimum gap in steps. The root's generic value type is a number or a readonly array of numbers.

To control a range, store the array in React state and pass it through `value` and `onValueChange`, just as for a single value.

## Keyboard and appearance

Arrow keys adjust a focused thumb by a step. Home and End move it toward the bounds while respecting range constraints. `orientation="vertical"` changes the layout and keyboard direction. Use `disabled` on `Root` to prevent changes.

Set `color="success"` for the alternative palette; the default is `accent`.

## Props

The reference is generated from the public component types. Native attributes, including accessible names and event handlers, are also accepted on parts that render elements.

### Slider.Root

<ParamField body="Root.className" type="string | ((state: SliderRootState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Root.color" type="&#x22;accent&#x22; | &#x22;success&#x22;" default="accent">
  Color of the indicator and thumbs.
</ParamField>

<ParamField body="Root.defaultValue" type="number | readonly number[]">
  The uncontrolled value of the slider when it's initially rendered.

  To render a controlled slider, use the `value` prop instead.
</ParamField>

<ParamField body="Root.disabled" type="boolean" default="false">
  Whether the slider should ignore user interaction.
</ParamField>

<ParamField body="Root.form" type="string">
  Identifies the form that owns the slider inputs.
  Useful when the slider is rendered outside the form.
</ParamField>

<ParamField body="Root.format" type="NumberFormatOptions">
  Options to format the value.
</ParamField>

<ParamField body="Root.largeStep" type="number" default="10">
  The granularity with which the slider can step through values when using Page Up/Page Down or Shift + Arrow Up/Arrow Down.
</ParamField>

<ParamField body="Root.locale" type="LocalesArgument">
  The locale used by `Intl.NumberFormat` when formatting the value.
  Defaults to the user's runtime locale.
</ParamField>

<ParamField body="Root.max" type="number" default="100">
  The maximum allowed value of the slider.
  Should not be equal to min.
</ParamField>

<ParamField body="Root.min" type="number" default="0">
  The minimum allowed value of the slider.
  Should not be equal to max.
</ParamField>

<ParamField body="Root.minStepsBetweenValues" type="number" default="0">
  The minimum steps between values in a range slider.
</ParamField>

<ParamField body="Root.name" type="string">
  Identifies the field when a form is submitted.
</ParamField>

<ParamField body="Root.onValueChange" type="((value: TValue extends number ? number : TValue, eventDetails: SliderRootChangeEventDetails) => 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
</ParamField>

<ParamField body="Root.onValueCommitted" type="((value: TValue extends number ? number : TValue, eventDetails: SliderRootCommitEventDetails) => 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
</ParamField>

<ParamField body="Root.orientation" type="&#x22;horizontal&#x22; | &#x22;vertical&#x22;" default="horizontal">
  The component orientation.
</ParamField>

<ParamField body="Root.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SliderRootState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Root.step" type="number" default="1">
  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.
</ParamField>

<ParamField body="Root.style" type="CSSProperties | ((state: SliderRootState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

<ParamField body="Root.thumbAlignment" type="&#x22;center&#x22; | &#x22;edge&#x22; | &#x22;edge-client-only&#x22;" default="edge">
  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
</ParamField>

<ParamField body="Root.thumbCollisionBehavior" type="&#x22;push&#x22; | &#x22;none&#x22; | &#x22;swap&#x22;" default="push">
  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.
</ParamField>

<ParamField body="Root.value" type="number | readonly number[]">
  The value of the slider.
  For range sliders, provide an array with one value per thumb.
</ParamField>

### Slider.Control

<ParamField body="Control.className" type="string | ((state: SliderControlState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Control.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SliderControlState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Control.style" type="CSSProperties | ((state: SliderControlState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### Slider.Track

<ParamField body="Track.className" type="string | ((state: SliderTrackState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Track.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SliderTrackState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Track.style" type="CSSProperties | ((state: SliderTrackState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### Slider.Indicator

<ParamField body="Indicator.className" type="string | ((state: SliderIndicatorState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Indicator.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SliderIndicatorState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Indicator.style" type="CSSProperties | ((state: SliderIndicatorState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### Slider.Thumb

<ParamField body="Thumb.aria-valuetext" type="string">
  A string value forwarded to the [`aria-valuetext`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-valuetext) attribute of the `input`.
  Ignored when `getAriaValueText` is provided.
</ParamField>

<ParamField body="Thumb.className" type="string | ((state: SliderThumbState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Thumb.disabled" type="boolean" default="false">
  Whether the thumb should ignore user interaction.
</ParamField>

<ParamField body="Thumb.getAriaLabel" type="((index: number) => string) | null">
  A function which returns a string value for the [`aria-label`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-label) attribute of the `input`.
</ParamField>

<ParamField body="Thumb.getAriaValueText" type="((formattedValue: string, value: number, index: number) => string) | null">
  A function which returns a string value for the [`aria-valuetext`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-valuetext) attribute of the `input`.
  This is important for screen reader users.
</ParamField>

<ParamField body="Thumb.index" type="number">
  The index of the thumb which corresponds to the index of its value in the
  `value` or `defaultValue` array.
  This prop is required to support server-side rendering for range sliders
  with multiple thumbs.
</ParamField>

<ParamField body="Thumb.inputRef" type="Ref<HTMLInputElement>">
  A ref to access the nested input element.
</ParamField>

<ParamField body="Thumb.onBlur" type="FocusEventHandler<HTMLInputElement>">
  A blur handler forwarded to the `input`.
</ParamField>

<ParamField body="Thumb.onFocus" type="FocusEventHandler<HTMLInputElement>">
  A focus handler forwarded to the `input`.
</ParamField>

<ParamField body="Thumb.onKeyDown" type="KeyboardEventHandler<HTMLInputElement>">
  A keydown handler forwarded to the `input`.
</ParamField>

<ParamField body="Thumb.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SliderThumbState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Thumb.style" type="CSSProperties | ((state: SliderThumbState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

<ParamField body="Thumb.tabIndex" type="number">
  Optional tab index attribute forwarded to the `input`.
</ParamField>

### Slider.Label

<ParamField body="Label.className" type="string | ((state: SliderRootState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Label.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SliderRootState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Label.style" type="CSSProperties | ((state: SliderRootState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### Slider.Value

<ParamField body="Value.className" type="string | ((state: SliderValueState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Value.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SliderValueState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Value.style" type="CSSProperties | ((state: SliderValueState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>
