Corex.Accordion (Corex v0.1.0-alpha.13)

View Source

Phoenix implementation of Zag.js Accordion.

Examples

List

You must use Corex.Accordion.Item struct for items.

The value for each item is optional, useful for controlled mode and API to identify the item.

You can specify disabled for each item.

<.accordion
  class="accordion"
  items={[
    %Corex.Accordion.Item{
      trigger: "Lorem ipsum dolor sit amet",
      content: "Consectetur adipiscing elit. Sed sodales ullamcorper tristique."
    },
    %Corex.Accordion.Item{
      trigger: "Duis dictum gravida odio ac pharetra?",
      content: "Nullam eget vestibulum ligula, at interdum tellus."
    },
    %Corex.Accordion.Item{
      trigger: "Donec condimentum ex mi",
      content: "Congue molestie ipsum gravida a. Sed ac eros luctus."
    }
  ]}
/>

List Custom

Similar to List but render a custom item slot that will be used for all items.

Use {item.meta.trigger} and {item.meta.content} to render the trigger and content for each item.

This example assumes the import of .icon from Core Components

  <.accordion
  class="accordion"
  items={[
    %Corex.Accordion.Item{
      value: "lorem",
      trigger: "Lorem ipsum dolor sit amet",
      content: "Consectetur adipiscing elit. Sed sodales ullamcorper tristique.",
      meta: %{
        indicator: "hero-chevron-right",
      }
    },
    %Corex.Accordion.Item{
      trigger: "Duis dictum gravida odio ac pharetra?",
      content: "Nullam eget vestibulum ligula, at interdum tellus.",
      meta: %{
        indicator: "hero-chevron-right",
      }
    },
    %Corex.Accordion.Item{
      value: "donec",
      trigger: "Donec condimentum ex mi",
      content: "Congue molestie ipsum gravida a. Sed ac eros luctus.",
      disabled: true,
      meta: %{
        indicator: "hero-chevron-right",
      }
    }
  ]}
>
  <:item :let={item}>
    <.accordion_trigger item={item}>
      {item.data.trigger}
      <:indicator>
        <.icon name={item.data.meta.indicator} />
      </:indicator>
    </.accordion_trigger>

    <.accordion_content item={item}>
      {item.data.content}
    </.accordion_content>
  </:item>
</.accordion>

Custom

Render a custom item slot per accordion item manually.

Use let={item} to get the item data and pass it to the accordion_trigger/1 and accordion_content/1 components.

The trigger component takes an optional :indicator slot to render the indicator ico

This example assumes the import of .icon from Core Components

<.accordion id="my-accordion" value={["duis"]} class="accordion">
<:item :let={item} value="lorem" disabled>
  <.accordion_trigger item={item}>
    Lorem ipsum dolor sit amet
    <:indicator>
     <.icon name="hero-chevron-right" />
    </:indicator>
  </.accordion_trigger>
  <.accordion_content item={item}>
    Consectetur adipiscing elit. Sed sodales ullamcorper tristique. Proin quis risus feugiat tellus iaculis fringilla.
  </.accordion_content>
</:item>
<:item :let={item} value="duis">
  <.accordion_trigger item={item}>
    Duis dictum gravida odio ac pharetra?
    <:indicator>
     <.icon name="hero-chevron-right" />
    </:indicator>
  </.accordion_trigger>
  <.accordion_content item={item}>
    Nullam eget vestibulum ligula, at interdum tellus. Quisque feugiat, dui ut fermentum sodales, lectus metus dignissim ex.
  </.accordion_content>
</:item>
</.accordion>

Controlled

Render an accordion controlled by the server.

You must use the on_value_change event to update the value on the server and pass the value as a list of strings.

The event will receive the value as a map with the key value and the id of the accordion.

defmodule MyAppWeb.AccordionLive do
use MyAppWeb, :live_view

def mount(_params, _session, socket) do
  {:ok, assign(socket, :value, ["lorem"])}
end

def handle_event("on_value_change", %{"value" => value}, socket) do
  {:noreply, assign(socket, :value, value)}
end

def render(assigns) do
  ~H"""
  <.accordion value={@value} on_value_change="on_value_change" class="accordion">
    <:item :let={item} value="lorem">
      <.accordion_trigger item={item}>
        Lorem ipsum dolor sit amet
      </.accordion_trigger>
      <.accordion_content item={item}>
        Consectetur adipiscing elit. Sed sodales ullamcorper tristique. Proin quis risus feugiat tellus iaculis fringilla.
      </.accordion_content>
    </:item>
    <:item :let={item} value="duis">
      <.accordion_trigger item={item}>
        Duis dictum gravida odio ac pharetra?
      </.accordion_trigger>
      <.accordion_content item={item}>
        Nullam eget vestibulum ligula, at interdum tellus. Quisque feugiat, dui ut fermentum sodales, lectus metus dignissim ex.
      </.accordion_content>
    </:item>
  </.accordion>
"""
end
end

Async

When the initial props are not available on mount, you can use the Phoenix.LiveView.assign_async function to assign the props asynchronously

You can use the optional Corex.Accordion.accordion_skeleton/1 to render a loading or error state

defmodule MyAppWeb.AccordionAsyncLive do
use MyAppWeb, :live_view

