# `PhiaUi.Components.Switch`
[🔗](https://github.com/charlenopires/PhiaUI/blob/v0.1.17/lib/phia_ui/components/inputs/switch.ex#L1)

Accessible on/off switch component for Phoenix LiveView.

A two-state toggle rendered as a pill-shaped track with an animated sliding
thumb. Uses `role="switch"` and `aria-checked` for full WAI-ARIA compliance.
The animation is pure CSS (`translate-x` transition) — zero JavaScript required.

## Sub-components

| Function       | Purpose                                                              |
|----------------|----------------------------------------------------------------------|
| `switch/1`     | Standalone switch button — manage state in your LiveView             |
| `form_switch/1`| Switch integrated with `Phoenix.HTML.FormField` and Ecto changesets  |

## When to use

Use a switch for binary settings that take effect immediately or are submitted
as part of a form. Switches communicate an on/off state more clearly than
checkboxes for settings like "Enable notifications", "Public profile", or
"Auto-renew subscription".

Use a `checkbox/1` instead when the control is part of a list of options, or
when the action requires explicit confirmation (e.g. "I agree to the terms").

## Standalone usage

    <%!-- Server-state switch: the LiveView owns the boolean --%>
    <.switch checked={@notifications_enabled} phx-click="toggle_notifications" />

    <%!-- Labelled by wrapping in a <label> --%>
    <label class="flex items-center gap-3 cursor-pointer">
      <.switch checked={@dark_mode} phx-click="toggle_dark_mode" />
      <span class="text-sm font-medium">Dark mode</span>
    </label>

    <%!-- Disabled --%>
    <.switch checked={true} disabled />

## Form-integrated usage

`form_switch/1` wraps a hidden checkbox so the value is submitted as part of
the form. Clicking the visual switch toggles the hidden input without JS:

    <.form for={@form} phx-submit="save_settings" phx-change="validate">
      <.form_switch field={@form[:email_notifications]} label="Email notifications" />
      <.form_switch field={@form[:sms_notifications]}   label="SMS notifications" />
      <.form_switch field={@form[:marketing_emails]}    label="Marketing emails" />
      <.button type="submit">Save settings</.button>
    </.form>

## Settings panel example

    defmodule MyAppWeb.SettingsLive do
      use MyAppWeb, :live_view

      def mount(_params, _session, socket) do
        changeset = Settings.change_notifications(socket.assigns.current_user)
        {:ok, assign(socket, form: to_form(changeset))}
      end

      def handle_event("save_settings", %{"settings" => params}, socket) do
        case Settings.update_notifications(socket.assigns.current_user, params) do
          {:ok, _settings} -> {:noreply, put_flash(socket, :info, "Settings saved")}
          {:error, changeset} -> {:noreply, assign(socket, form: to_form(changeset))}
        end
      end
    end

## Accessibility

- `role="switch"` identifies the element as a switch widget to screen readers
- `aria-checked="true"` / `"false"` reflects the on/off state
- `disabled` prevents interaction and sets `aria-disabled` via the native attribute
- The focus ring (`focus-visible:ring-2`) ensures keyboard navigability
- In `form_switch/1`, the label is associated with the hidden input via `for`/`id`

# `form_switch`

Renders a switch integrated with `Phoenix.HTML.Form`.

Internally uses a hidden `<input type="checkbox">` so the value is submitted
as part of the form payload without JavaScript. The visual `switch/1` component
reads `checked` from the field value and reflects the state via CSS.

The `<label>` wraps both the hidden checkbox and the visual switch, making
the entire row clickable to toggle the value. This is the standard PhiaUI
pattern for form-bound switches.

The field value is normalised via `truthy?/1` which handles `true`, `"true"`,
`"on"`, `1`, and `"1"` as truthy — matching all the ways a checkbox value
may arrive from browser submissions or Ecto changesets.

## Examples

    <%!-- Settings form --%>
    <.form for={@form} phx-submit="save">
      <.form_switch field={@form[:active]}         label="Account active" />
      <.form_switch field={@form[:email_opt_in]}   label="Email notifications" />
      <.form_switch field={@form[:two_factor_auth]} label="Two-factor authentication" />
      <.button type="submit">Save</.button>
    </.form>

    <%!-- Single inline setting --%>
    <.form_switch field={@form[:public_profile]} label="Make profile public" />

    <%!-- Without label --%>
    <.form_switch field={@form[:enabled]} />

## Attributes

* `field` (`Phoenix.HTML.FormField`) (required) - A `Phoenix.HTML.FormField` struct obtained via `@form[:field_name]`. Provides
  the hidden input `id` and `name`, and the current `value` used to derive the
  `checked` state via `truthy?/1`.

* `label` (`:string`) - Text rendered next to the switch inside a `<label>`. The label wraps both
  the hidden input and the visual switch, so clicking anywhere on the row
  (label text or switch) toggles the checkbox. When `nil`, only the switch
  is rendered.

  Defaults to `nil`.
* `class` (`:string`) - Additional CSS classes applied to the `<label>` wrapper element. Defaults to `nil`.

# `switch`

Renders a standalone accessible switch button.

The switch is a `<button type="button">` with `role="switch"` and
`aria-checked`. Track colour transitions from `bg-input` (off) to `bg-primary`
(on). The thumb slides with a `translate-x` CSS transition — no JavaScript.

Manage the state in your LiveView by passing `:checked` from your assigns
and handling the `phx-click` event to toggle the boolean:

    # In your LiveView:
    def handle_event("toggle_notifications", _params, socket) do
      {:noreply, assign(socket, notifications: !socket.assigns.notifications)}
    end

    # In your template:
    <.switch checked={@notifications} phx-click="toggle_notifications" />

## Examples

    <%!-- Basic off/on --%>
    <.switch checked={false} phx-click="toggle" />
    <.switch checked={true}  phx-click="toggle" />

    <%!-- Disabled --%>
    <.switch checked={false} disabled />
    <.switch checked={true}  disabled />

    <%!-- With phx-value for context --%>
    <.switch
      checked={@feature_enabled}
      phx-click="toggle_feature"
      phx-value-feature="dark_mode"
    />

    <%!-- Custom size via class --%>
    <.switch checked={@enabled} phx-click="toggle" class="scale-90" />

## Attributes

* `checked` (`:boolean`) (required) - Whether the switch is in the on (checked) state. Controls the track colour
  and thumb position. Pass a boolean from your LiveView assigns and update it
  via `phx-click`.

* `disabled` (`:boolean`) - When `true`, disables the switch. The button becomes non-interactive
  (`pointer-events-none`) and renders at 50% opacity to communicate its
  inactive state. The native `disabled` attribute is also set.

  Defaults to `false`.
* `class` (`:string`) - Additional CSS classes applied to the outer `<button>` element via `cn/1`.
  Use to adjust sizing or spacing. Example: `class="scale-125"`.

  Defaults to `nil`.
* Global attributes are accepted. HTML attributes forwarded to the `<button>` element. Typically used for
  `phx-click` to toggle state in the LiveView:
  `phx-click="toggle_feature" phx-value-feature="notifications"`
 Supports all globals plus: `["phx-click", "phx-value", "name"]`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
