Components

Slider

Input control for selecting a numeric value or range by dragging a thumb.

Category: Form — Pattern: Base UI Slider

Dependency: @base-ui-components/react/slider

Preview

Loading preview...
import {
  Slider,
  SliderTrack,
  SliderRange,
  SliderThumb,
  SliderOutput,
} from "@hareru/ui"

<Slider defaultValue={40}>
  <SliderOutput />
  <SliderTrack>
    <SliderRange />
    <SliderThumb />
  </SliderTrack>
</Slider>

Import

import {
  Slider,
  SliderTrack,
  SliderRange,
  SliderThumb,
  SliderOutput,
  sliderVariants,
} from "@hareru/ui"

Exports

NameTypeDescription
SliderComponentRoot slider context; accepts value, range, and interaction props
SliderTrackComponentThe track bar along which the thumb moves
SliderRangeComponentFilled portion of the track between origin and thumb(s)
SliderThumbComponentDraggable handle; one per value in a range slider
SliderOutputComponentLive readout of the current value; can be placed freely inside Slider
sliderVariantsCVA functionCVA variant function for size variants

Key Props

Slider

PropTypeDefaultDescription
valuenumber | readonly number[]Controlled value; single number or array for range
defaultValuenumber | readonly number[]Initial uncontrolled value
onValueChange(value: number | readonly number[]) => voidCallback fired while dragging
onValueCommitted(value: number | readonly number[]) => voidCallback fired when the user releases the thumb
minnumber0Minimum allowed value
maxnumber100Maximum allowed value
stepnumber1Increment between steps
disabledbooleanfalseDisables all interaction
orientation'horizontal' | 'vertical''horizontal'Slider orientation
namestringForm field name for native form submission
size'sm' | 'md' | 'lg''md'Visual size variant (CVA)

SliderThumb Props

PropTypeDefaultDescription
indexnumberIndex of this thumb in a range slider (0 for the first, 1 for the second)
disabledbooleanfalseDisables this thumb independently
getAriaLabel(index: number) => stringReturns an accessible label for the thumb at index
getAriaValueText(formattedValue: string, value: number, index: number) => stringReturns a human-readable value string for assistive technology
inputRefReact.Ref<HTMLInputElement>Ref forwarded to the underlying hidden <input>

Variants

VariantValuesDescription
sizesm, md, lgControls track height and thumb diameter

Structure

  • SliderTrack [container] (expected)
    • SliderRange [indicator] (expected)
    • SliderThumb [control] (expected) ×N
  • SliderOutput [label]

(expected) = recommended in canonical composition, not runtime-required.

States

StateTypeValuesDefaultCSS Reflection
disabledboolean

Accessibility

  • Roles: slider
  • ARIA attributes: aria-valuemin, aria-valuemax, aria-valuenow, aria-orientation
  • Keyboard:
    • Arrow Left/Right to adjust value
    • Home/End for min/max
    • Page Up/Down for large steps
  • Notes: WAI-ARIA Slider pattern with full keyboard support provided by Base UI.

Usage

import {
  Slider,
  SliderTrack,
  SliderRange,
  SliderThumb,
  SliderOutput,
} from "@hareru/ui"

// Basic
<Slider defaultValue={40}>
  <SliderOutput />
  <SliderTrack>
    <SliderRange />
    <SliderThumb />
  </SliderTrack>
</Slider>

// With output label
<div style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}>
  <div style={{ display: "flex", justifyContent: "space-between" }}>
    <label>Volume</label>
    <Slider defaultValue={60}>
      <SliderOutput />
      <SliderTrack>
        <SliderRange />
        <SliderThumb getAriaLabel={() => "volume"} />
      </SliderTrack>
    </Slider>
  </div>
</div>

// Range slider (two thumbs)
<Slider defaultValue={[20, 80]}>
  <SliderOutput />
  <SliderTrack>
    <SliderRange />
    <SliderThumb index={0} getAriaLabel={() => "minimum price"} />
    <SliderThumb index={1} getAriaLabel={() => "maximum price"} />
  </SliderTrack>
</Slider>

// Vertical orientation
<Slider defaultValue={50} orientation="vertical" style={{ height: "200px" }}>
  <SliderTrack>
    <SliderRange />
    <SliderThumb />
  </SliderTrack>
</Slider>

// Size variants
<Slider defaultValue={30} size="sm">
  <SliderTrack>
    <SliderRange />
    <SliderThumb />
  </SliderTrack>
</Slider>

<Slider defaultValue={30} size="lg">
  <SliderTrack>
    <SliderRange />
    <SliderThumb />
  </SliderTrack>
</Slider>

// Controlled
<Slider value={volume} onValueChange={(v) => setVolume(v as number)}>
  <SliderOutput />
  <SliderTrack>
    <SliderRange />
    <SliderThumb />
  </SliderTrack>
</Slider>

Notes

  • SliderRange and SliderThumb must be placed inside SliderTrack — they rely on the track's layout context for positioning.
  • SliderOutput can be placed freely anywhere inside the Slider root and will always reflect the current value.
  • For range sliders, provide one SliderThumb per value and set the index prop so each thumb corresponds to the correct value.
  • Use getAriaLabel and getAriaValueText on SliderThumb to provide meaningful text for screen readers, especially when multiple thumbs are present.

On this page