Toggle switch with labels and form chrome.
Introduction
Use switches for binary settings that take effect immediately, such as enabling notifications or dark mode. Prefer Checkbox when the choice is part of a form submission or when users may select multiple options.
endLabel / startLabel and description are built into the component. A native checkbox input with role="switch" drives the control under the hood.
Import
import { Switch } from "@bridge-ui/vue/Components/Switch";import { Switch } from "@bridge-ui/react/Components/Switch";Basic usage
Provide endLabel / startLabel and optional description. In React, use checked and onChange for controlled state; in Vue, use v-model. For uncontrolled usage with an initial state, use defaultChecked in React or default-checked in Vue.
<script setup lang="ts">
import { ref } from "vue";
import { Switch } from "@bridge-ui/vue/Components/Switch";
const enabled = ref(false);
</script>
<template>
<div class="flex w-full flex-col gap-6">
<Switch
end-label="Dark mode"
description="Use dark theme across the app."
/>
<Switch v-model="enabled" end-label="Enable notifications" />
</div>
</template>
import { useState } from "react";
import { Switch } from "@bridge-ui/react/Components/Switch";
export default function SwitchBasic() {
const [enabled, setEnabled] = useState(false);
return (
<div className="flex w-full flex-col gap-6">
<Switch
endLabel="Dark mode"
description="Use dark theme across the app."
/>
<Switch
checked={enabled}
endLabel="Enable notifications"
onChange={(event) => setEnabled(event.target.checked)}
/>
</div>
);
}
Colors
Use the color prop to change the track and thumb color. Available colors: primary, secondary, success, info, warning, error, and dark.
<script setup lang="ts">
import { Switch } from "@bridge-ui/vue/Components/Switch";
</script>
<template>
<div class="flex w-full flex-col gap-6">
<Switch default-checked color="primary" end-label="primary switch" />
<Switch default-checked color="secondary" end-label="secondary switch" />
<Switch default-checked color="success" end-label="success switch" />
<Switch color="info" default-checked end-label="info switch" />
<Switch default-checked color="warning" end-label="warning switch" />
<Switch color="error" default-checked end-label="error switch" />
<Switch color="dark" default-checked end-label="dark switch" />
</div>
</template>
import { Switch } from "@bridge-ui/react/Components/Switch";
export default function SwitchColors() {
return (
<div className="flex w-full flex-col gap-6">
<Switch defaultChecked color="primary" endLabel="primary switch" />
<Switch defaultChecked color="secondary" endLabel="secondary switch" />
<Switch defaultChecked color="success" endLabel="success switch" />
<Switch color="info" defaultChecked endLabel="info switch" />
<Switch defaultChecked color="warning" endLabel="warning switch" />
<Switch color="error" defaultChecked endLabel="error switch" />
<Switch color="dark" defaultChecked endLabel="dark switch" />
</div>
);
}
Sizes
Control the switch size with the size prop. Available sizes: 2xs, xs, sm, md (default), lg, xl, and 2xl.
<script setup lang="ts">
import { Switch } from "@bridge-ui/vue/Components/Switch";
</script>
<template>
<div class="flex w-full flex-col gap-4">
<Switch size="2xs" default-checked end-label="2xs switch" />
<Switch size="xs" default-checked end-label="xs switch" />
<Switch size="sm" default-checked end-label="sm switch" />
<Switch size="md" default-checked end-label="md switch" />
<Switch size="lg" default-checked end-label="lg switch" />
<Switch size="xl" default-checked end-label="xl switch" />
<Switch size="2xl" default-checked end-label="2xl switch" />
</div>
</template>
import { Switch } from "@bridge-ui/react/Components/Switch";
export default function SwitchSizes() {
return (
<div className="flex w-full flex-col gap-4">
<Switch size="2xs" defaultChecked endLabel="2xs switch" />
<Switch size="xs" defaultChecked endLabel="xs switch" />
<Switch size="sm" defaultChecked endLabel="sm switch" />
<Switch size="md" defaultChecked endLabel="md switch" />
<Switch size="lg" defaultChecked endLabel="lg switch" />
<Switch size="xl" defaultChecked endLabel="xl switch" />
<Switch size="2xl" defaultChecked endLabel="2xl switch" />
</div>
);
}
Rounded
Use the rounded prop to control border radius. Available values: none, xs, sm, md, lg, xl, 2xl, 3xl, 4xl, and full (defaults vary by component).
<script setup lang="ts">
import { Switch } from "@bridge-ui/vue/Components/Switch";
</script>
<template>
<div class="flex flex-wrap items-center gap-6">
<Switch rounded="none" default-checked end-label="none" />
<Switch rounded="sm" end-label="sm" default-checked />
<Switch rounded="md" end-label="md" default-checked />
<Switch rounded="2xl" default-checked end-label="2xl" />
<Switch rounded="full" default-checked end-label="full" />
</div>
</template>
import { Switch } from "@bridge-ui/react/Components/Switch";
export default function SwitchRounded() {
return (
<div className="flex flex-wrap items-center gap-6">
<Switch defaultChecked rounded="none" endLabel="none" />
<Switch rounded="sm" endLabel="sm" defaultChecked />
<Switch rounded="md" endLabel="md" defaultChecked />
<Switch rounded="2xl" defaultChecked endLabel="2xl" />
<Switch defaultChecked rounded="full" endLabel="full" />
</div>
);
}
Validation
Use required to mark the field as required, error with errorMessage for invalid state, and disabled to prevent interaction.
<script setup lang="ts">
import { Switch } from "@bridge-ui/vue/Components/Switch";
</script>
<template>
<div class="flex w-full flex-col gap-6">
<Switch required end-label="Required field" />
<Switch
error
end-label="Invalid option"
error-message="You must enable this setting."
/>
<Switch disabled :model-value="true" end-label="Disabled" />
</div>
</template>
import { Switch } from "@bridge-ui/react/Components/Switch";
export default function SwitchValidation() {
return (
<div className="flex w-full flex-col gap-6">
<Switch required endLabel="Required field" />
<Switch
error
endLabel="Invalid option"
errorMessage="You must enable this setting."
/>
<Switch disabled defaultChecked endLabel="Disabled" />
</div>
);
}
Related components
Accessibility
- Space toggles the switch when the native input is focused
- Tab and Shift+Tab move between controls in the page
- A visually hidden native <input type="checkbox" role="switch"> holds state; track and thumb have aria-hidden
- endLabel is associated with the input through matching id and htmlFor
- error sets aria-invalid on the input and data-invalid on the FormControl root
- disabled sets aria-disabled on the FormControl root
Anatomy
<div data-invalid>
<div>
<!-- row -->
<label>
<input type="checkbox" role="switch" class="sr-only" id="..." />
<span aria-hidden="true" />
<!-- track -->
<span aria-hidden="true" />
<!-- thumb -->
</label>
<label for="...">End label</label>
</div>
<p>Description</p>
<p aria-hidden>Error message</p>
</div>API
| Prop | Type | Default | Description |
|---|---|---|---|
| v-model | boolean | — | Two-way binding for the on state. |
| default-checked | boolean | false | Initial on state for uncontrolled usage (without v-model). |
| Prop | Type | Default | Description |
|---|---|---|---|
| checked | boolean | — | On state. Use with onChange for controlled state. |
| defaultChecked | boolean | — | Initial on state for uncontrolled usage. |
| onChange | ChangeEventHandler<HTMLInputElement> | — | Native input change handler. |
| Prop | Type | Default | Description |
|---|---|---|---|
| endLabel | string | — | Label text after the control (LTR: right). |
| startLabel | string | — | Label text before the control (LTR: left). |
| description | string | — | Helper text below the control row. |
| error | boolean | false | Applies invalid styling and sets aria-invalid. |
| errorMessage | string | — | Error message shown below the control row. |
| required | boolean | false | Sets the native required attribute on the input. |
| disabled | boolean | false | Whether the switch is disabled. |
| color | SwitchColor | "primary" | Semantic color of the switch. |
| size | SwitchSize | "md" | Size of the control and label typography. |
| rounded | SwitchRounded | "full" | Border radius of the track. |
| classes | SwitchClasses | — | Classes for form control chrome and switch parts. |
| customProps | SwitchCustomProps | — | Extra props for FormControl chrome and control parts. startLabel / endLabel accept Label props (no children). |
| slots | SwitchSlots | — | React slots for chrome and the control. |