Switch
A switch allows users to turn an individual option on or off.
Features
- Sync with
disabledstate of fieldset - Sync with form
resetevents - Can be toggled programmatically
Installation
Install the switch package:
npm install @zag-js/switch @zag-js/react # or yarn add @zag-js/switch @zag-js/react
npm install @zag-js/switch @zag-js/solid # or yarn add @zag-js/switch @zag-js/solid
npm install @zag-js/switch @zag-js/vue # or yarn add @zag-js/switch @zag-js/vue
npm install @zag-js/switch @zag-js/svelte # or yarn add @zag-js/switch @zag-js/svelte
Anatomy
Check the switch anatomy and part names.
Each part includes a
data-partattribute to help identify them in the DOM.
Usage
Import the switch package:
import * as zagSwitch from "@zag-js/switch"
The switch package exports two key functions:
machine- State machine logic.connect- Maps machine state to JSX props and event handlers.
Then use the framework integration helpers:
import * as zagSwitch from "@zag-js/switch" import { useMachine, normalizeProps } from "@zag-js/react" function Checkbox() { const service = useMachine(zagSwitch.machine, { id: "1" }) const api = zagSwitch.connect(service, normalizeProps) return ( <label {...api.getRootProps()}> <input {...api.getHiddenInputProps()} /> <span {...api.getControlProps()}> <span {...api.getThumbProps()} /> </span> <span {...api.getLabelProps()}>{api.checked ? "On" : "Off"}</span> </label> ) }
import * as zagSwitch from "@zag-js/switch" import { normalizeProps, useMachine } from "@zag-js/solid" import { createMemo, createUniqueId } from "solid-js" function Checkbox() { const service = useMachine(zagSwitch.machine, { id: "1" }) const api = createMemo(() => zagSwitch.connect(service, normalizeProps)) return ( <label {...api().getRootProps()}> <input {...api().getHiddenInputProps()} /> <span {...api().getControlProps()}> <span {...api().getThumbProps()} /> </span> <span {...api().getLabelProps()}>{api().checked ? "On" : "Off"}</span> </label> ) }
<script setup> import * as zagSwitch from "@zag-js/switch" import { normalizeProps, useMachine } from "@zag-js/vue" import { computed } from "vue" const service = useMachine(zagSwitch.machine, { id: "1" }) const api = computed(() => zagSwitch.connect(service, normalizeProps)) </script> <template> <label v-bind="api.getRootProps()"> <input v-bind="api.getHiddenInputProps()" /> <span v-bind="api.getControlProps()"> <span v-bind="api.getThumbProps()" /> </span> <span v-bind="api.getLabelProps()"> <span v-if="api.checked">On</span> <span v-else>Off</span> </span> </label> </template>
<script lang="ts"> import { normalizeProps, useMachine } from "@zag-js/svelte" import * as zagSwitch from "@zag-js/switch" const id = $props.id() const service = useMachine(zagSwitch.machine, { id, name: "switch", }) const api = $derived(zagSwitch.connect(service, normalizeProps)) </script> <label {...api.getRootProps()}> <input {...api.getHiddenInputProps()} /> <span {...api.getControlProps()}> <span {...api.getThumbProps()}></span> </span> <span {...api.getLabelProps()}>{api.checked ? "On" : "Off"}</span> </label>
Making it checked by default
Use the defaultChecked property to make a switch checked by default.
const service = useMachine(zagSwitch.machine, { defaultChecked: true, })
Controlled checked state
Use checked and onCheckedChange for controlled usage.
const service = useMachine(zagSwitch.machine, { checked, onCheckedChange(details) { setChecked(details.checked) }, })
Listening for changes
When the switch value changes, the onCheckedChange callback is invoked.
const service = useMachine(zagSwitch.machine, { onCheckedChange(details) { // details => { checked: boolean } console.log("switch is:", details.checked ? "On" : "Off") }, })
Programmatic toggle
Use the connected API when you need imperative control.
api.setChecked(true) api.toggleChecked()
Usage within forms
To use switch in forms, set name and render api.getHiddenInputProps().
const service = useMachine(zagSwitch.machine, { name: "feature", })
Custom form value
Set value to customize the submitted form value when checked.
const service = useMachine(zagSwitch.machine, { name: "notifications", value: "enabled", })
Styling guide
Each switch part includes a data-part attribute you can target in CSS.
Focused State
When the switch input is focused, the data-focus attribute is added to the
root, control and label parts.
[data-part="root"][data-focus] { /* styles for root focus state */ } [data-part="control"][data-focus] { /* styles for control focus state */ } [data-part="label"][data-focus] { /* styles for label focus state */ }
Disabled State
When the switch is disabled, the data-disabled attribute is added to the root,
control and label parts.
[data-part="root"][data-disabled] { /* styles for root disabled state */ } [data-part="control"][data-disabled] { /* styles for control disabled state */ } [data-part="label"][data-disabled] { /* styles for label disabled state */ }
Invalid State
When the switch is invalid, the data-invalid attribute is added to the root,
control and label parts.
[data-part="root"][data-invalid] { /* styles for root invalid state */ } [data-part="control"][data-invalid] { /* styles for control invalid state */ } [data-part="label"][data-invalid] { /* styles for label invalid state */ }
Methods and Properties
Machine Context
The switch machine exposes the following context properties:
idsPartial<{ root: string; hiddenInput: string; control: string; label: string; thumb: string; }>The ids of the elements in the switch. Useful for composition.labelstringSpecifies the localized strings that identifies the accessibility elements and their statesdisabledbooleanWhether the switch is disabled.invalidbooleanIf `true`, the switch is marked as invalid.requiredbooleanIf `true`, the switch input is marked as required,readOnlybooleanWhether the switch is read-onlyonCheckedChange(details: CheckedChangeDetails) => voidFunction to call when the switch is clicked.checkedbooleanThe controlled checked state of the switchdefaultCheckedbooleanThe initial checked state of the switch when rendered. Use when you don't need to control the checked state of the switch.namestringThe name of the input field in a switch (Useful for form submission).formstringThe id of the form that the switch belongs tovaluestring | numberThe value of switch input. Useful for form submission.dir"ltr" | "rtl"The document's text/writing direction.idstringThe unique identifier of the machine.getRootNode() => ShadowRoot | Node | DocumentA root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.
Machine API
The switch api exposes the following methods:
checkedbooleanWhether the switch is checkeddisabledbooleanWhether the switch is disabledfocusedbooleanWhether the switch is focusedsetChecked(checked: boolean) => voidSets the checked state of the switch.toggleCheckedVoidFunctionToggles the checked state of the switch.
Data Attributes
Accessibility
Adheres to the Switch WAI-ARIA design pattern
Keyboard Interactions
- SpaceEnterToggle the switch