Accessible, CSS-agnostic slider component for React applications
npx @tessl/cli install tessl/npm-react-slider@2.0.0React Slider is an accessible, CSS-agnostic slider component for React applications. It provides both single and multi-handle sliders with extensive customization options, accessibility features, keyboard navigation, and comprehensive event handling for user interactions.
npm install react-sliderimport ReactSlider from "react-slider";For CommonJS:
const ReactSlider = require("react-slider");import React, { useState } from "react";
import ReactSlider from "react-slider";
// Single value slider
function SingleSlider() {
const [value, setValue] = useState(50);
return (
<ReactSlider
value={value}
onChange={setValue}
min={0}
max={100}
step={1}
/>
);
}
// Multi-value slider
function MultiSlider() {
const [values, setValues] = useState([20, 80]);
return (
<ReactSlider
value={values}
onChange={setValues}
min={0}
max={100}
minDistance={10}
/>
);
}
// Custom styled slider
function StyledSlider() {
return (
<ReactSlider
className="horizontal-slider"
thumbClassName="slider-thumb"
trackClassName="slider-track"
defaultValue={[20, 80]}
ariaLabel={["Lower thumb", "Upper thumb"]}
renderThumb={(props, state) => (
<div {...props}>
{state.valueNow}
</div>
)}
/>
);
}React Slider is built around several key concepts:
The main slider component providing single and multi-thumb functionality with extensive customization options.
/**
* Accessible, CSS-agnostic slider component for React
* @param props - ReactSlider configuration props
* @returns JSX.Element - Rendered slider component
*/
function ReactSlider(props: ReactSliderProps): JSX.Element;
interface ReactSliderProps {
// Core value props
min?: number;
max?: number;
step?: number;
defaultValue?: number | number[];
value?: number | number[];
minDistance?: number;
// Behavior props
pageFn?: (step: number) => number;
orientation?: 'horizontal' | 'vertical';
disabled?: boolean;
snapDragDisabled?: boolean;
invert?: boolean;
pearling?: boolean;
withTracks?: boolean;
marks?: boolean | number | number[];
// Styling props
className?: string;
thumbClassName?: string;
thumbActiveClassName?: string;
trackClassName?: string;
markClassName?: string;
// Event handler props
onBeforeChange?: (value: number | number[], thumbIndex: number) => void;
onChange?: (value: number | number[], thumbIndex: number) => void;
onAfterChange?: (value: number | number[], thumbIndex: number) => void;
onSliderClick?: (value: number) => void;
// Accessibility props
ariaLabel?: string | string[];
ariaLabelledby?: string | string[];
ariaValuetext?: string | ((state: ThumbState) => string);
// Custom render props
renderThumb?: (props: ThumbProps, state: ThumbState) => React.ReactElement;
renderTrack?: (props: TrackProps, state: TrackState) => React.ReactElement;
renderMark?: (props: MarkProps) => React.ReactElement;
}
interface ThumbState {
index: number;
value: number | number[];
valueNow: number;
}
interface TrackState {
index: number;
value: number | number[];
}
interface ThumbProps {
key: string;
className: string;
style: React.CSSProperties;
onMouseDown: (e: React.MouseEvent) => void;
onTouchStart: (e: React.TouchEvent) => void;
onFocus: (e: React.FocusEvent) => void;
tabIndex: number;
role: string;
'aria-orientation': string;
'aria-valuenow': number;
'aria-valuemin': number;
'aria-valuemax': number;
'aria-label'?: string;
'aria-labelledby'?: string;
'aria-disabled': boolean;
'aria-valuetext'?: string;
}
interface TrackProps {
key: string;
className: string;
style: React.CSSProperties;
}
interface MarkProps {
key: string | number;
className: string;
style: React.CSSProperties;
}Configuration of slider values, constraints, and step behavior.
// Value range configuration
min?: number; // Minimum slider value (default: 0)
max?: number; // Maximum slider value (default: 100)
step?: number; // Value increment/decrement step (default: 1)
// Initial and controlled values
defaultValue?: number | number[]; // Initial value for uncontrolled mode (default: 0)
value?: number | number[]; // Current value for controlled mode
// Multi-thumb constraints
minDistance?: number; // Minimum distance between thumbs (default: 0)Usage Examples:
// Single value slider with custom range
<ReactSlider
min={-100}
max={100}
step={5}
defaultValue={0}
/>
// Multi-value slider with constraints
<ReactSlider
min={0}
max={1000}
step={10}
defaultValue={[200, 800]}
minDistance={50}
/>
// Controlled slider
function ControlledSlider() {
const [value, setValue] = useState(25);
return (
<ReactSlider
value={value}
onChange={setValue}
min={0}
max={100}
/>
);
}Configuration of slider interaction behavior and advanced features.
// Navigation and interaction
pageFn?: (step: number) => number; // Custom Page Up/Down step calculation
orientation?: 'horizontal' | 'vertical'; // Slider orientation (default: 'horizontal')
disabled?: boolean; // Disable all interactions (default: false)
snapDragDisabled?: boolean; // Disable thumb snap on track click (default: false)
invert?: boolean; // Invert slider direction (default: false)
// Advanced behavior
pearling?: boolean; // Enable thumb pushing behavior (default: false)
withTracks?: boolean; // Render tracks between thumbs (default: true)
marks?: boolean | number | number[]; // Show marks on track (default: [])Usage Examples:
// Vertical slider with custom page function
<ReactSlider
orientation="vertical"
pageFn={(step) => step * 5}
defaultValue={50}
/>
// Inverted slider with pearling
<ReactSlider
invert={true}
pearling={true}
defaultValue={[30, 70]}
/>
// Slider with marks
<ReactSlider
marks={[0, 25, 50, 75, 100]}
defaultValue={50}
/>
// Slider with step-based marks
<ReactSlider
marks={10} // Shows marks at 0, 10, 20, 30, etc.
max={100}
step={5}
/>Comprehensive event system for tracking slider interactions and value changes.
/**
* Called before starting to move a thumb (only if value will change)
* @param value - Initial value(s)
* @param thumbIndex - Index of the thumb being moved
*/
onBeforeChange?: (value: number | number[], thumbIndex: number) => void;
/**
* Called on every value change during interaction
* @param value - New value(s)
* @param thumbIndex - Index of the thumb being moved
*/
onChange?: (value: number | number[], thumbIndex: number) => void;
/**
* Called after moving a thumb has ended (only if value changed)
* @param value - Final value(s)
* @param thumbIndex - Index of the thumb that was moved
*/
onAfterChange?: (value: number | number[], thumbIndex: number) => void;
/**
* Called when the slider track is clicked
* @param value - Value at the clicked position
*/
onSliderClick?: (value: number) => void;Usage Examples:
function EventHandlerExample() {
const handleBeforeChange = (value, thumbIndex) => {
console.log('Starting to change:', value, 'thumb:', thumbIndex);
};
const handleChange = (value, thumbIndex) => {
console.log('Changing to:', value, 'thumb:', thumbIndex);
};
const handleAfterChange = (value, thumbIndex) => {
console.log('Final value:', value, 'thumb:', thumbIndex);
};
const handleSliderClick = (value) => {
console.log('Clicked at value:', value);
};
return (
<ReactSlider
onBeforeChange={handleBeforeChange}
onChange={handleChange}
onAfterChange={handleAfterChange}
onSliderClick={handleSliderClick}
defaultValue={[20, 80]}
/>
);
}CSS class configuration for complete visual customization.
// Main styling props
className?: string; // CSS class for slider container (default: 'slider')
thumbClassName?: string; // CSS class for thumb elements (default: 'thumb')
thumbActiveClassName?: string; // CSS class for active thumb (default: 'active')
trackClassName?: string; // CSS class for track elements (default: 'track')
markClassName?: string; // CSS class for mark elements (default: 'mark')Usage Examples:
// Custom CSS classes
<ReactSlider
className="my-slider"
thumbClassName="my-thumb"
thumbActiveClassName="my-active-thumb"
trackClassName="my-track"
markClassName="my-mark"
defaultValue={50}
/>
// Styled with CSS
/*
.my-slider {
width: 100%;
height: 20px;
background: #ddd;
border-radius: 10px;
}
.my-thumb {
width: 24px;
height: 24px;
background: #007bff;
border-radius: 50%;
border: 2px solid white;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
.my-active-thumb {
background: #0056b3;
}
.my-track {
background: #007bff;
border-radius: 10px;
}
*/Complete accessibility support with ARIA attributes and keyboard navigation.
// ARIA labeling
ariaLabel?: string | string[]; // ARIA label for thumbs
ariaLabelledby?: string | string[]; // ARIA labelledby for thumbs
ariaValuetext?: string | ((state: ThumbState) => string); // ARIA valuetext
interface ThumbState {
index: number; // Thumb index
value: number | number[]; // Current slider value(s)
valueNow: number; // Current thumb value
}Usage Examples:
// Accessibility labels
<ReactSlider
ariaLabel={["Minimum value", "Maximum value"]}
defaultValue={[20, 80]}
/>
// Dynamic aria-valuetext
<ReactSlider
ariaValuetext={(state) => `${state.valueNow}% completed`}
defaultValue={75}
/>
// Connected with external labels
<div>
<label id="temp-label">Temperature Range</label>
<ReactSlider
ariaLabelledby="temp-label"
min={-10}
max={40}
defaultValue={[18, 25]}
/>
</div>Advanced customization through render prop functions for complete visual control.
/**
* Custom render function for thumb elements
* @param props - Props to spread into thumb element
* @param state - Current thumb and slider state
* @returns React element for the thumb
*/
renderThumb?: (props: ThumbProps, state: ThumbState) => React.ReactElement;
/**
* Custom render function for track elements
* @param props - Props to spread into track element
* @param state - Current track and slider state
* @returns React element for the track
*/
renderTrack?: (props: TrackProps, state: TrackState) => React.ReactElement;
/**
* Custom render function for mark elements
* @param props - Props to spread into mark element
* @returns React element for the mark
*/
renderMark?: (props: MarkProps) => React.ReactElement;Usage Examples:
// Custom thumb with value display
<ReactSlider
renderThumb={(props, state) => (
<div {...props} className="custom-thumb">
<span className="thumb-value">{state.valueNow}</span>
</div>
)}
defaultValue={[20, 80]}
/>
// Custom track with gradient
<ReactSlider
renderTrack={(props, state) => (
<div
{...props}
className={`custom-track track-${state.index}`}
style={{
...props.style,
background: state.index === 1
? 'linear-gradient(to right, #ff6b6b, #4ecdc4)'
: '#e9ecef'
}}
/>
)}
defaultValue={[30, 70]}
/>
// Custom marks with labels
<ReactSlider
marks={[0, 25, 50, 75, 100]}
renderMark={(props) => (
<span {...props} className="custom-mark">
{props.key}%
</span>
)}
defaultValue={50}
/>Built-in keyboard support for accessibility and ease of use.
Supported Keys:
pageFn)pageFn)Usage Examples:
// Custom page step function
<ReactSlider
pageFn={(step) => step * 5} // Page Up/Down moves by 5x step
step={2}
defaultValue={50}
/>/**
* Returns the current slider value(s) in output format
* @returns Current value (number for single thumb, array for multiple thumbs)
*/
getValue(): number | number[];Usage Examples:
function SliderWithRef() {
const sliderRef = useRef(null);
const getCurrentValue = () => {
if (sliderRef.current) {
console.log('Current value:', sliderRef.current.getValue());
}
};
return (
<div>
<ReactSlider ref={sliderRef} defaultValue={[20, 80]} />
<button onClick={getCurrentValue}>Get Current Value</button>
</div>
);
}// Default prop values applied when not specified
const defaultProps = {
min: 0,
max: 100,
step: 1,
pageFn: (step) => step * 10,
minDistance: 0,
defaultValue: 0,
orientation: 'horizontal',
className: 'slider',
thumbClassName: 'thumb',
thumbActiveClassName: 'active',
trackClassName: 'track',
markClassName: 'mark',
withTracks: true,
pearling: false,
disabled: false,
snapDragDisabled: false,
invert: false,
marks: [],
renderThumb: (props) => React.createElement('div', props),
renderTrack: (props) => React.createElement('div', props),
renderMark: (props) => React.createElement('span', props)
};// Single value mode
type SingleValue = number;
// Multi-value mode
type MultiValue = number[];
// Combined value type
type SliderValue = SingleValue | MultiValue;
// Event handler signatures
type ChangeHandler = (value: SliderValue, thumbIndex: number) => void;
type ClickHandler = (value: number) => void;