Skip to content
Home Theme Gallery

Accordion

The custom element is <hui-accordion>.

Overview

A disclosure list with one shared keyboard behaviour. A collapsible single-item accordion is shadcn's Collapsible, so there is no separate component.

Example

Accordion
Source
<hui-accordion type="single" value="a" collapsible>
<div data-value="a">
<button data-trigger class="hui-accordion__trigger">Section A</button>
<div data-panel class="hui-accordion__panel">Content A</div>
</div>
<div data-value="b">
<button data-trigger class="hui-accordion__trigger">Section B</button>
<div data-panel class="hui-accordion__panel">Content B</div>
</div>
</hui-accordion>

The Go template that renders it:

<hui-accordion type="single" value="{{ .Open }}" collapsible>
{{ range .Items }}
<div data-value="{{ .ID }}">
<button data-trigger class="hui-accordion__trigger">{{ .Label }}</button>
<div data-panel class="hui-accordion__panel">{{ .Body }}</div>
</div>
{{ end }}
</hui-accordion>

API

Attributes3
Attributes
NameTypeDefaultDescription
valuestring""The open item data-value, or a comma-separated list when type="multiple". Reflected.
type"single" | "multiple""single"single keeps one item open; multiple toggles items independently.
collapsiblebooleanfalseIn a single accordion, allows the open item to close again — which is shadcn's Collapsible behaviour.
Properties3
Properties
NameTypeDefaultDescription
valuestring''Reflects to the value attribute.
typeAccordionType'single'Reflects to the type attribute.
collapsiblebooleanfalseReflects to the collapsible attribute.
Events3
Events
NameDescription
hui-openAn item was opened. It bubbles and is composed, with detail { value } for the item.
hui-closeAn item was closed. It bubbles and is composed, with detail { value } for the item.
click on [data-trigger]Activating an item's trigger toggles it, subject to type and collapsible.
Slots1
Slots
NameDescription
(default)The items: a wrapper with data-value containing a [data-trigger] control and a [data-panel] body.
CSS custom properties3
CSS custom properties
NameDefaultDescription
--hui-borderoklch(0.922 0.005 325.62)Bottom border on each item.
--hui-font-sans"IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serifInherited type family.
--hui-foregroundoklch(0.145 0.008 326)Inherited text colour.
Classes2
Classes
NameDescription
.hui-accordion__triggerThe trigger inside a slotted hui-accordion item. Styled here because a shadow rule cannot reach it.
.hui-accordion__panelThe panel inside a slotted hui-accordion item.

States

Multiple

type="multiple" lets more than one section stand open at once, and value is the list of open sections.

Multiple
Source
<hui-accordion type="multiple" value="x,y">
<div data-value="x">
<button data-trigger class="hui-accordion__trigger">X</button>
<div data-panel class="hui-accordion__panel">X body</div>
</div>
<div data-value="y">
<button data-trigger class="hui-accordion__trigger">Y</button>
<div data-panel class="hui-accordion__panel">Y body</div>
</div>
</hui-accordion>

Server-side mechanics

The server owns every item: a wrapper with data-value containing a [data-trigger] control and a [data-panel] body, plus value, type and collapsible. Render <hui-accordion type="multiple" value="x,y"> to open several items at once or value="a" for one, and read value back because it reflects; the comma-separated form is only meaningful while type="multiple". It is not form-associated and submits nothing; an item opening or closing emits a bubbling, composed hui-open or hui-close carrying { value }. The trigger and panel are light-DOM descendants of the slotted item, so an hx-swap can replace a panel's body without touching the component's state, and aria-expanded, aria-controls and the generated ids are re-synced. Replacing the whole hui-accordion requires the server to emit value again, since the component persists nothing.

Accessibility

  • Each trigger gets aria-expanded and aria-controls; each panel gets role="region" and aria-labelledby; ids are generated when absent.
  • Closed panels are hidden, and each item carries data-state="open" or "closed".
  • The component invents no item markup: the host renders the wrapper, trigger and panel.

Keyboard

Keyboard
KeysAction
Arrow Up, Arrow DownMove focus between item triggers, wrapping.
Home, EndMove focus to the first or last trigger.
Enter, SpaceActivate the focused trigger, which is a native button, toggling its panel.

Gotchas

  • hui-accordion reports expansion with hui-open and hui-close, the same two names hui-tabs uses for selection; a listener shared between them cannot tell which component fired without checking the event target or detail.