Corex.Toggle (Corex v0.1.2)

View Source

Phoenix implementation of Zag.js Toggle.

Anatomy

Minimal

<.toggle class="toggle">
  lorem
</.toggle>

With indicator

<.toggle class="toggle">
  <:indicator><.heroicon name="hero-bold" /></:indicator>
  Bold
</.toggle>

<.toggle class="toggle">
  <:indicator><.heroicon name="hero-bold" /></:indicator>
  <span class="sr-only">Bold</span>
</.toggle>

Dual label

Set data-toggle-dual-label on the host to swap visible label text when pressed. Use a second <span data-pressed> for the on-state label.

<.toggle class="toggle" data-toggle-dual-label>
  <span>lorem</span>
  <span data-pressed>donec</span>
</.toggle>

API

Requires a stable id on <.toggle>.

FunctionActionReturns
set_pressed/2Set pressed state (client)%Phoenix.LiveView.JS{}
set_pressed/3Set pressed state (server)socket
toggle_pressed/2Toggle pressed (client)%Phoenix.LiveView.JS{}
toggle_pressed/3Toggle pressed (server)socket

Events

Pick an event name and pass it to on_* on <.toggle>.

Server events

EventWhenPayload
on_pressed_change="toggle_pressed_changed"Pressed state changes%{"id" => id, "pressed" => boolean}

on_pressed_change

<.toggle
  class="toggle"
  controlled
  pressed={false}
  on_pressed_change="toggle_pressed_changed"
>
  lorem
</.toggle>
def handle_event("toggle_pressed_changed", %{"pressed" => pressed}, socket) do
  p = pressed == true or pressed == "true"
  {:noreply, assign(socket, :pressed, p)}
end

Client events

EventWhenevent.detail
on_pressed_change_client="toggle-client-changed"Pressed state changesid, pressed

on_pressed_change_client

<.toggle
  id="toggle-on-pressed-change-client"
  class="toggle"
  on_pressed_change_client="toggle-client-changed"
>
  lorem
</.toggle>
const el = document.getElementById("toggle-on-pressed-change-client");
el?.addEventListener("toggle-client-changed", (e) => console.log(e.detail));

Patterns

Controlled

For server-owned pressed state, set controlled, bind pressed, and handle on_pressed_change in LiveView.

<.toggle
  class="toggle"
  controlled
  pressed={@pressed}
  on_pressed_change="toggle_patterns_pressed"
>
  lorem
</.toggle>
def mount(_params, _session, socket) do
  {:ok, assign(socket, :pressed, false)}
end

def handle_event("toggle_patterns_pressed", %{"pressed" => pressed}, socket) do
  {:noreply, assign(socket, :pressed, pressed == true or pressed == "true")}
end

Style

Target parts with data-scope and data-part, or use Corex Design: import tokens and toggle.css, then set class="toggle" on <.toggle>.

[data-scope="toggle"][data-part="root"] {}
[data-scope="toggle"][data-part="indicator"] {}
@import "../corex/main.css";
@import "../corex/tokens/themes/neo/light.css";
@import "../corex/components/toggle.css";

Stack modifiers on the host (class on <.toggle>).

Color

ModifierClasses
Defaulttoggle
Accenttoggle toggle--accent
Brandtoggle toggle--brand
Alerttoggle toggle--alert
Infotoggle toggle--info
Successtoggle toggle--success

Size

ModifierClasses
SMtoggle toggle--sm
MDtoggle toggle--md
LGtoggle toggle--lg
XLtoggle toggle--xl

Rounded

ModifierClasses
Nonetoggle toggle--rounded-none
SMtoggle toggle--rounded-sm
MDtoggle toggle--rounded-md
LGtoggle toggle--rounded-lg
XLtoggle toggle--rounded-xl
Fulltoggle toggle--rounded-full

Summary

API

Set pressed state from a control (phx-click).

Set pressed state from handle_event.

Flip pressed state from a control (phx-click).

Flip pressed state from handle_event.

Components

toggle(assigns)

Attributes

  • id (:string)
  • pressed (:boolean) - Initial or controlled pressed state. Defaults to false.
  • controlled (:boolean) - Defaults to false.
  • disabled (:boolean) - Defaults to false.
  • dir (:string) - When nil, derived from document. Defaults to nil. Must be one of nil, "ltr", or "rtl".
  • on_pressed_change (:string) - Defaults to nil.
  • on_pressed_change_client (:string) - Defaults to nil.
  • Global attributes are accepted.

Slots

  • inner_block
  • indicator - Accepts attributes:
    • class (:string)

API

set_pressed(toggle_id, pressed)

Set pressed state from a control (phx-click).

<.action phx-click={Corex.Toggle.set_pressed("my-toggle", true)}>On</.action>
<.toggle id="my-toggle" class="toggle">Label</.toggle>
document.getElementById("my-toggle")?.dispatchEvent(
  new CustomEvent("corex:toggle:set-pressed", {
    bubbles: false,
    detail: { pressed: true },
  })
);

set_pressed(socket, toggle_id, pressed)

Set pressed state from handle_event.

<.action phx-click="press_toggle">On</.action>
<.toggle id="my-toggle" class="toggle">Label</.toggle>
def handle_event("press_toggle", _, socket) do
  {:noreply, Corex.Toggle.set_pressed(socket, "my-toggle", true)}
end

toggle_pressed(toggle_id)

Flip pressed state from a control (phx-click).

<.action phx-click={Corex.Toggle.toggle_pressed("my-toggle")}>Toggle</.action>
<.toggle id="my-toggle" class="toggle">Label</.toggle>
document.getElementById("my-toggle")?.dispatchEvent(
  new CustomEvent("corex:toggle:toggle-pressed", { bubbles: false })
);

toggle_pressed(socket, toggle_id)

Flip pressed state from handle_event.

<.action phx-click="flip_toggle">Toggle</.action>
<.toggle id="my-toggle" class="toggle">Label</.toggle>
def handle_event("flip_toggle", _, socket) do
  {:noreply, Corex.Toggle.toggle_pressed(socket, "my-toggle")}
end