react-switch
A draggable, accessible toggle-switch component for React with mouse, touch, and keyboard support out of the box.
Repository Health
Technical Analysis
react-switch renders a single customizable toggle-switch component that can be dragged with the mouse or a touch screen, clicked, or operated via keyboard, and wires up the correct accessibility semantics (role=“switch”, aria-checked, focus outline) automatically. It ships as a controlled component: the consumer owns the checked state and passes an onChange handler, keeping the library’s internal footprint small (under 2.5kB gzipped) since it uses inline styles instead of a stylesheet.
Beyond the default look, colors (on/off track and handle), icons, dimensions, border radius, and box-shadow are all configurable via props, and any unrecognized props are forwarded to the underlying checkbox input so consumers can add native HTML attributes like name or required without extra wrapper code.
What You Get
- A controlled Switch component driven entirely by
checkedandonChangeprops, so it fits cleanly into any existing form state management - Built-in drag support for both mouse and touch, with a halfway-checkpoint rule that toggles state if the handle is dragged more than 50% of the way across
- Correct accessibility wiring out of the box: role=“switch”, aria-checked, a hidden native checkbox input, and a visible focus outline that only appears on keyboard focus
- Full visual customization via props: track colors, handle colors, custom checked/unchecked icons, handle diameter, height, width, and border radius
- A tiny runtime footprint (under 2.5kB gzipped) achieved by using inline styles rather than a bundled CSS file
Common Use Cases
- Settings screens that need an on/off toggle for boolean preferences (notifications, dark mode, feature flags)
- Forms where a checkbox needs to look and feel like an iOS/Material-style switch rather than a square checkbox
- Dashboards and admin panels toggling a resource’s enabled/disabled state inline in a table row
- Any React app wanting drag-to-toggle interaction (not just click) for a more tactile mobile experience
Under The Hood
Architecture
The library is a single stateful class component (src/index.jsx) that owns all drag/click/keyboard/focus logic, delegating only pure, side-effect-free calculations to two extracted helper modules: getBackgroundColor.js (interpolates track/handle color between off and on states based on drag position) and hexColorPropType.js (a custom PropTypes validator restricting color props to hex strings). Mouse and touch input converge on shared $onDragStart/$onDrag/$onDragStop methods, and the constructor precomputes $checkedPos/$uncheckedPos bounds from height, width, and handleDiameter that every subsequent position, opacity, and transform calculation in render() depends on — meaning any change to how those bounds are derived cascades through nearly the entire render method. There is no internal layering beyond this, which is appropriate given the component’s narrow, single-purpose surface area.
Tech Stack
The only runtime dependency is prop-types (^15.7.2); react and react-dom are peer dependencies supporting a wide range (^15.3.0 through ^19.0.0). The build pipeline uses Rollup (with rollup-plugin-babel, rollup-plugin-buble, and rollup-plugin-terser) to produce separate dev and production bundles as both CJS and ESM, wired up through the package’s exports map, while Babel 7 (preset-env, preset-react) handles transpilation. A separate Webpack 5 config builds the demo site. Tests run on Jest 26 with @testing-library/react 16, and linting uses ESLint with the Airbnb config plus Prettier for formatting.
Code Quality
Tests exist under __tests__/ covering the two pure helper functions directly (getBackgroundColor.test.js, hexColorPropType.test.js) plus component-level behavior (Switch.test.jsx) including snapshot tests for default and custom prop rendering, and behavioral assertions for focus/blur outline changes and drag-triggered state transitions. Error handling relies on PropTypes validation rather than thrown exceptions — including a hand-written hexColorPropType validator for color props — with no TypeScript compilation in the source, though a hand-authored index.d.ts ships for TypeScript consumers. Internal-only instance fields and state keys consistently use a $ prefix (e.g. $onMouseDown, $checkedPos) to visually separate them from public props, and a GitHub Actions workflow runs CI on changes.
API Design
The public API needs only two required props (checked, onChange) to function, with every other prop — colors, icons, dimensions, box-shadow — defaulted sensibly, so getting a working switch on screen requires minimal boilerplate. Prop names are consistent and self-explanatory (offColor/onColor for the track, offHandleColor/onHandleColor for the handle, checkedIcon/uncheckedIcon vs checkedHandleIcon/uncheckedHandleIcon), and any extra props are spread onto the underlying input so consumers can pass native HTML attributes without a wrapper. Accessibility is handled by default (role=“switch”, aria-checked, focus outline logic) rather than requiring consumers to wire it up themselves, and the README documents label-association patterns for screen-reader users explicitly.
Used by 3 apps in this directory
Continue
Developer Tools · AI Development · AI Code Assistants
Open-source coding agent for VS Code, JetBrains, and CLI with support for 30+ LLM providers.
QRev
CRM · AI Agents
Open source AI-first sales platform that replaces Salesforce with autonomous agents handling prospecting, outreach, and lead management at scale.
Responsively App
Design Tools · Developer Tools
Preview and interact with your responsive web design across every device size simultaneously — no more manual resizing.