Accordion
A stack of collapsible sections, one or many open at a time, driven by pointer or keyboard.
Live demo
Accordion stacks a set of disclosure sections that expand and collapse. Each section pairs a [slot="header"] header with the [slot="panel"] that follows it; the component wraps every header in a heading and a role="button" trigger carrying aria-expanded and aria-controls, and turns each panel into a labelled role="region" that hides when collapsed.
By default it is single-open: opening one section closes the rest. multiple lets several stay open at once. Mark a header open to expand its section initially, or disabled to lock it. The heading level is h3 by default and settable with headingLevel, and three sizes (sm, md, lg) scale the trigger density. A chevron rotates with the open state, and pointer, Enter/Space, and the arrow/Home/End keys all drive it.
When to use
How this component composes with the rest of the set.
Props
3 props, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
Appearance
Sizes
sm
Compact triggers.
md
Default.
lg
Roomy triggers.
States
open
An expanded section: the trigger reads aria-expanded="true" and the chevron rotates.
trigger-hover
Pointer over a header: the hover tint paints behind it.
trigger-focus-visible
Keyboard focus on a header: an inset token ring plus the transparent outline promoted in forced-colors mode.
disabled
A locked header: muted and non-interactive.
Anatomy
The named parts that make up the component, with their selectors.
accordion
The bordered container stacking the sections, with hairlines between them.
trigger
The full-width header button that toggles its section; carries aria-expanded and the hover/press overlay.
chevron
The disclosure caret in the trigger corner; rotates 180° when the section is open.
panel
The collapsible role="region" holding the section content; hidden when collapsed.
Tokens & coverage
What the component consumes, checked live against what the algorithm produces.
Live coverage check against the xoji-default register
(derive(xojiDefault, { anchors }) →
coverComponent(manifest, register)). Every token this component
consumes must be a key the algorithm produces.
--bg-1
--border-normal
--border-thick
--border-thin
--duration-fast
--ease-standard
--fg-0
--fg-1
--fg-2
--fg-disabled
--font-sans
--leading-normal
--leading-tight
--line
--radius-md
--ring
--space-1
--space-2
--space-3
--space-4
--space-5
--state-hover
--state-press
--text-body
--text-lg
--text-sm
--weight-medium
Slots
Each section's header label, marked slot="header"; add open to expand it initially or disabled to lock it.
Each section's collapsible content, marked slot="panel", paired to the header before it by order.
Accessibility
Code
Single-open FAQ
Three sections where opening one collapses the others; the second starts open.
<xoji-accordion>
<span slot="header">Shipping</span>
<div slot="panel">Orders ship within two business days.</div>
<span slot="header" open>Returns</span>
<div slot="panel">Unworn items are accepted within 30 days.</div>
<span slot="header">Warranty</span>
<div slot="panel">Covered against defects for one year.</div>
</xoji-accordion>
<script lang="ts">
import { Accordion } from "@xoji/svelte";
</script>
<Accordion>
<span slot="header">Shipping</span>
<div slot="panel">Orders ship within two business days.</div>
<span slot="header" open>Returns</span>
<div slot="panel">Unworn items are accepted within 30 days.</div>
</Accordion>
---
import { Accordion } from "@xoji/astro";
---
<Accordion multiple>
<span slot="header">Shipping</span>
<div slot="panel">Orders ship within two business days.</div>
<span slot="header" open>Returns</span>
<div slot="panel">Unworn items are accepted within 30 days.</div>
</Accordion>
Multiple open, with a disabled section
A compact accordion that lets several panels stay open, with one locked header.
<xoji-accordion multiple size="sm">
<span slot="header" open>Filters</span>
<div slot="panel">In stock, on sale, free shipping.</div>
<span slot="header" open>Sort</span>
<div slot="panel">Price, rating, newest.</div>
<span slot="header" disabled>Saved searches</span>
<div slot="panel">Sign in to save a search.</div>
</xoji-accordion>
<script lang="ts">
import { Accordion } from "@xoji/svelte";
</script>
<Accordion>
<span slot="header">Shipping</span>
<div slot="panel">Orders ship within two business days.</div>
<span slot="header" open>Returns</span>
<div slot="panel">Unworn items are accepted within 30 days.</div>
</Accordion>
---
import { Accordion } from "@xoji/astro";
---
<Accordion multiple>
<span slot="header">Shipping</span>
<div slot="panel">Orders ship within two business days.</div>
<span slot="header" open>Returns</span>
<div slot="panel">Unworn items are accepted within 30 days.</div>
</Accordion>