A vertically stacked set of interactive headings that each reveal an associated section of content.
<Accordion.root
id="accordion-primitive"
type="single"
default_value="item-1"
collapsible={true}
class="DemoAccordionRoot"
>
<Accordion.item
id="accordion-primitive-1-root"
value="item-1"
class="DemoAccordionItem"
>
<Accordion.header class="DemoAccordionHeader">
<Accordion.trigger
id="accordion-primitive-1-content"
trigger_id="accordion-primitive-1-trigger"
class="DemoAccordionTrigger"
>
Is it accessible?
<svg
class="DemoAccordionChevron"
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
aria-hidden="true"
>
<path
d="M3.135 6.158a.5.5 0 0 1 .707-.023L7.5 9.565l3.658-3.43a.5.5 0 0 1 .684.73l-4 3.75a.5.5 0 0 1-.684 0l-4-3.75a.5.5 0 0 1-.023-.707Z"
fill="currentColor"
/>
</svg>
</Accordion.trigger>
</Accordion.header>
<Accordion.content
id="accordion-primitive-1-content"
trigger_id="accordion-primitive-1-trigger"
class="DemoAccordionContent"
>
<div class="DemoAccordionContentText">Yes. It adheres to the WAI-ARIA design pattern.</div>
</Accordion.content>
</Accordion.item>
<Accordion.item
id="accordion-primitive-2-root"
value="item-2"
class="DemoAccordionItem"
>
<Accordion.header class="DemoAccordionHeader">
<Accordion.trigger
id="accordion-primitive-2-content"
trigger_id="accordion-primitive-2-trigger"
class="DemoAccordionTrigger"
>
Is it unstyled?
<svg
class="DemoAccordionChevron"
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
aria-hidden="true"
>
<path
d="M3.135 6.158a.5.5 0 0 1 .707-.023L7.5 9.565l3.658-3.43a.5.5 0 0 1 .684.73l-4 3.75a.5.5 0 0 1-.684 0l-4-3.75a.5.5 0 0 1-.023-.707Z"
fill="currentColor"
/>
</svg>
</Accordion.trigger>
</Accordion.header>
<Accordion.content
id="accordion-primitive-2-content"
trigger_id="accordion-primitive-2-trigger"
class="DemoAccordionContent"
>
<div class="DemoAccordionContentText">
Yes. It's unstyled by default, giving you freedom over the look and feel.
</div>
</Accordion.content>
</Accordion.item>
<Accordion.item
id="accordion-primitive-3-root"
value="item-3"
class="DemoAccordionItem"
>
<Accordion.header class="DemoAccordionHeader">
<Accordion.trigger
id="accordion-primitive-3-content"
trigger_id="accordion-primitive-3-trigger"
class="DemoAccordionTrigger"
>
Can it be animated?
<svg
class="DemoAccordionChevron"
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
aria-hidden="true"
>
<path
d="M3.135 6.158a.5.5 0 0 1 .707-.023L7.5 9.565l3.658-3.43a.5.5 0 0 1 .684.73l-4 3.75a.5.5 0 0 1-.684 0l-4-3.75a.5.5 0 0 1-.023-.707Z"
fill="currentColor"
/>
</svg>
</Accordion.trigger>
</Accordion.header>
<Accordion.content
id="accordion-primitive-3-content"
trigger_id="accordion-primitive-3-trigger"
class="DemoAccordionContent"
>
<div class="DemoAccordionContentText">
Yes! You can animate the Accordion with CSS or JavaScript.
</div>
</Accordion.content>
</Accordion.item>
</Accordion.root>
/* reset */
button,
h3 {
all: unset;
}
.DemoAccordionRoot {
border-radius: 6px;
width: 300px;
background-color: var(--mauve-6);
box-shadow: 0 2px 10px var(--black-a4);
}
.DemoAccordionItem {
overflow: hidden;
margin-top: 1px;
}
.DemoAccordionItem:first-child {
margin-top: 0;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.DemoAccordionItem:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.DemoAccordionItem:focus-within {
position: relative;
z-index: 1;
box-shadow: 0 0 0 2px var(--mauve-12);
}
.DemoAccordionHeader {
display: flex;
}
.DemoAccordionTrigger {
font-family: inherit;
background-color: transparent;
padding: 0 20px;
height: 45px;
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 15px;
line-height: 1;
color: var(--violet-11);
box-shadow: 0 1px 0 var(--mauve-6);
background-color: white;
}
.DemoAccordionTrigger:hover {
background-color: var(--mauve-2);
}
.DemoAccordionContent {
overflow: hidden;
font-size: 15px;
color: var(--mauve-11);
background-color: var(--mauve-2);
}
.DemoAccordionContent[data-state="open"] {
animation: slideDown 300ms cubic-bezier(0.87, 0, 0.13, 1);
}
.DemoAccordionContent[data-state="closed"] {
animation: slideUp 300ms cubic-bezier(0.87, 0, 0.13, 1);
}
.DemoAccordionContentText {
padding: 15px 20px;
}
.DemoAccordionChevron {
color: var(--violet-10);
transition: transform 300ms cubic-bezier(0.87, 0, 0.13, 1);
}
.DemoAccordionTrigger[data-state="open"] > .DemoAccordionChevron {
transform: rotate(180deg);
}
@keyframes slideDown {
from {
height: 0;
}
to {
height: var(--radix-accordion-content-height);
}
}
@keyframes slideUp {
from {
height: var(--radix-accordion-content-height);
}
to {
height: 0;
}
}
Anatomy
Import all parts and piece them together.
<Accordion.root>
<Accordion.item>
<Accordion.header>
<Accordion.trigger />
</Accordion.header>
<Accordion.content />
</Accordion.item>
</Accordion.root>
Anatomy
-
Root - Contains all the parts of an accordion.
-
Item - Contains all the parts of a collapsible section.
-
Header - Wraps an `Accordion.trigger`. Renders as an `h3` by default.
-
Trigger - Toggles the collapsed state of its associated item. It should be nested inside of an `Accordion.header`.
-
Content - Contains the collapsible content for an item.
API Reference
Root
Contains all the parts of an accordion.
Use value with on_value_change for controlled open state in LiveView:
<Accordion.root id="faq" type="single" value={@value} on_value_change="accordion_value_change">
…
</Accordion.root>
def handle_event("accordion_value_change", %{"value" => value}, socket) do
{:noreply, assign(socket, :value, value)}
end
| Prop | Type | Default | Description |
|---|---|---|---|
collapsible
|
boolean
|
false
|
|
default_value
|
any
|
nil
|
|
dir
|
string
|
"ltr"
|
|
disabled
|
boolean
|
false
|
|
id
|
string
|
—
|
|
on_value_change
|
string
|
nil
|
|
orientation
|
string
|
"vertical"
|
|
type
|
string
|
"single"
|
|
value
|
any
|
nil
|
collapsible
boolean
Default
false
default_value
any
Default
nil
dir
string
Default
"ltr"
disabled
boolean
Default
false
id
string
Default
—
on_value_change
string
Default
nil
orientation
string
Default
"vertical"
type
string
Default
"single"
value
any
Default
nil
Data attributes
| Attribute | Values | Description |
|---|---|---|
[data-orientation]
|
vertical | horizontal
|
The orientation of the accordion. |
Item
Contains all the parts of a collapsible section.
| Prop | Type | Default | Description |
|---|---|---|---|
disabled
|
boolean
|
false
|
|
id
|
string
|
—
|
|
open
|
boolean
|
false
|
|
value
|
string
|
—
|
disabled
boolean
Default
false
id
string
Default
—
open
boolean
Default
false
value
string
Default
—
Data attributes
| Attribute | Values | Description |
|---|---|---|
[data-state]
|
open | closed
|
Reflects whether the item is open. |
[data-disabled]
|
Present when disabled
|
Present when the item is disabled. |
[data-orientation]
|
vertical | horizontal
|
The orientation of the accordion. |
Header
Wraps an Accordion.trigger.
| Prop | Type | Default | Description |
|---|
Data attributes
| Attribute | Values | Description |
|---|---|---|
[data-state]
|
open | closed
|
Reflects whether the item is open. |
[data-disabled]
|
Present when disabled
|
Present when the item is disabled. |
[data-orientation]
|
vertical | horizontal
|
The orientation of the accordion. |
Trigger
Toggles the collapsed state of its associated item. It should be nested inside of an Accordion.header.
| Prop | Type | Default | Description |
|---|---|---|---|
id
|
string
|
—
|
The ID of the content the trigger controls |
trigger_id
|
string
|
—
|
The ID of the trigger element |
id
The ID of the content the trigger controls
string
Default
—
trigger_id
The ID of the trigger element
string
Default
—
Data attributes
| Attribute | Values | Description |
|---|---|---|
[data-state]
|
open | closed
|
Reflects whether the item is open. |
[data-disabled]
|
Present when disabled
|
Present when the item is disabled. |
[data-orientation]
|
vertical | horizontal
|
The orientation of the accordion. |
Content
Contains the collapsible content for an item.
| Prop | Type | Default | Description |
|---|---|---|---|
id
|
string
|
—
|
|
trigger_id
|
string
|
—
|
id
string
Default
—
trigger_id
string
Default
—
Data attributes
| Attribute | Values | Description |
|---|---|---|
[data-state]
|
open | closed
|
Reflects whether the item is open. |
[data-disabled]
|
Present when disabled
|
Present when the item is disabled. |
[data-orientation]
|
vertical | horizontal
|
The orientation of the accordion. |
Essence exposes CSS variables on content for size animations:
| CSS variable | Description |
| --- | --- |
| --radix-accordion-content-width | The width of the content when it opens/closes |
| --radix-accordion-content-height | The height of the content when it opens/closes |
Examples
Expanded by default
Use the default_value prop to define the open item by default.
<Accordion.root id="accordion-default" type="single" default_value="item-2">
<Accordion.item id="accordion-default-1" value="item-1">…</Accordion.item>
<Accordion.item id="accordion-default-2" value="item-2">…</Accordion.item>
</Accordion.root>
Allow collapsing all items
Use the collapsible prop to allow all items to close.
<Accordion.root id="accordion-collapsible" type="single" collapsible={true}>
<Accordion.item id="accordion-collapsible-1" value="item-1">…</Accordion.item>
<Accordion.item id="accordion-collapsible-2" 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 id="accordion-multiple" type="multiple">
<Accordion.item id="accordion-multiple-1" value="item-1">…</Accordion.item>
<Accordion.item id="accordion-multiple-2" value="item-2">…</Accordion.item>
</Accordion.root>
Rotated icon when open
You can add extra decorative elements, such as chevrons, and rotate them when the item is open.
<Accordion.trigger id="item-1-content" trigger_id="item-1-trigger" class="DemoAccordionTrigger">
<span>Trigger text</span>
<svg class="DemoAccordionChevron" width="15" height="15" viewBox="0 0 15 15" fill="none" aria-hidden="true">
<path d="M3.135 6.158a.5.5 0 0 1 .707-.023L7.5 9.565l3.658-3.43a.5.5 0 0 1 .684.73l-4 3.75a.5.5 0 0 1-.684 0l-4-3.75a.5.5 0 0 1-.023-.707Z" fill="currentColor"/>
</svg>
</Accordion.trigger>
.DemoAccordionChevron {
transition: transform 300ms;
}
.DemoAccordionTrigger[data-state="open"] > .DemoAccordionChevron {
transform: rotate(180deg);
}
Horizontal orientation
Use the orientation prop to create a horizontal accordion.
<Accordion.root id="accordion-horizontal" orientation="horizontal">
<Accordion.item id="accordion-horizontal-1" value="item-1">…</Accordion.item>
<Accordion.item id="accordion-horizontal-2" 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:
<Accordion.content id="item-1-content" trigger_id="item-1-trigger" class="DemoAccordionContent">
…
</Accordion.content>
.DemoAccordionContent {
overflow: hidden;
}
.DemoAccordionContent[data-state="open"] {
animation: slideDown 300ms ease-out;
}
.DemoAccordionContent[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
Keyboard Interactions
| Key | Description |
|---|---|
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`. |