Native Solid 2 fork. Original documentation and designs © WorkOS; historical posts retain their original context.

Accordion

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

Download runnable sandbox
import { omit, type ComponentProps } from "solid-js";
import { Accordion } from "@radix-solid/primitives";
import { ChevronDownIcon } from "@radix-solid/icons";
import styles from "./styles.module.css";
const AccordionDemo = () => <Accordion.Root class={styles.Root} type="single" defaultValue="item-1" collapsible>
<Accordion.Item class={styles.Item} value="item-1">
<AccordionTrigger>Is it accessible?</AccordionTrigger>
<AccordionContent>
Yes. It adheres to the WAI-ARIA design pattern.
</AccordionContent>
</Accordion.Item>
<Accordion.Item class={styles.Item} value="item-2">
<AccordionTrigger>Is it unstyled?</AccordionTrigger>
<AccordionContent>
Yes. It&apos;s unstyled by default, giving you freedom over the look and
feel.
</AccordionContent>
</Accordion.Item>
<Accordion.Item class={styles.Item} value="item-3">
<AccordionTrigger>Can it be animated?</AccordionTrigger>
<AccordionContent>
Yes! You can animate the Accordion with CSS or JavaScript.
</AccordionContent>
</Accordion.Item>
</Accordion.Root>;
const AccordionTrigger = function AccordionTrigger(p: Extract<ComponentProps<typeof Accordion.Trigger>, {
asChild?: false;
}>) {
return <Accordion.Header class={styles.Header}>
<Accordion.Trigger class={[styles.Trigger, p.class]} {...omit(p, "children", "class")} ref={p.ref}>
{p.children}
<ChevronDownIcon class={styles.Chevron} aria-hidden="true" />
</Accordion.Trigger>
</Accordion.Header>;
};
const AccordionContent = function AccordionContent(p: Extract<ComponentProps<typeof Accordion.Content>, {
asChild?: false;
}>) {
return <Accordion.Content class={[styles.Content, p.class]} {...omit(p, "children", "class")} ref={p.ref}>
<div class={styles.ContentText}>{p.children}</div>
</Accordion.Content>;
};
export default AccordionDemo;

Features

  • Full keyboard navigation.

  • Supports horizontal/vertical orientation.

  • Supports Right to Left direction.

  • Can expand one or multiple items.

  • Can be controlled or uncontrolled.

Anatomy

Import all parts and piece them together.

import { Accordion } from "@radix-solid/primitives";
export default () => <Accordion.Root type="single">
<Accordion.Item value="item-1">
<Accordion.Header>
<Accordion.Trigger />
</Accordion.Header>
<Accordion.Content />
</Accordion.Item>
</Accordion.Root>;

API Reference

Root

Contains all the parts of an accordion.

PropTypeDefault
asChildbooleanfalse
type*enum—
valuestring—
defaultValuestring—
onValueChangefunction—
valuestring[][]
defaultValuestring[][]
onValueChangefunction—
collapsiblebooleanfalse
disabledbooleanfalse
direnum"ltr"
orientationenum"vertical"
Data attributeValues
[data-orientation]"vertical" | "horizontal"

Item

Contains all the parts of a collapsible section.

PropTypeDefault
asChildbooleanfalse
disabledbooleanfalse
value*string—
Data attributeValues
[data-state]"open" | "closed"
[data-disabled]

Present when disabled

[data-orientation]"vertical" | "horizontal"

Wraps an Accordion.Trigger. Use the asChild prop to update it to the appropriate heading level for your page.

PropTypeDefault
asChildbooleanfalse
Data attributeValues
[data-state]"open" | "closed"
[data-disabled]

Present when disabled

[data-orientation]"vertical" | "horizontal"

Trigger

Toggles the collapsed state of its associated item. It should be nested inside of an Accordion.Header.

PropTypeDefault
asChildbooleanfalse
Data attributeValues
[data-state]"open" | "closed"
[data-disabled]

Present when disabled

[data-orientation]"vertical" | "horizontal"

Content

Contains the collapsible content for an item.

PropTypeDefault
asChildbooleanfalse
forceMountboolean—
Data attributeValues
[data-state]"open" | "closed"
[data-disabled]

