Skip to main content

Overview

The Slider component provides an accessible range input with customizable value formatting and smooth interactions. Built on React Aria Components for full keyboard navigation and screen reader support.

Import

import { Slider } from 'stride-ds';

Basic Usage

import { Slider } from 'stride-ds';

function Example() {
  return <Slider label="Volume" defaultValue={[50]} />;
}

With Custom Range

<Slider 
  label="Temperature" 
  defaultValue={[22]}
  minValue={15}
  maxValue={30}
/>

Value Formatting

Format the displayed value:
<Slider 
  label="Volume" 
  defaultValue={[75]}
  formatValue={(value) => `${value}%`}
/>

Temperature Example

<Slider 
  label="Temperature" 
  defaultValue={[22]}
  minValue={15}
  maxValue={30}
  formatValue={(value) => `${value}°C`}
/>

Currency Example

<Slider 
  label="Price Range" 
  defaultValue={[500]}
  minValue={0}
  maxValue={1000}
  step={50}
  formatValue={(value) => `$${value}`}
/>

Without Label or Output

Without Label

<Slider defaultValue={[75]} />

Without Output Value

<Slider 
  label="Brightness" 
  defaultValue={[25]}
  showOutput={false}
/>

Step Increment

<Slider 
  label="Volume" 
  defaultValue={[50]}
  step={10} // Snap to increments of 10
/>

Precision Slider

<Slider 
  label="Precision" 
  defaultValue={[3.14]}
  minValue={0}
  maxValue={10}
  step={0.01}
  formatValue={(value) => value.toFixed(2)}
/>

Disabled State

<Slider 
  label="Disabled Slider" 
  defaultValue={[40]}
  isDisabled
/>

Props

label
string
Label text displayed above the slider.
defaultValue
number[]
Initial value of the slider (uncontrolled). Must be an array with one element.
value
number[]
Current value of the slider (controlled). Must be an array with one element.
onChange
(value: number[]) => void
Handler called when the slider value changes.
minValue
number
default:"0"
Minimum value of the slider.
maxValue
number
default:"100"
Maximum value of the slider.
step
number
default:"1"
Step increment for the slider. Use decimals for precision (e.g., 0.01).
formatValue
(value: number) => string
Function to format the displayed value. Default shows the raw number.
showOutput
boolean
default:"true"
Whether to show the current value next to the label.
isDisabled
boolean
default:"false"
Whether the slider is disabled.
className
string
Additional CSS classes for the wrapper.
trackClassName
string
Additional CSS classes for the track element.
thumbClassName
string
Additional CSS classes for the thumb element.

Accessibility

The Slider component is built with React Aria Components and provides:
  • Keyboard Navigation:
    • Arrow Left/Down: Decrease value
    • Arrow Right/Up: Increase value
    • Home: Jump to minimum
    • End: Jump to maximum
    • Page Up/Down: Large increment/decrement
  • Focus Management: Clear focus indicators
  • Screen Reader Support: Proper ARIA attributes including role="slider", aria-valuemin, aria-valuemax, aria-valuenow, and aria-valuetext
  • Value Announcements: Current value is announced when changed

Best Practices

  1. Always provide a label for accessibility:
    <Slider label="Volume" defaultValue={[50]} />
    
  2. Use appropriate step values:
    <Slider step={10} /> // Coarse adjustment
    <Slider step={1} />  // Fine adjustment
    <Slider step={0.1} /> // Precision
    
  3. Format values for better understanding:
    <Slider 
      label="Volume"
      formatValue={(v) => `${v}%`}
    />
    

Examples

Audio Level Slider

<Slider 
  label="Audio Level" 
  defaultValue={[65]}
  minValue={0}
  maxValue={100}
  step={5}
  formatValue={(value) => {
    if (value === 0) return 'Mute';
    if (value <= 30) return 'Low';
    if (value <= 70) return 'Medium';
    return 'High';
  }}
/>

Multiple Sliders

<div className="space-y-8">
  <Slider label="Volume" defaultValue={[25]} />
  <Slider label="Brightness" defaultValue={[50]} />
  <Slider label="Contrast" defaultValue={[75]} />
</div>

Enabled vs Disabled Comparison

<div className="space-y-8">
  <div>
    <h3 className="text-lg font-semibold mb-4">Enabled State</h3>
    <Slider
      label="Volume (Enabled)"
      defaultValue={[60]}
      formatValue={(v) => `${v}%`}
    />
  </div>

  <div>
    <h3 className="text-lg font-semibold mb-4">Disabled State</h3>
    <Slider
      label="Volume (Disabled)"
      defaultValue={[60]}
      formatValue={(v) => `${v}%`}
      isDisabled
    />
  </div>
</div>

Controlled Slider

import { useState } from 'react';
import { Slider } from 'stride-ds';

function ControlledExample() {
  const [value, setValue] = useState([50]);

  return (
    <div className="space-y-6">
      <Slider
        label="Master Volume"
        value={value}
        onChange={setValue}
        formatValue={(v) => `${v}%`}
      />

      <div className="p-4 bg-gray-100 rounded-lg">
        <p className="text-sm">
          Current value: <strong>{value[0]}%</strong>
        </p>
      </div>
    </div>
  );
}

Percentage Slider

<Slider 
  label="Completion" 
  defaultValue={[87]}
  minValue={0}
  maxValue={100}
  formatValue={(value) => `${value}%`}
/>

Temperature Control

<Slider 
  label="Room Temperature" 
  defaultValue={[22]}
  minValue={15}
  maxValue={30}
  step={0.5}
  formatValue={(value) => `${value}°C`}
/>

Price Range

<Slider 
  label="Maximum Price" 
  defaultValue={[500]}
  minValue={0}
  maxValue={2000}
  step={50}
  formatValue={(value) => `$${value.toLocaleString()}`}
/>

With onChange Handler

import { Slider } from 'stride-ds';

function OnChangeExample() {
  const handleChange = (newValue: number[]) => {
    console.log('Slider changed to:', newValue[0]);
    // Perform action based on value
  };

  return (
    <Slider
      label="Volume"
      defaultValue={[50]}
      onChange={handleChange}
      formatValue={(v) => `${v}%`}
    />
  );
}

Interactive Settings Panel

import { useState } from 'react';
import { Slider } from 'stride-ds';

function SettingsPanel() {
  const [settings, setSettings] = useState({
    volume: [75],
    brightness: [60],
    contrast: [50],
  });

  return (
    <div className="space-y-6">
      <h3 className="text-lg font-semibold">Display & Audio Settings</h3>
      
      <Slider
        label="Volume"
        value={settings.volume}
        onChange={(v) => setSettings({ ...settings, volume: v })}
        formatValue={(v) => `${v}%`}
      />
      
      <Slider
        label="Brightness"
        value={settings.brightness}
        onChange={(v) => setSettings({ ...settings, brightness: v })}
        formatValue={(v) => `${v}%`}
      />
      
      <Slider
        label="Contrast"
        value={settings.contrast}
        onChange={(v) => setSettings({ ...settings, contrast: v })}
        formatValue={(v) => `${v}%`}
      />
    </div>
  );
}

Form Integration

The Slider component works with form libraries:
import { useForm, Controller } from 'react-hook-form';
import { Slider } from 'stride-ds';

function FormExample() {
  const { control, handleSubmit } = useForm();

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="volume"
        control={control}
        defaultValue={[50]}
        render={({ field }) => (
          <Slider
            label="Volume"
            value={field.value}
            onChange={field.onChange}
            formatValue={(v) => `${v}%`}
          />
        )}
      />
    </form>
  );
}

Build docs developers (and LLMs) love