rc-slider
Accessible, headless React slider for single values, ranges, marks, and editable range handles.
Repository Health
Technical Analysis
@rc-component/slider is the slider primitive that powers range inputs across the Ant Design component ecosystem and countless standalone React apps. It renders a single component for both plain value sliders and dual/multi-handle range sliders, with support for marks, dots, keyboard interaction, vertical and reverse layouts, and fully custom handle rendering.
Beyond the basics, it goes further than most slider libraries: ranges can be made editable, letting users drag a handle past a distance threshold to delete it or click a track to insert a new one, with configurable min/max handle counts. Disabled handles are treated as fixed anchors that other handles push against rather than cross, and semantic classNames/styles props expose every internal slot (rail, track, handle) for styling without fighting specificity.
What You Get
- A single
<Slider />component that handles both single-value and range (multi-handle) modes via onerangeprop - Editable ranges: drag a handle past a distance threshold to delete it, or click the track to insert a new handle, with
minCount/maxCountlimits - Marks and dots for labeled stops, with automatic value snapping to the nearest mark or step
- Full keyboard support (arrow keys, Home/End behavior) alongside mouse and touch dragging
- Semantic
classNamesandstylesprops for the rail, track(s), and handle so you can theme every slot directly - TypeScript types for every prop, including generics over
number | number[]value shapes
Common Use Cases
- Price or quantity range filters in e-commerce and dashboard UIs
- Volume, brightness, and other single-value input controls
- Multi-stop timeline or duration scrubbers with labeled marks
- Editable range selectors where users add or remove segments, such as shift or schedule blocks
Under The Hood
Architecture The library centers on a single orchestrating component, Slider.tsx, which owns all derived state via a dense chain of useMemo/useEvent hooks and delegates specific concerns to focused hooks and subcomponents: useRange normalizes the range/editable/draggableTrack/min-max-count config, useOffset computes step- and mark-aware value snapping and per-handle drag boundaries (including disabled-handle anchor logic in getDisabledBoundaryValues and getClosestEnabledHandleIndex), and useDrag owns all pointer/touch event wiring, cache values during a drag, and the delete-by-drag-distance interaction. Presentation is split into four leaf components - Handles, Marks, Steps, and Tracks - which read shared layout primitives (min/max/direction/disabled/keyboard/styles) from SliderContext rather than receiving them as prop-drilled parameters, keeping the leaf components thin. Data flows one way: user interaction reaches Slider.tsx’s onChange/onStartMove/onDelete handlers, state updates via useControlledState, and the resulting values flow back down through context and props to the leaf renderers. If the core value-shape abstraction (number | number[], normalized once in the rawValues useMemo) changed, essentially every hook and leaf component would need to change in lockstep, since they all assume a single sorted array of numeric values regardless of mode.
Tech Stack The package is plain TypeScript with React as a peer dependency (>=16.9.0, developed against React 19) and a single runtime dependency, @rc-component/util, which supplies shared cross-package primitives (useEvent, useControlledState, useLayoutEffect, isEqual, warning, KeyCode) reused throughout the rc-component family. Styling ships as a separate Less file compiled to CSS rather than CSS-in-JS, with clsx composing class names at runtime. The build is handled by father (via @rc-component/father-plugin) producing both CommonJS and ESM output plus type declarations, docs are built and served with dumi, a React-focused static site generator used across the Ant Design ecosystem, and releases are cut through @rc-component/np. Husky plus lint-staged run Prettier on every commit, and ESLint uses the newer flat-config format via typescript-eslint and eslint-plugin-react-hooks.
Code Quality Testing is substantial: the Slider and Range test suites alone total well over a thousand lines, exercising click positioning in all four directions, keyboard stepping, drag-to-delete thresholds, disabled-handle boundaries, and marks/dots rendering, run through the project’s own rc-test wrapper around Jest plus Testing Library, with DOM measurement mocked via spied element prototypes. Snapshot tests cover base render output. Deprecated props are kept working but emit dev-only warning() calls rather than being silently dropped or throwing, a deliberate, non-breaking migration path visible directly in the component source. Naming is consistent and domain-specific, and the public API is fully typed, including a generic value type on SliderProps. CI runs a dedicated test workflow plus CodeQL security scanning on every push and pull request.
API Design The single biggest ergonomic choice is collapsing single-value and range sliders into one component and one value type switched by a boolean-or-config range prop, rather than shipping a separate range component - this avoids the API duplication seen in many competing libraries. Editable ranges, with configurable min/max handle counts and drag-to-delete, and draggable range tracks are genuinely uncommon capabilities for a slider primitive, going beyond typical two-handle range inputs. Custom handle-render escape hatches and the semantic-slot classNames/styles system mean consumers rarely need to fork the component to reskin it, and the whole surface stays framework-idiomatic: controlled/uncontrolled via value/defaultValue, forwardRef exposing focus/blur, and standard onChange/onChangeComplete callbacks. It isn’t conceptually novel research, it’s a well-executed controlled component, but the depth of interaction support is well above the median for slider libraries in this space.
Used by 5 apps in this directory
CodeSandbox
Code Editors · Developer Tools
Instantly ready browser-based IDE that runs full npm dependency resolution and transpilation entirely client-side, with no server needed.
Grafana
Monitoring · Analytics
The open-source observability platform that unifies metrics, logs, and traces from any data source into dynamic, queryable dashboards.
highlight.io
Developer Tools · Analytics · Monitoring
Open-source full-stack monitoring that unifies session replay, error tracking, logging, and distributed tracing so you can stop context-switching between tools.
Portainer
Devops
A lightweight, open-source web UI that puts Docker, Kubernetes, and Podman management within reach of any team—no CLI expertise required.
ToolJet
Low Code Platforms · No Code Platforms · AI Agents
Open-source AI-native platform to build and deploy internal tools, workflows, and AI agents with a visual drag-and-drop builder and 80+ data source integrations.