Skip to main content

Accordion

Toggle content sections. Keep layouts clean. Focus user attention.

Want to survive 12-hour coding sessions? Always keep snacks nearby and caffeine on standby. Bonus points for comfy socks and a chair that doesn't destroy your back.

Remember: comments are your friend. Future you will thank past you for writing clear notes.

default.tsx
1'use client';
2
3import { Accordion } from '@/components/ui/accordion';
4
5const accordionItems = [
6 {
7 value: 'item-1',
8 title: 'Life Hacks for Coders',
9 content: (
10 <>
11 <p>
12 Want to survive 12-hour coding sessions? Always keep snacks nearby and caffeine on
13 standby. Bonus points for comfy socks and a chair that doesn't destroy your back.
14 </p>
15 <p>
16 Remember: comments are your friend. Future you will thank past you for writing clear
17 notes.
18 </p>
19 </>
20 ),
21 },
22 {
23 value: 'item-2',
24 title: 'Debugging Secrets',
25 content: (
26 <>
27 <p>
28 Debugging is basically detective work, but your suspects are lines of code. Breakpoints
29 are your magnifying glass.
30 </p>
31 <p>
32 Pro tip: if it compiles but doesn't work, stare at the screen, whisper "why won't you
33 work?," then Google like your life depends on it.
34 </p>
35 </>
36 ),
37 },
38 {
39 value: 'item-3',
40 title: 'Random Productivity Tips',
41 content: (
42 <>
43 <p>
44 Sometimes the best way to get code done is to step away. Take a walk, pet your cat, or
45 pretend to meditate.
46 </p>
47 <p>And remember: Ctrl+S is life. Save often, panic never.</p>
48 </>
49 ),
50 },
51];
52
53export function Default() {
54 return (
55 <Accordion type="single" className="w-full" defaultValue="item-1">
56 {accordionItems.map((item) => (
57 <Accordion.Item key={item.value} value={item.value}>
58 <Accordion.Trigger value={item.value}>{item.title}</Accordion.Trigger>
59 <Accordion.Content value={item.value} className="flex flex-col gap-4 text-balance">
60 {item.content}
61 </Accordion.Content>
62 </Accordion.Item>
63 ))}
64 </Accordion>
65 );
66}

Installation

pnpm dlx nachui add accordion

Anatomy

1import { Accordion } from '@/components/ui/accordion';
1<Accordion type="single" defaultValue="item-1">
2 <Accordion.Item value="item-1">
3 <Accordion.Trigger>Is it accessible?</Accordion.Trigger>
4 <Accordion.Content>Yes. It adheres to the WAI-ARIA design pattern.</Accordion.Content>
5 </Accordion.Item>
6</Accordion>

Variants

Single

The single type allows only one item to be open at a time.

Want to survive 12-hour coding sessions? Always keep snacks nearby and caffeine on standby. Bonus points for comfy socks and a chair that doesn't destroy your back.

Remember: comments are your friend. Future you will thank past you for writing clear notes.

default.tsx
1'use client';
2
3import { Accordion } from '@/components/ui/accordion';
4
5const accordionItems = [
6 {
7 value: 'item-1',
8 title: 'Life Hacks for Coders',
9 content: (
10 <>
11 <p>
12 Want to survive 12-hour coding sessions? Always keep snacks nearby and caffeine on
13 standby. Bonus points for comfy socks and a chair that doesn't destroy your back.
14 </p>
15 <p>
16 Remember: comments are your friend. Future you will thank past you for writing clear
17 notes.
18 </p>
19 </>
20 ),
21 },
22 {
23 value: 'item-2',
24 title: 'Debugging Secrets',
25 content: (
26 <>
27 <p>
28 Debugging is basically detective work, but your suspects are lines of code. Breakpoints
29 are your magnifying glass.
30 </p>
31 <p>
32 Pro tip: if it compiles but doesn't work, stare at the screen, whisper "why won't you
33 work?," then Google like your life depends on it.
34 </p>
35 </>
36 ),
37 },
38 {
39 value: 'item-3',
40 title: 'Random Productivity Tips',
41 content: (
42 <>
43 <p>
44 Sometimes the best way to get code done is to step away. Take a walk, pet your cat, or
45 pretend to meditate.
46 </p>
47 <p>And remember: Ctrl+S is life. Save often, panic never.</p>
48 </>
49 ),
50 },
51];
52
53export function Default() {
54 return (
55 <Accordion type="single" className="w-full" defaultValue="item-1">
56 {accordionItems.map((item) => (
57 <Accordion.Item key={item.value} value={item.value}>
58 <Accordion.Trigger value={item.value}>{item.title}</Accordion.Trigger>
59 <Accordion.Content value={item.value} className="flex flex-col gap-4 text-balance">
60 {item.content}
61 </Accordion.Content>
62 </Accordion.Item>
63 ))}
64 </Accordion>
65 );
66}