def mount(_params, _session, socket) do
  socket =
    socket
    |> assign_async(:accordion, fn ->
      Process.sleep(1000)

      items = [
        %Corex.Accordion.Item{
          value: "lorem",
          trigger: "Lorem ipsum dolor sit amet",
          content: "Consectetur adipiscing elit. Sed sodales ullamcorper tristique.",
          disabled: true
        },
        %Corex.Accordion.Item{
          value: "duis",
          trigger: "Duis dictum gravida odio ac pharetra?",
          content: "Nullam eget vestibulum ligula, at interdum tellus."
        },
        %Corex.Accordion.Item{
          value: "donec",
          trigger: "Donec condimentum ex mi",
          content: "Congue molestie ipsum gravida a. Sed ac eros luctus."
        }
      ]

      {:ok,
       %{
         accordion: %{
           items: items,
           value: ["duis", "donec"]
         }
       }}
    end)

  {:ok, socket}
end

def render(assigns) do
  ~H"""
  <Layouts.app flash={@flash}>
    <div class="layout__row">
      <h1>Accordion</h1>
      <h2>Async</h2>
    </div>

    <.async_result :let={accordion} assign={@accordion}>
      <:loading>
        <.accordion_skeleton count={3} class="accordion" />
      </:loading>

      <:failed>
        there was an error loading the accordion
      </:failed>

      <.accordion
        id="async-accordion"
        class="accordion"
        items={accordion.items}
        value={accordion.value}
      />
    </.async_result>
  </Layouts.app>
  """
end
end

API Control

Client-side

<button phx-click={Corex.Accordion.set_value("my-accordion", ["item-1"])}>
  Open Item 1
</button>

Server-side

def handle_event("open_item", _, socket) do
  {:noreply, Corex.Accordion.set_value(socket, "my-accordion", ["item-1"])}
end

Styling

Use data attributes to target elements:

[data-scope="accordion"][data-part="root"] {}
[data-scope="accordion"][data-part="item"] {}
[data-scope="accordion"][data-part="item-trigger"] {}
[data-scope="accordion"][data-part="item-content"] {}
[data-scope="accordion"][data-part="item-indicator"] {}

Summary

Components

Renders an accordion component.

Renders the accordion content area.

Renders a loading skeleton for the accordion component.

Renders the accordion trigger button. Includes optional :indicator slot.

API

Sets the accordion value from client-side. Returns a Phoenix.LiveView.JS command.

Sets the accordion value from server-side. Pushes a LiveView event.

Components

accordion(assigns)

Renders an accordion component.

You can use either:

  • The :item slot for manual item definition with full control
  • The :items attribute for programmatic item generation from a list of %Corex.Accordion.Item{} structs

When using :items, each item MUST be a %Corex.Accordion.Item{} struct with:

  • :value (required) - unique identifier for the item
  • :trigger (required) - content for the trigger button
  • :content (optional, default: "") - content for the accordion panel
  • :disabled (optional, default: false) - whether the item is disabled

Attributes

  • id (:string) - The id of the accordion, useful for API to identify the accordion.
  • items (:list) - The items of the accordion, must be a list of %Corex.Accordion.Item{} structs. Defaults to nil.
  • value (:list) - The initial value or the controlled value of the accordion, must be a list of strings. Defaults to [].
  • controlled (:boolean) - Whether the accordion is controlled. Only in LiveView, the on_value_change event is required. Defaults to false.
  • collapsible (:boolean) - Whether the accordion is collapsible. Defaults to true.
  • disabled (:boolean) - Whether the accordion is disabled. Defaults to false.
  • multiple (:boolean) - Whether the accordion allows multiple items to be selected. Defaults to true.
  • orientation (:string) - The orientation of the accordion. Defaults to "vertical". Must be one of "horizontal", or "vertical".
  • dir (:string) - The direction of the accordion. Defaults to "ltr". Must be one of "ltr", or "rtl".
  • on_value_change (:string) - The server event name when the value change. Defaults to nil.
  • on_value_change_client (:string) - The client event name when the value change. Defaults to nil.
  • on_focus_change (:string) - The server event name when the focus change. Defaults to nil.
  • on_focus_change_client (:string) - The client event name when the focus change. Defaults to nil.
  • Global attributes are accepted.

Slots

  • item - Accepts attributes:
    • value (:string) - The value of the item, useful in controlled mode and for API to identify the item.
    • disabled (:boolean) - Whether the item is disabled.

accordion_content(assigns)

Renders the accordion content area.

Attributes

  • item (:map) (required)

Slots

  • inner_block (required)

accordion_skeleton(assigns)

Renders a loading skeleton for the accordion component.

Attributes

  • count (:integer) - Defaults to 3.
  • Global attributes are accepted.

Slots

  • trigger
  • indicator
  • content

accordion_trigger(assigns)

Renders the accordion trigger button. Includes optional :indicator slot.

Attributes

  • item (:map) (required)

Slots

  • inner_block (required)
  • indicator

API

set_value(accordion_id, value)

Sets the accordion value from client-side. Returns a Phoenix.LiveView.JS command.

Examples

<button phx-click={Corex.Accordion.set_value("my-accordion", ["item-1"])}>
  Open Item 1
</button>

set_value(socket, accordion_id, value)

Sets the accordion value from server-side. Pushes a LiveView event.

Examples

def handle_event("open_item", _params, socket) do
  socket = Corex.Accordion.set_value(socket, "my-accordion", ["item-1"])
  {:noreply, socket}
end