Switch Component
The Switch component is a flexible UI primitive built with TypeScript that supports both single toggle and group multi-select modes. It is designed for modern design systems with full customization support, accessibility, and group keyboard navigation.
Use mode="single" for simple on/off toggles like settings or preferences, and mode="group" for multi-select options like permissions or filters. Control state using checked and selectedValues, and customize size using iconSize.
Overview
Switch works in two modes: single for simple on/off toggles and group for multi-select switch lists. It supports controlled state management, group keyboard navigation, disabled/readOnly states, error handling, and highly customizable styling through Tailwind or inline styles.
Use single mode for settings like notifications or themes, and group mode for selecting multiple options such as features, permissions, or preferences.
Option Structure
Group mode receives an options array. Each option needs a display label and a string value.
1type SwitchOption = {
2 label: string;
3 value: string;
4};Import Component From Library
1import { Switch } from "@neuctra/ui";The Switch component supports both single and group modes. No extra setup is required — just import and start using it.
Basic Usage Code
Start with a simple switch. The component supports both single toggle and group multi-select modes with full customization.
1import { useState } from 'react';
2import { Switch } from '@neuctra/ui';
3
4function BasicExample() {
5 const [checked, setChecked] = useState(false);
6
7 return (
8 <Switch
9 mode="single"
10 label="Enable notifications"
11 checked={checked}
12 onCheckedChange={setChecked}
13 />
14 );
15}Group Usage Code
Use mode="group" when several independent switches should be controlled as a string array.
1import { useState } from 'react';
2import { Switch } from '@neuctra/ui';
3
4function SwitchGroupExample() {
5 const [selectedValues, setSelectedValues] = useState(['email']);
6
7 const options = [
8 { label: 'Email alerts', value: 'email' },
9 { label: 'SMS alerts', value: 'sms' },
10 { label: 'Product updates', value: 'updates' }
11 ];
12
13 return (
14 <Switch
15 mode="group"
16 name="notifications"
17 options={options}
18 selectedValues={selectedValues}
19 onChange={setSelectedValues}
20 />
21 );
22}Single Mode
Default mode for simple on/off toggles.
Group Mode
Multi-select switch group using mode="group".
Disabled & ReadOnly
Use disabled to completely block interaction and dim the UI. Use readOnly when you want to display the current state but prevent any changes.
Error State
Display validation feedback using the error prop. This is useful in forms when a required toggle has not been enabled.
You must accept the terms to continue
Sizes (iconSize)
Control the overall size of the switch using iconSize. This adjusts both the track and thumb proportionally.
Styling & Customization
The Switch component exposes multiple styling layers. You can customize the track, thumb, label, and layout using Tailwind classes or inline styles.
Props Table
All available props for the Switch component.
| Prop | Type | Default | Description |
|---|---|---|---|
| mode | "single" | "group" | "single" | Controls single toggle or multi-switch group mode. |
| label | string | — | Label for single switch mode. |
| checked | boolean | false | Controlled state for single switch. |
| onCheckedChange | (checked: boolean) => void | — | Triggered when single switch toggles. |
| options | { label: string; value: string }[] | — | List of switches in group mode. |
| selectedValues | string[] | [] | Currently selected values in group mode. |
| onChange | (values: string[]) => void | — | Triggered when group selection changes. |
| disabled | boolean | false | Disables interaction. |
| readOnly | boolean | false | Prevents changes but keeps UI interactive. |
| required | boolean | false | Marks field as required. |
| error | string | — | Error message displayed below switches. |
| iconSize | number | 20 | Base switch size in pixels. The track and thumb scale from this value. |
| name | string | — | Form field name attribute. |
| className | string | — | Root wrapper styles. |
| itemClassName | string | — | Each switch row container. |
| labelClassName | string | — | Label wrapper styles. |
| textClassName | string | — | Label text styling. |
| switchClassName | string | — | Switch track styling. |
| thumbClassName | string | — | Thumb styling. |
| errorClassName | string | — | Error text styling. |
| style | React.CSSProperties | — | Root inline styles. |
| itemStyle | React.CSSProperties | — | Row inline styles. |
| labelStyle | React.CSSProperties | — | Label container styles. |
| textStyle | React.CSSProperties | — | Label text styles. |
| switchStyle | React.CSSProperties | — | Track inline styles. |
| thumbStyle | React.CSSProperties | — | Thumb inline styles. |
| errorStyle | React.CSSProperties | — | Error message styles. |
Common Mistakes
selectedValues="react"Must be an array: string[]
mode="group" + checkedDo not mix single-mode props with group mode
group without onChangeGroup mode requires onChange to update state
controlled usageAlways control state for predictable UI behavior
Pro Tips
- Use
mode="group"for settings panels, permissions, filters. - Use
iconSizeto scale switch without touching CSS. - Combine
switchClassName+ Tailwind gradients for modern UI. - Use
readOnlyfor display-only preference screens. - Use
errorfor inline validation instead of external messages. - Prefer controlled state (checked / selectedValues) for consistency.
Frequently Asked Questions
How do I install and import the Switch component?
Install the @neuctra/ui package, then import it with: import { Switch } from "@neuctra/ui";
Can I customize the Switch component's appearance?
Yes. Switch accepts a className prop for custom Tailwind CSS classes, so you can adjust spacing, layout, and styling without overriding the component internals.
Is the Switch component accessible?
Switch is built with semantic HTML and standard ARIA attributes, and supports keyboard navigation and focus states out of the box, so it works well with screen readers and keyboard-only users.