Component reference
Switch
A native checkbox with switch semantics; form reset and keyboard remain native.
Preview
Switch has no story of its own; this one draws it as part of Checkbox.
Checkboxes and switches
Activate labels, toggle with the space bar and reset the form; a controlled switch leaves it to the caller to accept a change.
render: () => {
const checked = signal(true);
return (
<form onSubmit={(event: Event) => event.preventDefault()}>
<Stack>
<Checkbox label="Save this choice" name="remember" defaultChecked />
<Checkbox label="Required before submitting" name="confirm" required />
<Checkbox label="Currently unavailable" disabled />
<Checkbox label="Some children selected" indeterminate defaultChecked={false} />
<Switch label="Show tool process" name="tools" defaultChecked />
<Switch
label="Notifications (controlled)"
name="notifications"
checked={checked}
onChange={(event: Event) => {
checked.value = (event.currentTarget as HTMLInputElement).checked;
}}
/>
<Switch label="Always on (rejects changes)" checked={true} />
<Switch label="Unavailable" disabled />
<ActionRow>
<Button type="reset" variant="outline">
Reset
</Button>
<Button type="submit">Confirm</Button>
</ActionRow>
</Stack>
</form>
);
}Installation
bun add meowtail
Usage
Taken from the examples on this page.
import { Switch } from "meowtail";
<Switch label="Show tool process" name="tools" defaultChecked />Examples
Other stories that draw Switch.
Control centers and symmetry
Checks the vertical center and top/bottom symmetry of single-line inputs, selects, button icons/text, and the inline composer on one screen; shared by visual review and geometry regressions.
render() {
const choice = signal("current");
const rowChoice = signal("current");
const view = signal("list");
return (
<div className="workshop-stack" data-basic-quality-scene>
<Specimen label="Single-line inputs and selects" align="start">
<Input aria-label="Project name" value="Workspace" data-batch1="input" />
<Input
aria-label="Project name placeholder"
placeholder="Project name"
data-batch1="input-placeholder"
/>
<Select aria-label="Current workspace" value="current" data-batch1="select">
<option value="current">Current workspace</option>
<option value="new">New workspace</option>
</Select>
<ChoiceSelect
id="basic-quality-choice"
aria-label="Select model"
value={choice}
onValueChange={(value) => {
choice.value = value;
}}
data-batch1="choice-select"
options={[
{ value: "current", label: "DeepSeek-V4-Pro" },
{ value: "fast", label: "DeepSeek-V4-Fast" },
]}
/>
</Specimen>
<Specimen label="One row of every single-line control" align="start">
{/* Top-aligned on purpose: the row only lines up if every height agrees. */}
<Inline gap="compact" align="start" data-mixed-row>
<Input aria-label="Filter name" placeholder="Name" />
<SearchInput label="Search files" placeholder="Search" />
<Select aria-label="Status">
<option>Any status</option>
</Select>
<ChoiceSelect
id="basic-quality-row-choice"
aria-label="Owner"
value={rowChoice}
onValueChange={(value) => {
rowChoice.value = value;
}}
options={[
{ value: "current", label: "Anyone" },
{ value: "me", label: "Me" },
]}
/>
<NumberInput defaultValue={10} aria-label="Limit" />
<SegmentedControl
id="basic-quality-row-view"
label="View"
value={view}
onValueChange={(value) => {
view.value = value;
}}
options={[
{ value: "list", label: "List" },
{ value: "grid", label: "Grid" },
]}
/>
<Button variant="outline">Reset</Button>
<Button>Apply</Button>
<IconButton label="Refresh">
<Icon name="refresh-cw" />
</IconButton>
</Inline>
</Specimen>
<Specimen label="Actions" align="start">
<div className="workshop-row">
<Button data-batch1="button-text">Save changes</Button>
<Button data-batch1="button-icon-text">
<Icon name="search" />
Search
</Button>
<IconButton label="Search" data-batch1="icon-button">
<Icon name="search" />
</IconButton>
</div>
</Specimen>
<Specimen label="Switches and checkboxes" align="start">
<div className="workshop-row">
<Checkbox label="Keep draft" defaultChecked data-batch1="checkbox" />
<Switch label="Notify when complete" data-batch1="switch" />
</div>
</Specimen>
<Specimen label="Inline input" align="start">
<div style={{ width: "100%" }}>
<ChatComposer
layout="inline"
placeholder="Write a message…"
inputLabel="Message"
submitLabel="Send"
onSubmit={(event) => event.preventDefault()}
data-batch1="composer"
/>
</div>
</Specimen>
</div>
);
}API reference
Props
| Prop | Type | Default |
|---|---|---|
checked | MaybeSignal<boolean> | – |
defaultChecked | boolean | – |
indeterminateNative indeterminate property. Assistive technology reads aria-checked="mixed". | MaybeSignal<boolean> | – |
onChange | (event: Event) => void | – |
labelRequired | MaybeSignal<string> | – |
labelHiddenKeep the accessible name while hiding the visible label, for compact tables. | boolean | – |
Also takes className, children and the attributes and events of its root element.
DOM parts
rootinputtrackthumblabel
Registry
The component is registered as switch in the meowtail component registry.