Kobalte.v0.12.5

Accordion

A vertically stacked set of interactive headings that each reveal an associated section of content.

Import

ts
import { Accordion } from "@kobalte/core";
ts
import { Accordion } from "@kobalte/core";

Features

  • Follow the WAI ARIA Accordion design pattern.
  • Full keyboard navigation.
  • Can expand one or multiple items.
  • Can be controlled or uncontrolled.

Anatomy

The accordion consists of:

  • Accordion.Root: The root container for an accordion.
  • Accordion.Item: An item of the accordion, contains all the parts of a collapsible section.
  • Accordion.Header: Wraps an Accordion.Trigger. Use the as prop to update it to the appropriate heading level for your page.
  • Accordion.Trigger: Toggles the collapsed state of its associated item. It should be nested inside an Accordion.Header.
  • Accordion.Content: Contains the content to be rendered when the Accordion.Item is expanded.
tsx
<Accordion.Root>
<Accordion.Item>
<Accordion.Header>
<Accordion.Trigger />
</Accordion.Header>
<Accordion.Content />
</Accordion.Item>
</Accordion.Root>
tsx
<Accordion.Root>
<Accordion.Item>
<Accordion.Header>
<Accordion.Trigger />
</Accordion.Header>
<Accordion.Content />
</Accordion.Item>
</Accordion.Root>

Example

Yes. It adheres to the WAI-ARIA design pattern.

Usage

Default value

A default expanded item can be provided using the defaultValue prop, which should correspond to the value prop provided to each accordion item.

Yes. It's unstyled by default, giving you freedom over the look and feel.

tsx
<Accordion.Root defaultValue={["item-2"]}>
<Accordion.Item value="item-1">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-2">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-3">{/* ... */}</Accordion.Item>
</Accordion.Root>
tsx
<Accordion.Root defaultValue={["item-2"]}>
<Accordion.Item value="item-1">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-2">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-3">{/* ... */}</Accordion.Item>
</Accordion.Root>
The value and defaultValue props always take a string[].

Controlled value

Expanded item can be controlled using the value prop, paired with the onChange event. The value prop from the accordion item will be passed into the callback when the item is expanded, allowing you to update state accordingly.

Yes. It's unstyled by default, giving you freedom over the look and feel.

Expanded item: item-2

tsx
import { createSignal } from "solid-js";
function ControlledExample() {
const [expandedItem, setExpandedItem] = createSignal(["item-2"]);
return (
<>
<Accordion.Root value={expandedItem()} onChange={setExpandedItem}>
<Accordion.Item value="item-1">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-2">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-3">{/* ... */}</Accordion.Item>
</Accordion.Root>
<p>Expanded item: {expandedItem().join(",")}</p>
</>
);
}
tsx
import { createSignal } from "solid-js";
function ControlledExample() {
const [expandedItem, setExpandedItem] = createSignal(["item-2"]);
return (
<>
<Accordion.Root value={expandedItem()} onChange={setExpandedItem}>
<Accordion.Item value="item-1">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-2">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-3">{/* ... */}</Accordion.Item>
</Accordion.Root>
<p>Expanded item: {expandedItem().join(",")}</p>
</>
);
}

Collapsible item

By default, accordion items are not collapsible, meaning you can't toggle them from open to close and vice-versa. Use the collapsible prop to enable this behavior.

tsx
<Accordion.Root collapsible>
<Accordion.Item value="item-1">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-2">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-3">{/* ... */}</Accordion.Item>
</Accordion.Root>
tsx
<Accordion.Root collapsible>
<Accordion.Item value="item-1">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-2">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-3">{/* ... */}</Accordion.Item>
</Accordion.Root>

Allow expanding multiple items

Use the multiple to allow expanding multiple accordion items at the same time. This also make all accordion items collapsible.

tsx
<Accordion.Root multiple>
<Accordion.Item value="item-1">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-2">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-3">{/* ... */}</Accordion.Item>
</Accordion.Root>
tsx
<Accordion.Root multiple>
<Accordion.Item value="item-1">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-2">{/* ... */}</Accordion.Item>
<Accordion.Item value="item-3">{/* ... */}</Accordion.Item>
</Accordion.Root>

Animating content size

We expose the CSS custom properties --kb-accordion-content-width and --kb-accordion-content-height which you can use to animate the size of the content when it opens/closes.

css
/* style.css */
.accordion__item-content {
overflow: hidden;
font-size: 16px;
animation: slideUp 300ms cubic-bezier(0.87, 0, 0.13, 1);
}
.accordion__item-content[data-expanded] {
animation: slideDown 300ms cubic-bezier(0.87, 0, 0.13, 1);
}
@keyframes slideDown {
from {
height: 0;
}
to {
height: var(--kb-accordion-content-height);
}
}
@keyframes slideUp {
from {
height: var(--kb-accordion-content-height);
}
to {
height: 0;
}
}
css
/* style.css */
.accordion__item-content {
overflow: hidden;
font-size: 16px;
animation: slideUp 300ms cubic-bezier(0.87, 0, 0.13, 1);
}
.accordion__item-content[data-expanded] {
animation: slideDown 300ms cubic-bezier(0.87, 0, 0.13, 1);
}
@keyframes slideDown {
from {
height: 0;
}
to {
height: var(--kb-accordion-content-height);
}
}
@keyframes slideUp {
from {
height: var(--kb-accordion-content-height);
}
to {
height: 0;
}
}

API Reference

Accordion.Root

PropDescription
valuestring[]
The controlled value of the accordion item(s) to expand.
defaultValuestring[]
The value of the accordion item(s) to expand when initially rendered. Useful when you do not need to control the state.
onChange(value: string[]) => void
Event handler called when the value changes.
multipleboolean
Whether multiple items can be opened at the same time.
collapsibleboolean
When multiple is false, allows closing content when clicking trigger for an open item.
shouldFocusWrapboolean
Whether focus should wrap around when the end/start is reached.

Accordion.Item

Accordion.Item consists of Collapsible.Root.

PropDescription
valuestring
A unique value for the item.
disabledboolean
Whether the item is disabled.
forceMountboolean
Used to force mounting the item content when more control is needed. Useful when controlling animation with SolidJS animation libraries.
Data attributeDescription
data-expandedPresent when the accordion item is expanded.
data-closedPresent when the accordion item is collapsed.
data-disabledPresent when the accordion item is disabled.

Accordion.Header, Accordion.Trigger and Accordion.Content share the same data-attributes.

Accordion.Trigger

Accordion.Trigger consists of Collapsible.Trigger.

Accordion.Content

Accordion.Content consists of Collapsible.Content.

Rendered elements

ComponentDefault rendered element
Accordion.Rootdiv
Accordion.Itemdiv
Accordion.Headerh3
Accordion.Triggerbutton
Accordion.Contentdiv

Accessibility

Keyboard Interactions

KeyDescription
SpaceWhen focus is on an Accordion.Trigger of a collapsed section, expands the section.
EnterWhen focus is on an Accordion.Trigger of a collapsed section, expands the section.
TabMoves focus to the next focusable element.
Shift + TabMoves focus to the previous focusable element.
ArrowDownMoves focus to the next Accordion.Trigger.
ArrowUpMoves focus to the previous Accordion.Trigger.
HomeWhen focus is on an Accordion.Trigger, moves focus to the first Accordion.Trigger.
EndWhen focus is on an Accordion.Trigger, moves focus to the last Accordion.Trigger.