Multiple

The multiple type allows multiple items to be open simultaneously.
multiple.tsx
1'use client';
2
3import { Accordion } from '@/components/ui/accordion';
4
5const items = [
6 {
7 value: 'item-1',
8 trigger: 'Can I open multiple items?',
9 content:
10 'Yes! When using type="multiple", you can have multiple accordion items open at the same time.',
11 },
12 {
13 value: 'item-2',
14 trigger: 'How does it work?',
15 content:
16 'Simply set the type prop to "multiple" and users can expand as many sections as they want simultaneously.',
17 },
18 {
19 value: 'item-3',
20 trigger: 'Is this useful?',
21 content:
22 "Absolutely! It's perfect for FAQ sections where users might want to compare multiple answers at once.",
23 },
24];
25
26export function Multiple() {
27 return (
28 <Accordion type="multiple" className="w-full">
29 {items.map((item) => (
30 <Accordion.Item key={item.value} value={item.value}>
31 <Accordion.Trigger value={item.value}>{item.trigger}</Accordion.Trigger>
32 <Accordion.Content value={item.value}>{item.content}</Accordion.Content>
33 </Accordion.Item>
34 ))}
35 </Accordion>
36 );
37}

Without default value

You can omit defaultValue to have the accordion start completely collapsed.
collapsed.tsx
1'use client';
2
3import { Accordion } from '@/components/ui/accordion';
4
5const items = [
6 {
7 value: 'item-1',
8 trigger: 'Will it start closed?',
9 content:
10 "Yes! When you don't provide a defaultValue prop, all items start in a collapsed state.",
11 },
12 {
13 value: 'item-2',
14 trigger: 'Can users still open items?',
15 content:
16 'Of course! Users can click any trigger to expand the content. It just starts fully collapsed.',
17 },
18 {
19 value: 'item-3',
20 trigger: 'When is this useful?',
21 content:
22 'This is great when you want users to actively choose what information they want to see, keeping the interface clean initially.',
23 },
24];
25
26export function Collapsed() {
27 return (
28 <Accordion type="single" className="w-full">
29 {items.map((item) => (
30 <Accordion.Item key={item.value} value={item.value}>
31 <Accordion.Trigger value={item.value}>{item.trigger}</Accordion.Trigger>
32 <Accordion.Content value={item.value}>{item.content}</Accordion.Content>
33 </Accordion.Item>
34 ))}
35 </Accordion>
36 );
37}

API Reference

Accordion

PropTypeDefaultDescription
type"single" | "multiple""single"Controls whether only one item or multiple items can be open at the same time.
defaultValuestringundefinedThe initially opened item.
childrenReact.ReactNodeShould be AccordionItem components.
classNamestringAdditional classes for the wrapper.

Accordion.Item

PropTypeDefaultDescription
valuestringUnique identifier for the item. Required.
childrenReact.ReactNodeShould include AccordionTrigger and AccordionContent.
isOpenbooleanInternalDetermines whether the item is open.
onToggle() => voidInternalFunction to toggle open/closed state.
classNamestringAdditional classes for the wrapper.

Accordion.Trigger

PropTypeDefaultDescription
childrenReact.ReactNodeThe title or content of the button.
isOpenbooleanInternalWhether the item is open (controls icon rotation).
onToggle() => voidInternalClick handler for toggling.
classNamestringAdditional classes for the trigger button.

Accordion.Content

PropTypeDefaultDescription
childrenReact.ReactNodeCollapsible content.
isOpenbooleanInternalControls open state and animations.
classNamestringAdditional classes for the animated content wrapper.
Found something to improve?

Notice a bug, typo, or missing detail on this page? Help us make the documentation better by opening a GitHub issue.

Create an Issue