Light

Slider

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

Spec · from metadata

When to use

  • Selecting a value within a continuous range (e.g., volume, price)
  • Range selection with two thumbs (e.g., price range filter)
  • Numeric input where approximate value is acceptable

When not to use

  • Precise numeric input — use Input with type='number' instead
  • Discrete choices — use RadioGroup or Select instead
  • Binary on/off — use Switch instead

Anti-patterns

Avoid<Slider defaultValue={50} />
Prefer<Slider defaultValue={[50]} max={100} step={1} />

Slider value must be an array, even for single-thumb usage.

Avoid<Slider orientation="vertical" />
Prefer<div className="h-44">
  <Slider orientation="vertical" defaultValue={[50]} />
</div>

Vertical sliders need a container with explicit height. The component sets min-h-44 but the parent must allow it.

Accessibility

  • Required ARIAaria-label or aria-labelledbyaria-valuemin (auto from min prop)aria-valuemax (auto from max prop)aria-valuenow (auto from value)
  • Min touch target16px
  • Screen readerBuilt on Radix Slider which manages ARIA slider attributes. Announce min, max, and current value.
  • ContrastThumb uses bg-background with border-primary for clear visibility.

Token bindings

TokenCategoryUsage
primarycolorTrack fill and thumb border
mutedcolorTrack background
backgroundcolorThumb background
ringcolorHover/focus ring

Import

import { Slider } from "@timelycare/helix-ui"

Props

interface SliderProps {
  value?: number[]
  defaultValue?: number[]
  min?: number
  max?: number
  step?: number
  onValueChange?: (value: number[]) => void
  disabled?: boolean
  orientation?: "horizontal" | "vertical"
  className?: string
}

Structure

PartTailwind
Rootrelative flex w-full touch-none select-none items-center
Trackrelative h-1.5 w-full grow overflow-hidden rounded-full bg-muted
Range (filled)absolute h-full bg-primary rounded-full
Thumbsize-4 rounded-full border border-primary bg-background shadow-sm

Thumb States

StateTailwind
Defaultsize-4 rounded-full border border-primary bg-background shadow-sm
Hoverring-2 ring-muted-foreground/50 (outer glow)
Focusring-2 ring-ring ring-offset-2
Disabledopacity-50 pointer-events-none

Variants

VariantUse ForValue Format
SingleVolume, brightnessdefaultValue={[50]}
RangePrice range, min/maxdefaultValue={[25, 75]}

Common Patterns

Single Value

<Slider defaultValue={[50]} max={100} step={1} />

Range Selection

<Slider defaultValue={[25, 75]} max={100} step={1} />

With Label and Value Display

const [value, setValue] = useState([50])

<div className="space-y-2">
  <div className="flex justify-between">
    <Label>Volume</Label>
    <span className="text-sm text-muted-foreground">{value}%</span>
  </div>
  <Slider
    value={value}
    onValueChange={setValue}
    max={100}
    step={1}
  />
</div>

Vertical Orientation

<Slider
  defaultValue={[50]}
  max={100}
  orientation="vertical"
  className="h-[200px]"
/>

Sizing

PartValue
Track heighth-1.5 (6px)
Thumb sizesize-4 (16px)
Track widthw-full (horizontal)
Vertical heightCustom via className

Accessibility

  • Built on Radix Slider — handles keyboard and focus automatically
  • Keyboard: Arrow keys to adjust, Page Up/Down for larger steps, Home/End for min/max
  • Screen reader: announces current value
  • Requires label association via Label component
  • Supports range selection with multiple thumbs

Gotchas

ProblemSolution
Value must be arrayUse value={[50]} not value={50}
Range needs two valuesdefaultValue={[25, 75]}
Vertical needs heightAdd className="h-[200px]"
Controlled not updatingUse onValueChange callback
Thumb touch target smallConsider wrapper padding for mobile

See Also


Last updated: February 9, 2026