Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

react-switch

markusenglund1.3mMIT7.1.0TypeScript support: included

Draggable toggle-switch component for react

switch, toggle, toggle-button, toggle-switch, checkbox, react, react-component

readme

A draggable toggle-switch component for React.

npm npm GitHub stars gzip size

  • Draggable with the mouse or with a touch screen.
  • Customizable - Easy to customize size, color and more.
  • Accessible to visually impaired users and those who can't use a mouse.
  • Reasonable package size - <2.5 kB gzipped.
  • It Just Works - Sensible default styling. Uses inline styles, so no need to import a separate css file.

Demo

Take a look at the demo

Installation

npm install react-switch

Usage

import React, { Component } from "react";
import Switch from "react-switch";

class SwitchExample extends Component {
  constructor() {
    super();
    this.state = { checked: false };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(checked) {
    this.setState({ checked });
  }

  render() {
    return (
      <label>
        <span>Switch with default style</span>
        <Switch onChange={this.handleChange} checked={this.state.checked} />
      </label>
    );
  }
}

What's the deal with the label tag?

The Switch component in the above example is nested inside a label tag. This makes sure that the label text is read out to people with reduced sight who use screen readers and enables users to click on the text to toggle the switch. If you would only put some text next to the switch but not inside a label element, the screen reader will just read out "switch off" and the user will have no idea what it is for.

If you don't want to nest the switch inside a label, you can use the htmlFor attribute on the label-element and set it to the same value as the id of the switch. Alternatively, you can use the aria-labelledby or aria-label props to give the switch a label. You can see examples of this at the bottom of the demo page.

API

Prop Type Default Description
checked bool Required If true, the switch is set to checked. If false, it is not checked.
onChange ([checked], [event], [id]) func Required Invoked when the user clicks or drags the switch. It is passed three arguments: checked, which is a boolean that describes the presumed future state of the checked prop (1), the event object (2) and the id prop (3).
disabled bool false When disabled, the switch will no longer be interactive and its colors will be greyed out.
offColor string '#888' The switch will take on this color when it is not checked. Only accepts hex-colors.
onColor string '#080' The switch will take on this color when it is checked. Only accepts hex-colors.
offHandleColor string '#fff' The handle of the switch will take on this color when it is not checked. Only accepts hex-colors.
onHandleColor string '#fff' The handle of the switch will take on this color when it is checked. Only accepts hex-colors.
handleDiameter number undefined The diameter of the handle, measured in pixels. By default it will be 2 pixels smaller than the height of the switch.
uncheckedIcon element or bool Default value An icon that will be shown on the switch when it is not checked. Pass in false if you don't want any icon.
checkedIcon element or bool Default value An icon that will be shown on the switch when it is checked. Pass in false if you don't want any icon.
uncheckedHandleIcon element undefined An icon that will be shown on the handle of the switch when it is not checked.
checkedHandleIcon element undefined An icon that will be shown on the handle of the switch when it is checked.
boxShadow string undefined The default box-shadow of the handle. You can read up on the box-shadow syntax on MDN.
activeBoxShadow string '0 0 2px 3px #3bf' The box-shadow of the handle when it is active or focused. Do not set this to null, since it is important for accessibility.
height number 28 The height of the background of the switch, measured in pixels.
width number 56 The width of the background of the switch, measured in pixels.
className string undefined Set as the className of the outer shell of the switch. Useful for positioning the switch.
borderRadius number undefined Border radius of the switch and the handle.
id string undefined Set as an attribute to the embedded checkbox. This is useful for the associated label, which can point to the id in its htmlFor attribute.

NOTE: All additional props will be passed to the nested input element.

The following props have to be either 3-digit or 6-digit hex-colors: offColor, onColor, offHandleColor, and onHandleColor. This is because this library calculates intermediate color values based on the hex-color strings.

Examples of valid colors: '#abc', '#123456'

Examples of invalid colors: 'red', 'rgb(0,0,0)'

Development

You're welcome to contribute to react-switch. Keep in mind that big changes have to be thoroughly tested on lots of different browsers and devices before they can be merged.

To set up the project:

  1. Fork and clone the repository
  2. $ npm install
  3. $ npm run dev

The demo page will then be served on http://localhost:8000/ in watch mode, meaning you don't have refresh the page to see your changes.

Contributors


Markus Englund

Timothy McLane

License

MIT

changelog

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

[7.1.0 - 2024-12-14]

Added

  • Add react@19 as a peerDependency.

[7.0.0 - 2022-06-09]

Changed

  • Export package as ESM, fixes incompatibility with Rollup/Vite and makes output slightly smaller (@Niputi)

[6.1.0 - 2022-06-08]

Added

  • Add react@18 as a peerDependency (@smhg)

Changed

  • Replace Enzyme with React testing library (@smhg)

[6.0.0 - 2021-01-06]

Added

  • Add custom handle icons (@morinted)
  • Add aria-checked attribute (@monicahung)
  • Add borderRadius prop

Fixed

  • Prevent setState from being called after component is unmounted (@smhg)

Changed

  • When the checked state is not changed in the onChange callback, the switch will now go back to its previous position instead of getting stuck halfway. This means the switch will move back and forth if the onChange callback changes the state after an asynchronous operation.
  • Support react and react-dom 17 as peer dependencies
  • Update all dev depencies

[5.0.1 - 2019-07-16]

Fixed

  • Minor typescript definition fix.

[5.0.0 - 2019-04-22]

Added

