A vertically stacked set of collapsible sections, built purely on client-side JS commands and CSS — no LiveView hook and no server round-trip.
Each trigger's phx-click flips a data-state of "open"/"closed" (and the
matching aria-expanded) on both itself and its paired content panel. The
panel animates open/closed in pure CSS using the grid-template-rows
0fr → 1fr technique: the content lives inside a grid whose single row
transitions between 0fr (collapsed) and 1fr (expanded), with the inner
wrapper clipping overflow. This animates the panel's height smoothly without
anyone having to measure it, and degrades to an instant toggle under
prefers-reduced-motion.
Because the collapsed panel stays in the DOM (so it can animate) rather than
being display:none, it carries inert while closed to keep it out of the
tab order and the accessibility tree; the same phx-click toggles inert.
The trigger's data-state also drives the chevron rotation via the
[&[data-state=open]>svg]:rotate-180 utility lifted from shadcn.
Ids wire the pieces together: accordion_item/1 takes a unique :id,
accordion_trigger/1 and accordion_content/1 take that same id and derive
"#{id}-trigger" / "#{id}-content" so aria-controls and the toggle target
line up stably.
NOTE: type="single" auto-closing of sibling items is simplified — items
behave as independent toggles in this v1, so type is currently advisory and
rendered as a data-type hint on the root.
Summary
Functions
Renders the accordion root, a vertical stack of accordion_item/1s.
The collapsible body of an item. :id is the item id.
A single accordion item; wraps a trigger and its content.
The clickable header of an item. :id is the item id.
Functions
Renders the accordion root, a vertical stack of accordion_item/1s.
:type is advisory in this v1 (see moduledoc): both "single" and
"multiple" render independent toggles and the value is exposed as
data-type for styling/JS hooks.
Attributes
type(:string) - Defaults to"single". Must be one of"single", or"multiple".class(:string) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
The collapsible body of an item. :id is the item id.
Renders <div id="#{id}-content" role="region">, collapsed (data-state="closed"
and inert) by default. The panel animates open/closed in pure CSS via the
grid-template-rows 0fr → 1fr trick keyed off data-state; the inner
overflow-hidden wrapper clips the content as the row collapses. Under
prefers-reduced-motion the transition is dropped and it toggles instantly.
Attributes
id(:string) (required)class(:string) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
A single accordion item; wraps a trigger and its content.
:id must be unique per item and is reused by accordion_trigger/1 and
accordion_content/1 to wire aria-controls and the toggle target.
Attributes
id(:string) (required)class(:string) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
The clickable header of an item. :id is the item id.
Renders a <button id="#{id}-trigger"> with aria-controls="#{id}-content",
aria-expanded and a data-state that toggle on click, plus a chevron SVG
that rotates when data-state="open". The same phx-click flips the paired
content panel's data-state (which drives the CSS open/close animation) and
its inert attribute.
Attributes
id(:string) (required)class(:string) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)