Anonymous View
ProComponents, templates & AI tooling
HeroUI
27.7k

SwitchUpdated

A toggle switch component for boolean states

Import

import { Switch, SwitchGroup, Label } from '@heroui/react';

Usage

Anatomy

Import the Switch component and access all parts using dot notation.

import { Switch, Description, FieldError } from '@heroui/react';

export default () => (
  <Switch>
    <Switch.Content>
      <Switch.Control>
        <Switch.Thumb>
          <Switch.Icon /> {/* Optional */}
        </Switch.Thumb>
      </Switch.Control>
      Label {/* plain text — the clickable label + accessible name */}
    </Switch.Content>
    <Description /> {/* Optional — field-level help text */}
    <FieldError /> {/* Optional — validation message */}
  </Switch>
);

For grouping multiple switches, use the SwitchGroup component:

import { Switch, SwitchGroup, Label } from '@heroui/react';

export default () => (
  <SwitchGroup>
    <Switch>
      <Switch.Content>
        <Switch.Control>
          <Switch.Thumb />
        </Switch.Control>
        Option 1
      </Switch.Content>
    </Switch>
    <Switch>
      <Switch.Content>
        <Switch.Control>
          <Switch.Thumb />
        </Switch.Control>
        Option 2
      </Switch.Content>
    </Switch>
  </SwitchGroup>
);

Disabled

Default Selected

Controlled

Without Label

Sizes

Label Position

With Icons

With Description

Group

Group Horizontal

Render Props

Form Integration

Custom Styles

Custom Render Function

Styling

Passing Tailwind CSS classes

You can customize individual Switch components:

import { Switch, Label } from '@heroui/react';

function CustomSwitch() {
  return (
    <Switch>
      {({isSelected}) => (
        <>
          <Switch.Control
            className={`h-[31px] w-[51px] bg-blue-500 ${isSelected ? "bg-cyan-500 shadow-[0_0_12px_rgba(6,182,212,0.5)]" : ""}`}
          >
            <Switch.Thumb
              className={`size-[27px] bg-white shadow-sm ${isSelected ? "translate-x-5 shadow-lg" : ""}`}
            />
          </Switch.Control>
          Custom Switch
        </>
      )}
    </Switch>
  );
}

Or customize the SwitchGroup layout:

import { Switch, SwitchGroup, Label } from '@heroui/react';

function CustomSwitchGroup() {
  return (
    <SwitchGroup className="gap-8" orientation="horizontal">
      <Switch>
        <Switch.Content>
          <Switch.Control>
            <Switch.Thumb />
          </Switch.Control>
          Option 1
        </Switch.Content>
      </Switch>
      <Switch>
        <Switch.Content>
          <Switch.Control>
            <Switch.Thumb />
          </Switch.Control>
          Option 2
        </Switch.Content>
      </Switch>
    </SwitchGroup>
  );
}

Customizing the component classes

To customize the Switch component classes, you can use the @layer components directive.
Learn more.

@layer components {
  .switch {
    @apply inline-flex gap-3 items-center;
  }

  .switch__control {
    @apply h-5 w-8 bg-gray-400 data-[selected=true]:bg-blue-500;
  }

  .switch__thumb {
    @apply bg-white shadow-sm;
  }

  .switch__content {
    @apply items-center gap-3;
  }

  .switch__icon {
    @apply h-3 w-3 text-current;
  }
}

HeroUI follows the BEM methodology to ensure component variants and states are reusable and easy to customize.

CSS Classes

Switch Classes

The Switch component uses these CSS classes (View source styles):

  • .switch - Base switch container (the field)
  • .switch__content - Clickable label wrapping the control and label text
  • .switch__control - Switch control track
  • .switch__thumb - Switch thumb that moves
  • .switch__icon - Optional icon inside the thumb
  • .switch--sm - Small size variant
  • .switch--md - Medium size variant (default)
  • .switch--lg - Large size variant

SwitchGroup Classes

The SwitchGroup component uses these CSS classes (View source styles):

  • .switch-group - Switch group container
  • .switch-group__items - Container for switch items
  • .switch-group--horizontal - Horizontal layout
  • .switch-group--vertical - Vertical layout (default)

Interactive States

The switch supports both CSS pseudo-classes and data attributes for flexibility:

  • Selected: [data-selected="true"] (thumb position and background color change)
  • Hover: :hover or [data-hovered="true"] on Switch.Control (button)
  • Focus: :focus-visible or [data-focus-visible="true"] on the button (shows focus ring on track)
  • Disabled: [data-disabled="true"] on the field (reduced opacity, including help text)
  • Pressed: :active or [data-pressed="true"]

API Reference

Switch Props

Inherits from React Aria SwitchField.

PropTypeDefaultDescription
size'sm' | 'md' | 'lg''md'The size of the switch
isSelectedbooleanfalseWhether the switch is on
defaultSelectedbooleanfalseWhether the switch is on by default (uncontrolled)
isDisabledbooleanfalseWhether the switch is disabled
isInvalidbooleanfalseWhether the switch is invalid
isReadOnlybooleanfalseWhether the switch is read only
isRequiredbooleanfalseWhether the switch must be selected
validate(value: boolean) => ValidationError | true | null | undefined-Custom validation function
validationBehavior'native' | 'aria''native'Whether to use native HTML form validation or ARIA
namestring-The name of the input element, used when submitting an HTML form
valuestring-The value of the input element, used when submitting an HTML form
onChange(isSelected: boolean) => void-Handler called when the switch value changes
onPress(e: PressEvent) => void-Handler called when the switch is pressed
childrenReact.ReactNode | (values: SwitchFieldRenderProps) => React.ReactNode-Switch content or field render prop
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, SwitchFieldRenderProps>-Overrides the default DOM element with a custom render function.

Switch.Content Props

The clickable <label> that wraps the control and label text. Put Switch.Control and the Label inside it; keep Description/FieldError as siblings of Switch.Content. For a switch with no label, omit the Label and pass an aria-label on Switch.

PropTypeDefaultDescription
childrenReact.ReactNode | (values: SwitchButtonRenderProps) => React.ReactNode-Button content (control + label), or a button render prop
classNamestring | (values: SwitchButtonRenderProps) => string-Classes applied to the clickable label

SwitchFieldRenderProps

When using a render prop on the root Switch, these field-level values are provided:

PropTypeDescription
isSelectedbooleanWhether the switch is currently on
isDisabledbooleanWhether the switch is disabled
isReadOnlybooleanWhether the switch is read only
isInvalidbooleanWhether the switch is invalid
isRequiredbooleanWhether the switch is required
stateToggleStateState of the switch

SwitchButtonRenderProps

Switch.Control uses button-level render props (isHovered, isPressed, isFocusVisible, etc.). Pass a function as Switch.Control children to access them.

SwitchGroup Props

PropTypeDefaultDescription
orientation'horizontal' | 'vertical''vertical'The orientation of the switch group
childrenReact.ReactNode-The switch items to render
classNamestring-Additional CSS class names

On this page