Skip to main content
Gremorie

Slider

Continuous numeric input via draggable thumb - single or range, horizontal or vertical, with a `thumbAriaLabel` extension for multi-thumb accessibility.

Overview

Slider wraps @radix-ui/react-slider. Single thumb by default; pass defaultValue={[low, high]} (or value) for a range slider. Honors step, min, max, and orientation="vertical".

Use Slider when approximate position is more useful than exact precision - volume, brightness, price filters. For exact values use a number Input. For discrete choices, prefer RadioGroup or Select. Always show the current value next to the slider; silent sliders confuse users.

Preview

Installation

bash npx gremorie@latest add rx-slider
bash pnpm dlx gremorie@latest add rx-slider
bash yarn dlx gremorie@latest add rx-slider
bash bunx --bun gremorie@latest add rx-slider

Usage

import { Slider } from "@gremorie/rx-forms";

export function Example() {
  return <Slider defaultValue={[40]} max={100} step={1} />;
}

Angular edition planned for Phase 5h. Star the repo to track progress.

API

<Slider>

PropTypeDefaultDescription
valuenumber[]-Controlled value(s). One number for single thumb; two for range.
defaultValuenumber[][min, max]Uncontrolled initial value(s).
onValueChange(value: number[]) => void-Fires on every drag step.
onValueCommit(value: number[]) => void-Fires when the user releases the thumb (useful for network commits).
minnumber0Minimum value.
maxnumber100Maximum value.
stepnumber1Increment between allowed values.
orientation"horizontal" | "vertical""horizontal"Vertical sliders default to min-h-44 so they have something to drag along.
disabledbooleanfalseDisables interaction.
namestring-Form field name.
thumbAriaLabelstring | string[]-Gremorie extension (not in shadcn default). Accessible name for each thumb. Pass an array for range sliders, e.g. ["Minimum price", "Maximum price"]. Required for WCAG 4.1.2 when the slider lacks an adjacent <Label>.
aria-labelstring-Falls back to this for thumb labels when thumbAriaLabel is not set.

Forwards to SliderPrimitive.Root. Renders SliderPrimitive.Track, SliderPrimitive.Range, and one SliderPrimitive.Thumb per value.

thumbAriaLabel is a Gremorie addition to the standard shadcn Slider. Without it, range sliders announce two unnamed thumbs and fail WCAG 4.1.2 (Name, Role, Value). Always set it for range / multi-thumb sliders.

Composition

  1. <Slider> is a leaf primitive that renders track + range + one thumb per value.
  2. Pair with a <Label> (associated via aria-labelledby if no htmlFor target exists) or set aria-label directly on the root.
  3. Show the current value next to the slider - users expect a numeric readout to confirm where they are.
  4. For form-bound usage, wrap with <FormField> + <FormControl> and convert the array value back to a number (or array) for your form schema.

Variations

Single thumb

The canonical pattern. Show the value alongside.

function Volume() {
  const [value, setValue] = React.useState([40]);
  return (
    <div className="grid gap-2">
      <div className="flex items-center justify-between">
        <Label>Volume</Label>
        <span className="text-sm tabular-nums text-muted-foreground">
          {value[0]}%
        </span>
      </div>
      <Slider
        value={value}
        onValueChange={setValue}
        max={100}
        step={1}
        aria-label="Volume"
      />
    </div>
  );
}

Range slider

Pass two values for defaultValue (or value). Always set thumbAriaLabel as an array so each thumb has a unique name.

<Slider
  defaultValue={[20, 80]}
  min={0}
  max={100}
  step={1}
  thumbAriaLabel={['Minimum price', 'Maximum price']}
/>

Stepped slider

Use a larger step for discrete values like rating or font size.

<Slider defaultValue={[3]} min={1} max={5} step={1} aria-label="Rating" />

Vertical orientation

Useful for media controls, color pickers, or any UI where horizontal space is precious.

<div className="h-44">
  <Slider defaultValue={[60]} orientation="vertical" aria-label="Brightness" />
</div>

Accessibility

  • ARIA: each thumb is a role="slider" with aria-valuemin, aria-valuemax, aria-valuenow, and aria-orientation set by Radix.
  • Keyboard:
    • ArrowLeft / ArrowDown decrement by step.
    • ArrowRight / ArrowUp increment by step.
    • PageDown / PageUp change by larger increments (typically 10x step).
    • Home jumps to min; End jumps to max.
  • Multi-thumb: each thumb is independently focusable; Radix prevents thumbs from crossing each other.
  • thumbAriaLabel: set it for any range / multi-thumb slider so each thumb announces a specific name. Without it, screen readers fall back to aria-label of the root, then to a generic "Slider thumb 1".
  • Disabled: data-disabled removes the thumbs from the tab order and drops opacity to 50%.
  • Always show the value: visually display the current value so all users (not only screen reader users) get the same feedback.
  • Input - use for exact numeric values
  • Form - wire Slider into react-hook-form
  • Label - the canonical companion

On this page