Switch
Form ControlsLocal guide ↗
import { Switch } from "bits-ui" Settings row
A labelled binary setting with a moving thumb and explicit status
A concise activity summary every Monday morning.
<script lang="ts">
import { Label, Switch } from 'bits-ui';
let enabled = $state(true);
</script>
<div class="panel mx-auto flex max-w-lg items-center gap-4 p-4">
<div class="min-w-0 flex-1">
<Label.Root for="weekly-digest" class="text-sm font-medium text-ink-50">Weekly digest</Label.Root>
<p class="muted mt-1 text-xs">A concise activity summary every Monday morning.</p>
</div>
<Switch.Root
id="weekly-digest"
bind:checked={enabled}
name="weekly-digest"
value="enabled"
class="inline-flex h-7 w-12 shrink-0 items-center rounded-full border border-ink-700 bg-ink-800 p-0.5 transition-colors data-[state=checked]:border-brand-500 data-[state=checked]:bg-brand-500"
>
<Switch.Thumb
class="block size-5 rounded-full bg-ink-200 shadow-sm transition-transform data-[state=checked]:translate-x-5 data-[state=checked]:bg-ink-950 data-[state=unchecked]:translate-x-0"
/>
</Switch.Root>
<span class="chip w-10 justify-center">{enabled ? 'On' : 'Off'}</span>
</div>
Controlled and disabled
External controls update the same bound state; managed settings remain visibly unavailable
Controlled state: off
Managed by your organization
<script lang="ts">
import { Label, Switch } from 'bits-ui';
let checked = $state(false);
</script>
<div class="grid gap-4">
<div class="flex flex-wrap items-center gap-2">
<button class="btn btn-sm" onclick={() => (checked = true)}>Enable</button>
<button class="btn btn-sm" onclick={() => (checked = false)}>Disable</button>
<span class="chip">Controlled state: {checked ? 'on' : 'off'}</span>
</div>
<div class="panel divide-y divide-ink-800">
<div class="flex items-center gap-4 p-4">
<Label.Root for="quiet-hours" class="flex-1 text-sm font-medium text-ink-50">Quiet hours</Label.Root>
<Switch.Root
id="quiet-hours"
bind:checked
class="inline-flex h-7 w-12 items-center rounded-full border border-ink-700 bg-ink-800 p-0.5 data-[state=checked]:border-brand-500 data-[state=checked]:bg-brand-500"
>
<Switch.Thumb class="block size-5 rounded-full bg-ink-200 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0" />
</Switch.Root>
</div>
<div class="flex items-center gap-4 p-4 opacity-50">
<div class="flex-1">
<Label.Root for="managed-alerts" class="text-sm font-medium text-ink-50">Security alerts</Label.Root>
<p class="muted mt-1 text-xs">Managed by your organization</p>
</div>
<Switch.Root
id="managed-alerts"
checked
disabled
class="inline-flex h-7 w-12 items-center rounded-full border border-brand-500 bg-brand-500 p-0.5 data-disabled:cursor-not-allowed"
>
<Switch.Thumb class="block size-5 translate-x-5 rounded-full bg-ink-950" />
</Switch.Root>
</div>
</div>
</div>
Both Switch.Root and Switch.Thumb expose data-state="checked|unchecked". The root also exposes data-disabled; bind checked when an external control must drive the switch.
A name on the root creates a hidden input for form submission. Its checked payload defaults to "on", value supplies a custom payload, and required is applied to that hidden input so native form validation can require the switch to be on.