Switch

On/off toggle with size and color variants.

Basic

.heex
<.switch name="notifications" label="Enable notifications" />

Sublabel and description

Pair sublabel for a short inline qualifier with description for longer copy beneath the label.

Recommended

Automatically save your changes every few seconds.

Optional

A summary of new features shipped with each release.

.heex
<div class="flex flex-col gap-y-4 max-w-sm">
  <.switch
    name="auto_save"
    label="Auto save"
    sublabel="Recommended"
    description="Automatically save your changes every few seconds."
  />
  <.switch
    name="release_notes"
    label="Release notes"
    sublabel="Optional"
    description="A summary of new features shipped with each release."
  />
</div>

Sizes

The size attribute scales the track and thumb together. Pick sm for dense layouts, md as the default, and lg for touch surfaces or emphasized settings.

.heex
<.switch name="compact" label="Compact mode" size="sm" />
<.switch name="default" label="Default" />
<.switch name="emphasis" label="Important setting" size="lg" />

Colors

The color attribute tints the track when the switch is on, reinforcing the meaning of the setting being toggled.

Experimental
.heex
<.switch name="primary" label="Primary" checked />
<.switch name="backups" label="Automatic backups" color="success" checked />
<.switch name="beta" label="Beta features" sublabel="Experimental" color="warning" checked />
<.switch name="public" label="Public profile" color="danger" checked />
<.switch name="analytics" label="Anonymous analytics" color="info" checked />

Disabled

Add disabled to grey out the label, sublabel, and description, and disable the hidden mirror input so the field is omitted from the submitted payload.

Upgrade required

This setting is included with the Pro plan.

.heex
<.switch
  name="premium_feature"
  label="Premium feature"
  sublabel="Upgrade required"
  description="This setting is included with the Pro plan."
  disabled
/>

Custom values

Override checked_value and unchecked_value when the schema expects 1/0 or tokens like on/off.

Submits 1 when on and 0 when off.

Submits on or off, matching the legacy schema.

.heex
<div class="flex flex-col gap-y-4 max-w-sm">
  <.switch
    name="active"
    label="Account active"
    description="Submits 1 when on and 0 when off."
    checked_value="1"
    unchecked_value="0"
    checked
  />
  <.switch
    name="feature"
    label="Experimental feature"
    description="Submits on or off, matching the legacy schema."
    checked_value="on"
    unchecked_value="off"
  />
</div>

Standalone toggle

Pair name with checked and phx-click to drive a LiveView event handler directly, without a backing changeset.

.heex
<.switch
  name="dark_mode"
  label="Dark mode"
  checked={@dark_mode}
  phx-click="toggle_theme"
/>

Settings panel

Stack switches in a vertical list to build a preferences surface. Each toggle reads as its own decision, and color reinforces the meaning of the setting.

Mobile and desktop

Receive alerts when something needs your attention.

Daily digests and important account activity.

Optional

Hear about new features, launches, and the occasional sale.

.heex
<div class="flex flex-col gap-5 max-w-sm">
  <.switch
    name="push_notifications"
    label="Push notifications"
    sublabel="Mobile and desktop"
    description="Receive alerts when something needs your attention."
    checked
  />
  <.switch
    name="email_notifications"
    label="Email notifications"
    description="Daily digests and important account activity."
    color="info"
    checked
  />
  <.switch
    name="marketing_emails"
    label="Marketing communications"
    sublabel="Optional"
    description="Hear about new features, launches, and the occasional sale."
    color="info"
  />
</div>

Settings rows

Pass class="flex-row-reverse w-full justify-between" to push the toggle to the right of the row, the layout most account and notification settings pages reach for.

Require a verification code in addition to your password.

A summary of activity in your workspace, sent every Monday.

Allow other users on the platform to view your profile.

.heex
<div class="divide-y divide-base rounded-lg border border-base">
  <.switch
    class="flex-row-reverse w-full justify-between p-4"
    name="two_factor"
    label="Two-factor authentication"
    description="Require a verification code in addition to your password."
    color="success"
    checked
  />
  <.switch
    class="flex-row-reverse w-full justify-between p-4"
    name="weekly_digest"
    label="Weekly digest"
    description="A summary of activity in your workspace, sent every Monday."
  />
  <.switch
    class="flex-row-reverse w-full justify-between p-4"
    name="public_profile"
    label="Public profile"
    description="Allow other users on the platform to view your profile."
    color="danger"
  />
</div>

Form integration

Bind each switch to a Phoenix.HTML.FormField through field. The component derives id, name, and the current value, and a hidden mirror input keeps the field in form data even when the toggle is off.

Require a verification code in addition to your password.

Allow other users to view your profile.

.heex
<.form :let={f} for={@form} phx-change="validate" phx-submit="save">
  <.switch
    field={f[:two_factor_enabled]}
    label="Two-factor authentication"
    description="Require a verification code in addition to your password."
    color="success"
  />
  <.switch
    field={f[:public_profile]}
    label="Public profile"
    description="Allow other users to view your profile."
    color="danger"
  />
  <.switch field={f[:active]} label="Account active" checked_value="1" unchecked_value="0" />

  <.button type="submit">Save changes</.button>
</.form>

Switch outside its form

Pass form="..." to bind the switch to a form by id when the toggle sits in a sticky footer, sidebar, or header outside the <form> element.

Sign-up form fields live here.

.heex
<form id="signup-form" phx-submit="register">
  <%!-- form fields --%>
</form>

<div class="sticky bottom-0 p-4">
  <.switch name="agree" label="I agree to the terms" form="signup-form" />
  <.button type="submit" form="signup-form">Sign up</.button>
</div>