# Slider A single-thumb slider for selecting a numeric value within a range. It is built on top of [the `Range` component](./range.mdx), and exposes the same behavior through a single-value API. ```tsx demo import { Slider } from "@tenstorrent/vesper/slider"; export default function SliderDemo() { return ; } ``` ## Options | Prop | Type | Description | Default | | ---------------- | ------------------------- | --------------------------------------------------------------------------------------------- | ------- | | `thumbAriaLabel` | `string` | The accessible `aria-label` for the thumb. Required. | — | | `value` | `number` | The value of the thumb (controlled mode). | — | | `defaultValue` | `number` | The initial thumb value (uncontrolled mode). | `min` | | `onValueChange` | `(value: number) => void` | Callback fired as the thumb value changes during interaction. | — | | `onValueCommit` | `(value: number) => void` | Callback fired when the thumb interaction is completed, eg. on pointer up. | — | | `min` | `number` | The minimum allowed value. | `0` | | `max` | `number` | The maximum allowed value. | `100` | | `step` | `number` | The stepping interval between selectable values. | `1` | | `showTicks` | `boolean` | When `true`, renders tick marks along the track at each step interval. | `false` | | `showValueLabel` | `boolean` | When `true`, displays a value label above the thumb. | `false` | | `valueLabel` | `string` | A custom display label for the thumb. When unset, it falls back to the thumb's current value. | — | | `disabled` | `boolean` | When `true`, prevents interaction. | `false` | | `name` | `string` | The form field name submitted with form data. | — | | `form` | `string` | Associates the slider with a `
` element by its `id`. | — | All other props are forwarded to the wrapping `
` element. If you need to select a span of values rather than a single one, reach for [the `Range` component](./range.mdx) instead: it renders the same track, but with a thumb per value. ## Examples ### Uncontrolled vs controlled Render a `Slider` in an **uncontrolled** fashion to let it keep track of its own value. Pass `defaultValue` if the thumb should start somewhere other than `min`: ```tsx demo import { Slider } from "@tenstorrent/vesper/slider"; export default function UncontrolledSlider() { return ; } ``` If you need to control the value, use the `value` and `onValueChange` props. `onValueChange` fires continuously as the thumb is dragged: ```tsx demo import { useState } from "react"; import { Slider } from "@tenstorrent/vesper/slider"; export default function ControlledSlider() { const [volume, setVolume] = useState(75); return ( ); } ``` Use `onValueCommit` when you only care about the final value of an interaction, eg. to avoid firing a request on every pointer move: ```tsx import { Slider } from "@tenstorrent/vesper/slider"; export default function VolumeSlider() { return ( savePreference({ volume })} thumbAriaLabel="Volume" /> ); } ``` ### Bounds and stepping `min`, `max`, and `step` describe the values the thumb can take, defaulting to `0`, `100`, and `1`. A `step` of `100` on a range of `0-1000` restricts the thumb to multiples of 100: ```tsx demo import { Slider } from "@tenstorrent/vesper/slider"; export default function LargeStepSlider() { return ( ); } ``` The `step` also determines how far the thumb moves per arrow key press when it is focused. > [!NOTE] > > When neither `value` nor `defaultValue` is provided, the thumb starts at `min` rather than at zero, so a slider with a `min` of `10` starts at `10`. ### Showing ticks Pass `showTicks` to mark each step along the track. Ticks are rendered between `min` and `max`, so a range of `0-10` with a `step` of `1` renders nine of them: ```tsx demo import { Slider } from "@tenstorrent/vesper/slider"; export default function SliderWithTicks() { return ( ); } ``` > [!NOTE] > > Ticks are drawn per step, so a fine `step` on a wide range produces a dense, noisy track. Ticks work best when the range has a handful of stops, eg. a range of `0-100` with a `step` of `10`. ### Value label Pass `showValueLabel` to render the thumb's current value above it as you drag: ```tsx demo import { Slider } from "@tenstorrent/vesper/slider"; export default function SliderWithVisibleValueLabel() { return ; } ``` Use `valueLabel` to display something other than the raw value, such as a formatted or unit-suffixed one. It is only rendered when `showValueLabel` is also passed: ```tsx demo import { useState } from "react"; import { Slider } from "@tenstorrent/vesper/slider"; export default function SliderWithCustomValueLabel() { const [volume, setVolume] = useState(40); return ( ); } ``` > [!IMPORTANT] > > Value label is presentational, and is not announced by assistive technology. > > Screen readers announce the underlying numeric value of a thumb instead. If a label carries meaning that the number alone doesn't, such as a currency or a unit, include it in the `thumbAriaLabel` too. ### Keyboard interaction The thumb is a native ``, so a `Slider` is fully keyboard operable once it is focused: | Key | Behaviour | | ------------------------- | ---------------------------------------------- | | `ArrowRight` / `ArrowUp` | Increases the value by `step`. | | `ArrowLeft` / `ArrowDown` | Decreases the value by `step`. | | `Shift` + any arrow key | Moves the thumb by 10 units instead of `step`. | | `PageUp` / `PageDown` | Increases / decreases the value by 10 units. | | `Home` | Moves the thumb to `min`. | | `End` | Moves the thumb to `max`. | ### Disabling the slider Pass `disabled` to prevent all interaction. A disabled `Slider` still displays its current value, but its thumb is skipped in the tab order and excluded from form data: ```tsx demo import { Slider } from "@tenstorrent/vesper/slider"; export default function DisabledSlider() { return ; } ``` ### Usage in forms The thumb renders a native ``, so passing a `name` includes its value in form submissions. Use the `form` prop to associate the field with a `` rendered elsewhere on the page: ```tsx demo import { useState } from "react"; import { Button } from "@tenstorrent/vesper/button"; import { Slider } from "@tenstorrent/vesper/slider"; import { Typography } from "@tenstorrent/vesper/typography"; export default function FormSliderDemo() { const [submitted, setSubmitted] = useState(null); return ( { event.preventDefault(); const data = new FormData(event.currentTarget); setSubmitted(String(data.get("volume") ?? "")); }} > {submitted !== null && ( Submitted value: {submitted} )} ); } ``` A range input always has a value, so a `Slider` submits its current value even if the user never touches it. The form above submits `volume=50` on an untouched slider.