PhiaUi.Components.Toggle (phia_ui v0.1.16)

Copy Markdown View Source

Pressable toggle button component with aria-pressed semantics.

A two-state button that communicates its on/off state through the aria-pressed ARIA attribute. Ideal for toolbar actions (Bold, Italic, Underline), filter buttons, or any feature that the user activates by clicking.

When to use

Use toggle/1 when:

  • The button represents an on/off feature that applies while pressed (e.g. text formatting)
  • The pressed state is visually distinct from the unpressed state
  • You need the aria-pressed semantics that button[aria-pressed] provides

Use switch/1 instead for binary settings (on/off configurations that persist), and toggle_group/1 when multiple toggles need to coordinate as a single or multi-select group.

State ownership

State is owned by the server — pass :pressed from your LiveView assigns and update it on the server via phx-click. For purely client-side toggling without a server round-trip, wire Phoenix.LiveView.JS push/toggle operations:

<.toggle pressed={@bold} phx-click="toggle_bold">
  <.icon name="bold" size="sm" />
</.toggle>

Text editor toolbar example

<div class="flex items-center gap-1 border rounded-md p-1">
  <.toggle pressed={@bold} phx-click="toggle_format" phx-value-format="bold">
    <.icon name="bold" size="sm" />
  </.toggle>
  <.toggle pressed={@italic} phx-click="toggle_format" phx-value-format="italic">
    <.icon name="italic" size="sm" />
  </.toggle>
  <.toggle pressed={@underline} phx-click="toggle_format" phx-value-format="underline">
    <.icon name="underline" size="sm" />
  </.toggle>
</div>

Filter tag example

<div class="flex flex-wrap gap-2">
  <.toggle
    :for={tag <- @available_tags}
    pressed={tag in @active_tags}
    phx-click="toggle_tag"
    phx-value-tag={tag}
    variant="outline"
    size="sm"
  >
    {tag}
  </.toggle>
</div>

Variants

  • "default" — ghost-like, transparent background, switches to bg-accent when pressed
  • "outline" — shows a border-input border, switches to bg-accent when pressed

Sizes

  • "sm"h-9 px-2.5 text-xs, compact for toolbars
  • "default"h-10 px-3, standard size
  • "lg"h-11 px-5, larger click target

Accessibility

  • aria-pressed="true" / "false" reflects the current state to screen readers
  • Focus ring (focus-visible:ring-2) ensures keyboard navigability
  • disabled attribute prevents interaction and sets pointer-events-none
  • Content (slot) should include descriptive text or an icon with aria-label

Summary

Functions

Renders a pressable toggle button with aria-pressed state.

Functions

toggle(assigns)

Renders a pressable toggle button with aria-pressed state.

The <button> receives type="button" to prevent accidental form submission. Visual state is communicated via background colour change (variant-controlled) in addition to the aria-pressed attribute for screen readers.

Examples

<%!-- Icon toggle in a toolbar --%>
<.toggle pressed={@bold} phx-click="toggle_bold">
  <.icon name="bold" size="sm" />
</.toggle>

<%!-- Text toggle --%>
<.toggle pressed={@active} phx-click="toggle">
  Compact view
</.toggle>

<%!-- Outline variant --%>
<.toggle pressed={@italic} variant="outline" phx-click="toggle_italic">
  <.icon name="italic" size="sm" />
</.toggle>

<%!-- Small toolbar toggle with aria-label --%>
<.toggle pressed={@underline} size="sm" phx-click="toggle_underline" aria-label="Underline">
  <.icon name="underline" size="sm" />
</.toggle>

<%!-- Disabled --%>
<.toggle pressed={false} disabled>
  Unavailable
</.toggle>

<%!-- Filter tag pattern --%>
<.toggle
  pressed={"elixir" in @selected_tags}
  phx-click="toggle_tag"
  phx-value-tag="elixir"
  variant="outline"
  size="sm"
>
  Elixir
</.toggle>

Attributes

  • pressed (:boolean) (required) - Whether the toggle is in the pressed (active) state. Controls the visual appearance and the aria-pressed attribute. Pass a boolean from your LiveView assigns and update it via a phx-click event handler.

  • variant (:string) - Visual style of the toggle button:

    • "default" — ghost-like with transparent background. On press: bg-accent
    • "outline" — shows a border-input border. On press: bg-accent with border

    Defaults to "default". Must be one of "default", or "outline".

  • size (:string) - Size of the toggle button. Controls height and horizontal padding:

    • "sm"h-9 px-2.5 text-xs (compact, ideal for toolbars)
    • "default"h-10 px-3 (standard)
    • "lg"h-11 px-5 (larger click target)

    Defaults to "default". Must be one of "default", "sm", or "lg".

  • class (:string) - Additional CSS classes applied to the <button> element via cn/1. Last-wins merge means your classes override the size/variant defaults.

    Defaults to nil.

  • Global attributes are accepted. HTML attributes forwarded to the <button> element. Commonly used:

    • phx-click — LiveView event name to handle the toggle
    • phx-value-* — additional context passed with the event (e.g. phx-value-format="bold")
    • disabled — disables the button Supports all globals plus: ["disabled", "form", "name", "value", "type", "phx-click", "phx-value"].

Slots

  • inner_block (required) - The content of the toggle button — typically an icon or short text label. For icon-only toggles, add aria-label via :rest to describe the action for screen readers.