Present when disabled

[data-orientation]"vertical" | "horizontal"
CSS VariableDescription
--radix-accordion-content-widthThe width of the content when it opens/closes
--radix-accordion-content-heightThe height of the content when it opens/closes

Examples

Expanded by default

Use the defaultValue prop to define the open item by default.

<Accordion.Root type="single" defaultValue="item-2">
<Accordion.Item value="item-1">…</Accordion.Item>
<Accordion.Item value="item-2">…</Accordion.Item>
</Accordion.Root>

Allow collapsing all items

Use the collapsible prop to allow all items to close.

<Accordion.Root type="single" collapsible>
<Accordion.Item value="item-1">…</Accordion.Item>
<Accordion.Item value="item-2">…</Accordion.Item>
</Accordion.Root>

Multiple items open at the same time

Set the type prop to multiple to enable opening multiple items at once.

<Accordion.Root type="multiple">
<Accordion.Item value="item-1">…</Accordion.Item>
<Accordion.Item value="item-2">…</Accordion.Item>
</Accordion.Root>

Rotated icon when open

You can add extra decorative elements, such as chevrons, and rotate it when the item is open.

// index.tsx
import { Accordion } from "@radix-solid/primitives";
import { ChevronDownIcon } from "@radix-solid/icons";
import "./styles.css";
export default () => <Accordion.Root type="single">
<Accordion.Item value="item-1">
<Accordion.Header>
<Accordion.Trigger class="AccordionTrigger">
<span>Trigger text</span>
<ChevronDownIcon class="AccordionChevron" aria-hidden="true" />
</Accordion.Trigger>
</Accordion.Header>
<Accordion.Content>…</Accordion.Content>
</Accordion.Item>
</Accordion.Root>;
/* styles.css */
.AccordionChevron {
transition: transform 300ms;
}
.AccordionTrigger[data-state="open"] > .AccordionChevron {
transform: rotate(180deg);
}

Horizontal orientation

Use the orientation prop to create a horizontal accordion.

<Accordion.Root type="single" orientation="horizontal">
<Accordion.Item value="item-1">…</Accordion.Item>
<Accordion.Item value="item-2">…</Accordion.Item>
</Accordion.Root>

Animating content size

Use the --radix-accordion-content-width and/or --radix-accordion-content-height CSS variables to animate the size of the content when it opens/closes:

// index.tsx
import { Accordion } from "@radix-solid/primitives";
import "./styles.css";
export default () => <Accordion.Root type="single">
<Accordion.Item value="item-1">
<Accordion.Header>…</Accordion.Header>
<Accordion.Content class="AccordionContent">…</Accordion.Content>
</Accordion.Item>
</Accordion.Root>;
/* styles.css */
.AccordionContent {
overflow: hidden;
}
.AccordionContent[data-state="open"] {
animation: slideDown 300ms ease-out;
}
.AccordionContent[data-state="closed"] {
animation: slideUp 300ms ease-out;
}
@keyframes slideDown {
from {
height: 0;
}
to {
height: var(--radix-accordion-content-height);
}
}
@keyframes slideUp {
from {
height: var(--radix-accordion-content-height);
}
to {
height: 0;
}
}

Accessibility

Adheres to the Accordion WAI-ARIA design pattern.

Keyboard Interactions

KeyDescription
Space
When focus is on an Accordion.Trigger of a collapsed section, expands the section.
Enter
When focus is on an Accordion.Trigger of a collapsed section, expands the section.
Tab
Moves focus to the next focusable element.
Shift + Tab
Moves focus to the previous focusable element.
ArrowDown
Moves focus to the next Accordion.Trigger when orientation is vertical.
ArrowUp
Moves focus to the previous Accordion.Trigger when orientation is vertical.
ArrowRight
Moves focus to the next Accordion.Trigger when orientation is horizontal.
ArrowLeft
Moves focus to the previous Accordion.Trigger when orientation is horizontal.
Home
When focus is on an Accordion.Trigger, moves focus to the first Accordion.Trigger.
End
When focus is on an Accordion.Trigger, moves focus to the last Accordion.Trigger.