Multi-option Switch/Toggle component for React
Tags: javascriptlibraries, react, ui, typescript
Published: 2023-10-10 03:53:40

We all got accustomed to the switch UI button element thanks to IOS and Android. They look a bit different but convey a simple idea of switching between two states like “on” and “off”.

![Example of current IOS Switch button UI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6qvw3f0dtij7ruztzuk.png)

### _But what if I need more than one option to switch between?_


This simple idea motivated me to start coding my own take at Switch component for React. I came up with some new concepts like handling switch dragging with snap to option, supporting mobile touch events and options for UI customisation while I was writing my shiny code 😎.

So after some time a new npm library was born…

## react-custom-switcher

“Multi-option Switch/Toggle component for React with dragging, snap and customisable UI” as I wrote it in the docs.

Library exposes the **CustomSwitcher** React component that lets you easily create something like this:

{% embed https://codesandbox.io/embed/react-custom-switcher-examples-lps566?fontsize=14&hidenavigation=1&theme=dark %}

Or you can experiment more and come up with something like this:

{% embed https://codesandbox.io/embed/react-custom-switcher-extended-customisation-demo-6h5ygd?fontsize=14&hidenavigation=1&theme=dark %}

You can think up a lot of different use cases for such a component: to rate something, to switch between tabs or images, or select some needed setting.

In order to create switchers like this, you need to know how to use the **CustomSwitcher**…

## The API

CustomSwitcher component accepts a list of props corresponding to **ICustomSwitcherProps** interface:

```typescript
export interface ICustomSwitcherProps<OptionValue = unknown> {
  options: CustomSwitcherOption<OptionValue>[];
  value: OptionValue;
  containerWidth: number;
  variant?: CustomSwitcherVariant;
  switchSize?: number;
  dragEnabled?: boolean;
  disabled?: boolean;
  scaleWhileDrag?: boolean | number;
  cssOverrides?: CSSOverrides;
  callback(currentValue: OptionValue): unknown;
}
```

Lets look at them one by one.

### options
(**required**, type: _CustomerSwitcherOption<OptionValue>[]_)

Required array of options to switch between. Every option is array should have a shape corresponding to **CustomSwitcherOption**:

```typescript
export type CustomSwitcherOption<OptionValue> = {
  value: OptionValue;
  label?: string | React.ReactElement;
  color?: string;
};
```

### value
(**required**, type: _OptionValue_)

A value from options where switch will be set by default. You can use it as a controlled value.

### containerWidth
(**required**, type: _number_)


![containerWidth explained](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tpastej4qclctbdaspi7.png)

Width of the container where all the options will be rendered.

### variant
(**optional**, defaults to _’primary’_, type: _CustomSwitcherVariant_)

```typescript
export type CustomSwitcherVariant = 'primary' | 'secondary';
```

There are only two basic variants of CustomSwitcher UI. All the customisations are based on one of those variants.

**The anatomy of primary variant**

![Primary variant explained](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2sobrp4ugmmmmg61mqnm.png)

Primary variant has all the elements like switch, division line, divisions and options labels at the bottom.

Switch is filled and background color is transitioned in case optional **color** properties were provided in **options** array.

**The anatomy of secondary variant**

![Secondary variant explained](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aon909f0tf1taruqgq9a.png)

Secondary variant has only main switch and labels at the center of divisions areas. Divisions and division line elements are hidden but this can be overridden by **cssOverrides** prop (see below).

Switch element is transparent but has a border. Border color is transitioned in case optional **color** properties were provided in **options** array.

### switchSize
(**optional**, type: _number_)

![switchSize explained](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q9trp92jz6v7boeumag6.png)

As is.

### dragEnabled
(**optional**, defaults to _true_, type: _boolean_)

You can disable dragging and it can be useful in some cases, for example when using value as a controlled value.

### disabled
(**optional**, defaults to _false_, type: _boolean_)

In case you need to disable interaction with CustomSwitcher.

### scaleWhileDrag
(**optional**, defaults to _true_, type: _boolean | number_)

You can turn off scaling of switch element while dragging by providing false. Or you can define a custom scale by providing a number, e.g 1.5 will mean a 150% switch size while dragging like when using CSS scale property.

### cssOverrides
(**optional**, type: _CSSOverrides_)

You can pass an object of CSS overrides corresponding to this shape:

```typescript
export type CSSOverrides = {
  cursorDefault?: CSSProperties['cursor'];
  cursorGrab?: CSSProperties['cursor'];
  cursorGrabbing?: CSSProperties['cursor'];
  cursorDisabled?: CSSProperties['cursor'];
  switch?: CSSProperties;
  switchDisabled?: CSSProperties;
  division?: CSSProperties;
  divisionLine?: CSSProperties;
  label?: CSSProperties;
};
```

With this you can add and/or modify existing CSS properties of different elements and some behaviours.

### callback
(**required**, type: _(currentValue: OptionValue) => unknown_)

A callback which is fired when user selects an option either by using drag or just clicking on needed option.

## Last words
I hope you enjoyed the ride and that some of you might find react-custom-switcher npm library useful.

And a couple of useful links:

- [react-custom-switcher on GitHub](https://github.com/innrvoice/react-custom-switcher)
- [react-custom-switcher on npm](https://www.npmjs.com/package/react-custom-switcher)
- [all react-custom-switcher examples on codesandbox](https://codesandbox.io/examples/package/react-custom-switcher)

Thank you!