Skip to main content

Switch

Switch

Toggle switch for binary on/off settings

Tags: component form toggle

View Demo

Switch is a toggle control for binary settings, providing an alternative to checkboxes for on/off states.

Import​

<script>
  import { Switch } from '@classic-homes/theme-svelte';
</script>

Basic Usage​

<script>
  let enabled = $state(false);
</script>

<Switch bind:checked={enabled} />

Props​

Prop Type Default Description
checked boolean false Whether the switch is on (bindable)
disabled boolean false Disables the switch
required boolean false Marks as required
name string - Name attribute for forms
value string - Value attribute for forms
id string - Element ID for label association
class string - Additional CSS classes
onchange (checked: boolean) => void - Callback when checked state changes

With Label​

Pair switches with descriptive labels:

<script>
  import { Switch, Label } from '@classic-homes/theme-svelte';

  let darkMode = $state(false);
</script>

<div class="flex items-center gap-3">
  <Switch id="dark-mode" bind:checked={darkMode} />
  <Label for="dark-mode">Dark mode</Label>
</div>

States​

On (Checked)​

<Switch checked />

Off (Unchecked)​

<Switch />

Disabled​

<Switch disabled />
<Switch disabled checked />

Controlled Switch​

Use onchange for controlled behavior:

<script>
  let notifications = $state(false);

  function handleChange(newChecked: boolean) {
    // Save preference to server
    savePreference('notifications', newChecked);
    notifications = newChecked;
  }
</script>

<Switch checked={notifications} onchange={handleChange} />

Switch vs Checkbox​

Use Switch when:

  • The setting takes effect immediately (no form submission)
  • The option is a clear on/off toggle
  • You want a more visual, mobile-friendly control

Use Checkbox when:

  • The selection is part of a form that will be submitted
  • Multiple selections are possible
  • The change requires explicit save/submit

Settings Pattern​

Common pattern for settings pages:

<script>
  import { Switch, Label } from '@classic-homes/theme-svelte';

  let settings = $state({
    notifications: true,
    emailUpdates: false,
    autoSave: true,
  });
</script>

<div class="space-y-6">
  <div class="flex items-center justify-between">
    <div>
      <Label for="notifications" class="text-base font-medium">Notifications</Label>
      <p class="text-sm text-muted-foreground">Receive push notifications</p>
    </div>
    <Switch id="notifications" bind:checked={settings.notifications} />
  </div>

  <div class="flex items-center justify-between">
    <div>
      <Label for="email-updates" class="text-base font-medium">Email Updates</Label>
      <p class="text-sm text-muted-foreground">Receive weekly email updates</p>
    </div>
    <Switch id="email-updates" bind:checked={settings.emailUpdates} />
  </div>

  <div class="flex items-center justify-between">
    <div>
      <Label for="auto-save" class="text-base font-medium">Auto-save</Label>
      <p class="text-sm text-muted-foreground">Automatically save changes</p>
    </div>
    <Switch id="auto-save" bind:checked={settings.autoSave} />
  </div>
</div>

Touch Target​

The Switch component includes an expanded touch target that extends beyond the visible switch, ensuring easy tapping on mobile devices.

Accessibility​

The Switch component includes:

  • Uses Bits UI Switch primitive for proper accessibility
  • Keyboard navigation (Space to toggle)
  • Expanded touch target for mobile
  • Proper ARIA role and state
  • Visual focus indicator
  • Smooth thumb animation
Keyboard Navigation

Press Space to toggle a focused switch. Tab moves focus between switches.

Examples​

Feature Toggle​

<script>
  let betaFeatures = $state(false);
</script>

<div class="p-4 border rounded-lg">
  <div class="flex items-center justify-between">
    <div>
      <h3 class="font-medium">Beta Features</h3>
      <p class="text-sm text-muted-foreground">Enable experimental features</p>
    </div>
    <Switch bind:checked={betaFeatures} />
  </div>

  {#if betaFeatures}
    <p class="mt-3 text-sm text-warning">Beta features may be unstable.</p>
  {/if}
</div>

Privacy Controls​

<script>
  let privacy = $state({
    analytics: true,
    personalization: false,
    thirdParty: false,
  });
</script>

<div class="space-y-4">
  <h2 class="text-lg font-semibold">Privacy Settings</h2>

  <div class="space-y-3">
    <div class="flex items-center justify-between">
      <Label for="analytics">Analytics cookies</Label>
      <Switch id="analytics" bind:checked={privacy.analytics} />
    </div>

    <div class="flex items-center justify-between">
      <Label for="personalization">Personalization</Label>
      <Switch id="personalization" bind:checked={privacy.personalization} />
    </div>

    <div class="flex items-center justify-between">
      <Label for="third-party">Third-party cookies</Label>
      <Switch id="third-party" bind:checked={privacy.thirdParty} />
    </div>
  </div>
</div>

Inline Switch​

<p class="text-sm">
  Show completed tasks
  <Switch bind:checked={showCompleted} class="ml-2 align-middle" />
</p>
On this page