Skip to main content

Slider

Slider is a form control that lets people choose a number or range within set bounds, such as volume or a price filter.

Import

import { Slider } from '@vortexlabs/vortex';
import type { SliderProps } from '@vortexlabs/vortex';

Other links

Drag to adjust the volume.
<Stack
  width="320px"
  maxWidth="100%"
>
  <Slider.Root>
    <Slider.Label>Volume</Slider.Label>
  <Slider.Control name="playground-volume" defaultValue={40} />
  <Slider.HelperText>Drag to adjust the volume.</Slider.HelperText>
  <Slider.ErrorMessage>Volume is too high.</Slider.ErrorMessage>
  </Slider.Root>
</Stack>

Features

  • Supports single values and ranges.
  • Supports custom bounds and steps.
  • Formats the tooltip value.
  • Reports live and final values.
  • Supports horizontal and vertical layouts.
  • Shows helper text, errors, and disabled states.

Anatomy

<Slider.Root>
  <Slider.Label>Volume</Slider.Label>
  <Slider.Control name="volume" />
  <Slider.HelperText>Adjust the playback volume.</Slider.HelperText>
  <Slider.ErrorMessage>Choose a volume.</Slider.ErrorMessage>
</Slider.Root>
Component Part
Description
Shares disabled and error state with its parts.
Names the slider.
Renders the track and handles, and submits the value under name.
Adds supporting text below the slider.
Explains the error while error is set.

Bounds and Steps

Set min, max, and step to define the available values, and defaultValue to choose the starting point.

Adjust in steps of five.
import { Slider } from "@vortexlabs/vortex";

<Slider.Root>
  <Slider.Label>Volume</Slider.Label>
  <Slider.Control name="volume" min={0} max={100} step={5} defaultValue={40} />
  <Slider.HelperText>Adjust in steps of five.</Slider.HelperText>
</Slider.Root>

Range Selection

Set range and give each handle a minLabel and maxLabel. Use minName and maxName to submit separate form values, or one shared name.

Minimum priceMaximum price
Choose a minimum and maximum price.
<Slider.Root>
  <Slider.Label>Price range</Slider.Label>
  <Slider.Control
    range
    minName="min-price"
    maxName="max-price"
    minLabel="Minimum price"
    maxLabel="Maximum price"
    min={0}
    max={500}
    step={25}
    defaultMinValue={100}
    defaultMaxValue={350}
  />
  <Slider.HelperText>Choose a minimum and maximum price.</Slider.HelperText>
</Slider.Root>

Controlled Values and Commit Events

Use value with onChange to track the value as it changes. onChangeCommit fires once the interaction ends, which suits expensive work like applying a filter.

Current: 40 km. Applied: 40 km.
"use client";

import { Slider } from "@vortexlabs/vortex";
import React from "react";

export const SliderControlledExample = () => {
  const [value, setValue] = React.useState(40);
  const [committed, setCommitted] = React.useState(40);
  return (
    <Slider.Root>
      <Slider.Label>Search radius</Slider.Label>
      <Slider.Control
        name="radius"
        min={5}
        max={100}
        step={5}
        value={value}
        onChange={({ value }) => setValue(value)}
        onChangeCommit={({ value }) => setCommitted(value)}
      />
      <Slider.HelperText>
        Current: {value} km. Applied: {committed} km.
      </Slider.HelperText>
    </Slider.Root>
  );
};

Controlled Range

A controlled range takes minValue and maxValue. onChange reports both, so update them together.

Minimum temperatureMaximum temperature
20–70 degrees
"use client";

import { Slider } from "@vortexlabs/vortex";
import React from "react";

export const SliderRangeExample = () => {
  const [range, setRange] = React.useState({ minValue: 20, maxValue: 70 });
  return (
    <Slider.Root>
      <Slider.Label>Temperature range</Slider.Label>
      <Slider.Control
        range
        name="temperature"
        minLabel="Minimum temperature"
        maxLabel="Maximum temperature"
        min={0}
        max={100}
        minValue={range.minValue}
        maxValue={range.maxValue}
        onChange={({ minValue, maxValue }) => setRange({ minValue, maxValue })}
      />
      <Slider.HelperText>
        {range.minValue}–{range.maxValue} degrees
      </Slider.HelperText>
    </Slider.Root>
  );
};

Value Formatting

Use renderValue to format the tooltip and the value screen readers announce. Pass false to hide the tooltip.

"use client";

import { Slider, Stack } from "@vortexlabs/vortex";

export const SliderFormatExample = () => {
  return (
    <Stack gap={6} width="100%">
      <Slider.Root>
        <Slider.Label>Playback speed</Slider.Label>
        <Slider.Control
          name="playback-speed"
          min={0.5}
          max={2}
          step={0.25}
          defaultValue={1}
          renderValue={({ value }) => value + "× speed"}
        />
      </Slider.Root>
      <Slider.Root>
        <Slider.Label>Background intensity</Slider.Label>
        <Slider.Control name="intensity" defaultValue={30} renderValue={false} />
      </Slider.Root>
    </Stack>
  );
};

Vertical

Set orientation="vertical" and place the slider in a container with a set height.

<Stack height="16rem">
  <Slider.Root>
    <Slider.Label>Volume</Slider.Label>
    <Slider.Control name="vertical-volume" orientation="vertical" defaultValue={60} />
  </Slider.Root>
</Stack>

Disabled and Error States

Set disabled or error on Slider.Root. Slider.ErrorMessage shows only when error is set.

This allocation exceeds your remaining storage.
<Stack gap={6} width="100%">
  <Slider.Root disabled>
    <Slider.Label>Managed volume</Slider.Label>
    <Slider.Control name="managed-volume" defaultValue={50} />
  </Slider.Root>
  <Slider.Root error>
    <Slider.Label>Storage allocation</Slider.Label>
    <Slider.Control name="storage-allocation" defaultValue={90} />
    <Slider.ErrorMessage>This allocation exceeds your remaining storage.</Slider.ErrorMessage>
  </Slider.Root>
</Stack>

Accessibility

Key
Description
Up arrowDown arrowLeft arrowRight arrow
Move the focused handle by one step.
Page UpPage Down
Move the focused handle by a larger, browser-defined step.
HomeEnd
Move the focused handle to its minimum or maximum.
Provide Slider.Label, or an aria-label through inputAttributes, to name the slider.
Provide distinct minLabel and maxLabel when range is set.
Use renderValue when the raw number needs units to make sense.