  • It's now possible to give the Switch any prop (such as aria-* props or tabIndex) and it will automatically be passed to the nested input-element.
  • Improved Typescript compatibility by using exports:named option in rollup. This could possibly be breaking for some obscure setups.

Changed

  • Replaced deprecated componentWillReceiveProps lifecycle hook with componentDidUpdate, which means it now works in strict mode.

Fixed

  • Now works properly with right-to-left languages.

[4.1.0 - 2019-02-17]

Added

  • Add support for name attribute

[4.0.0 - 2019-01-30]

Changed

  • The switch now includes a hidden nested checkbox input, which creates an expience more akin to a normal checkbox - clicking on the label will now cause a toggle, and the VoiceOver screen reader will now reliably read the label.
  • The switch will now always fire the onChange event if the dragStop event occurs <250ms after the dragStart event since that feels like a click.
  • Aria role changed from "checkbox" to "switch".
  • Pressing enter no longer activates the switch (spacebar still does)

Added

  • Add new tabIndex prop

Fixed

  • Fix glitch where the clicking the handle wouldn't trigger onChange event when browser window was out of focus on Windows.

[3.0.3 - 2018-06-15]

Fixed

  • Fix glitch where the switch would disintegrate if it had a parent with text-align set to center or right

[3.0.2 - 2018-06-07]

Changed

  • Add the correct gzip badge.

[3.0.1 - 2018-06-07]

Changed

  • Some more byte shaving.

[3.0.0 - 2018-06-07]

Changed

  • Shave off some extra bytes by setting interop: false in rollup config.

Fixed

  • Fix peculiar glitch when used with preact-compat.

[3.0.0-beta.0 - 2018-06-06]

Changed

  • Project structure was completely revamped to reduce bundle size:

  • Use rollup to bundle the different source files.

  • Use buble instead of babel for transpiling since it produces tinier output.
  • Remove prop-types from production mode. Prop-types are still there in development mode so developer experience is unchanged.
  • Mangle property names with uglify by putting a $-sign at the start of the properties that are safe to mangle.

Fixed

[2.3.2 - 2018-04-20]

Fixed

  • Corrected dead links in README

[2.3.1 - 2018-04-08]

Added

  • Devs now receive a console warning if they have passed an invalid color prop.

[2.3.0 - 2017-12-27]

Added

  • Added TypeScript declaration file

[2.2.0 - 2017-12-19]

Added

  • onChange callback function is now given the id prop that the user has given as the third argument.

Fixed

  • Improved responsiveness on mobile by removing the 300 ms delay when clicking the background.
  • It is no longer possible to select text while holding down the switch.
  • Highlighting effect when clicking the switch on mobile webkit browsers has been removed.
  • Fixed bug where dragging the switch would create a strange shadow on IOS.

[2.1.0 - 2017-11-22]

Added

  • onChange callback function is now given the event that activated the callback as a second argument.

[2.0.1 - 2017-11-03]

Changed

  • prop-types is switched from peerDependency to dependency. This should reduce frustration for devs who don't use prop-types in their project, but shouldn't affect anyone else.

[2.0.0 - 2017-10-31]

Added

  • Added some keywords

Changed

  • Improved demo with best practices for labels.
  • README clarifications

[2.0.0-rc.2.1]

Fixed

  • Removed some unnecessary files from the package.

[2.0.0-rc.2] - 2017-10-13

Refactor

  • The switch no longer uses the opacity hack to transition between color. This involved stacking two divs on top of each other and varying the opacity of the top div. This caused some weird visual artifacts.

Changed

  • onColor and offColor props can now only take colors in the form of '#xxxxxx'. Gradients and rgb(xxx, xxx, xxx) are no longer supported.
  • handleColor prop is replaced by onHandleColor and offHandleColor.
  • The boxShadow the handle gets when selected is now available in the activeBoxShadow prop. The boxShadow prop is now the boxShadow the handle has when it is not selected, and is null by default.

Fixed

  • The switch no longer has a pixel wide gloria of the offColor when checked.

Removed

  • activeHandleColor prop is removed because of lack of usefulness.

[2.0.0-rc.1] - 2017-10-08

Added

  • New prop boxShadow. It acts just like outline, but I called it boxShadow since that is the actual css attribute that is being controlled.
  • New props checkedIcon and uncheckedIcon. They have a checkmark and an x as default. Custom elements can be given as icons or the boolean value 'false', which will remove icons.

Refactor

  • Dependency on 'react-draggable' is removed and replaced with new drag logic.

Fixed

  • Glitch related to faulty 'inTransition' state fixed due to inTransition no longer existing.

Changed

  • Outline disappears when the users stops holding down the mouse. This is the same behaviour as google's switch-button implementation.
  • onChange callback function is now also triggered when enter key is pressed in violation of wai-aria checkbox spec. This is reasonably since it's in the toggle-button spec.

Removed

  • The deprecated 'name' and 'value' properties are removed.

[1.2.0 - 2017-09-29]

Fixed

  • Removed react and react-dom from dependencies.
  • Css-file replaced with inline styles to avoid webpack style-loader dependence.

Changed

  • Cursor style of handle changed to pointer instead of grabbing.

[1.1.0] - 2017-09-26

Fixed

  • Pressing the spacebar while the switch is focused no longer causes the page to scroll.
  • Disabling the switch now sets opacity to 0.5 as it should.
  • Fixed glitch where the left property of the switch-handle would be off by one if checked was initially set to true.

Deprecated

  • The 'name' and 'value' properties will be removed in the next major version since I don't believe they serve any purpose in a controlled component.