# Accordion

URL: https://ark-ui.com/docs/components/accordion
LLM: https://ark-ui.com/llms.txt/components/accordion

A collapsible component for displaying content in a vertical stack.

---



## Anatomy



```tsx
<Accordion.Root>
  <Accordion.Item>
    <Accordion.ItemTrigger>
      <Accordion.ItemIndicator />
    </Accordion.ItemTrigger>
    <Accordion.ItemContent />
  </Accordion.Item>
</Accordion.Root>
```

## Examples

### Default Value

Set the `defaultValue` prop to specify which item should be expanded by default.

```tsx
import { Accordion } from '@ark-ui/react/accordion'
import { ChevronDownIcon } from 'lucide-react'
import styles from 'styles/accordion.module.css'

export const Basic = () => {
  return (
    <Accordion.Root className={styles.Root} defaultValue={['ark-ui']}>
      {items.map((item) => (
        <Accordion.Item className={styles.Item} key={item.value} value={item.value}>
          <Accordion.ItemTrigger className={styles.ItemTrigger}>
            {item.title}
            <Accordion.ItemIndicator className={styles.ItemIndicator}>
              <ChevronDownIcon />
            </Accordion.ItemIndicator>
          </Accordion.ItemTrigger>
          <Accordion.ItemContent className={styles.ItemContent}>
            <div className={styles.ItemBody}>{item.content}</div>
          </Accordion.ItemContent>
        </Accordion.Item>
      ))}
    </Accordion.Root>
  )
}

const items = [
  {
    value: 'ark-ui',
    title: 'What is Ark UI?',
    content: 'A headless component library for building accessible web apps.',
  },
  {
    value: 'getting-started',
    title: 'How to get started?',
    content: 'Install the package and import the components you need.',
  },
  {
    value: 'maintainers',
    title: 'Who maintains this project?',
    content: 'Ark UI is maintained by the Chakra UI team.',
  },
]
```

### Controlled

Use the `value` and `onValueChange` props to control the expanded items.

```tsx
import { Accordion } from '@ark-ui/react/accordion'
import { ChevronDownIcon } from 'lucide-react'
import { useState } from 'react'
import styles from 'styles/accordion.module.css'

export const Controlled = () => {
  const [value, setValue] = useState<string[]>([])

  return (
    <Accordion.Root className={styles.Root} value={value} onValueChange={(details) => setValue(details.value)}>
      {items.map((item) => (
        <Accordion.Item className={styles.Item} key={item.value} value={item.value}>
          <Accordion.ItemTrigger className={styles.ItemTrigger}>
            {item.title}
            <Accordion.ItemIndicator className={styles.ItemIndicator}>
              <ChevronDownIcon />
            </Accordion.ItemIndicator>
          </Accordion.ItemTrigger>
          <Accordion.ItemContent className={styles.ItemContent}>
            <div className={styles.ItemBody}>{item.content}</div>
          </Accordion.ItemContent>
        </Accordion.Item>
      ))}
    </Accordion.Root>
  )
}

const items = [
  {
    value: 'ark-ui',
    title: 'What is Ark UI?',
    content: 'A headless component library for building accessible web apps.',
  },
  {
    value: 'getting-started',
    title: 'How to get started?',
    content: 'Install the package and import the components you need.',
  },
  {
    value: 'maintainers',
    title: 'Who maintains this project?',
    content: 'Ark UI is maintained by the Chakra UI team.',
  },
]
```

### Root Provider

An alternative way to control the accordion is to use the `RootProvider` component and the `useAccordion` hook. This way
you can access the state and methods from outside the component.

```tsx
import { Accordion, useAccordion } from '@ark-ui/react/accordion'
import { ChevronDownIcon } from 'lucide-react'
import styles from 'styles/accordion.module.css'

export const RootProvider = () => {
  const accordion = useAccordion({
    multiple: true,
    defaultValue: ['ark-ui'],
  })

  return (
    <div className="stack">
      <output>Value: {JSON.stringify(accordion.value)}</output>

      <Accordion.RootProvider className={styles.Root} value={accordion}>
        {items.map((item) => (
          <Accordion.Item className={styles.Item} key={item.value} value={item.value}>
            <Accordion.ItemTrigger className={styles.ItemTrigger}>
              {item.title}
              <Accordion.ItemIndicator className={styles.ItemIndicator}>
                <ChevronDownIcon />
              </Accordion.ItemIndicator>
            </Accordion.ItemTrigger>
            <Accordion.ItemContent className={styles.ItemContent}>
              <div className={styles.ItemBody}>{item.content}</div>
            </Accordion.ItemContent>
          </Accordion.Item>
        ))}
      </Accordion.RootProvider>
    </div>
  )
}

const items = [
  {
    value: 'ark-ui',
    title: 'What is Ark UI?',
    content: 'A headless component library for building accessible web apps.',
  },
  {
    value: 'getting-started',
    title: 'How to get started?',
    content: 'Install the package and import the components you need.',
  },
  {
    value: 'maintainers',
    title: 'Who maintains this project?',
    content: 'Ark UI is maintained by the Chakra UI team.',
  },
]
```

### Collapsible

Use the `collapsible` prop to allow the user to collapse all panels.

```tsx
import { Accordion } from '@ark-ui/react/accordion'
import { ChevronDownIcon } from 'lucide-react'
import styles from 'styles/accordion.module.css'

export const Collapsible = () => {
  return (
    <Accordion.Root className={styles.Root} defaultValue={['ark-ui']} collapsible>
      {items.map((item) => (
        <Accordion.Item className={styles.Item} key={item.value} value={item.value}>
          <Accordion.ItemTrigger className={styles.ItemTrigger}>
            {item.title}
            <Accordion.ItemIndicator className={styles.ItemIndicator}>
              <ChevronDownIcon />
            </Accordion.ItemIndicator>
          </Accordion.ItemTrigger>
          <Accordion.ItemContent className={styles.ItemContent}>
            <div className={styles.ItemBody}>{item.content}</div>
          </Accordion.ItemContent>
        </Accordion.Item>
      ))}
    </Accordion.Root>
  )
}

const items = [
  {
    value: 'ark-ui',
    title: 'What is Ark UI?',
    content: 'A headless component library for building accessible web apps.',
  },
  {
    value: 'getting-started',
    title: 'How to get started?',
    content: 'Install the package and import the components you need.',
  },
  {
    value: 'maintainers',
    title: 'Who maintains this project?',
    content: 'Ark UI is maintained by the Chakra UI team.',
  },
]
```

### Multiple

Use the `multiple` prop to allow multiple panels to be expanded simultaneously.

```tsx
import { Accordion } from '@ark-ui/react/accordion'
import { ChevronDownIcon } from 'lucide-react'
import styles from 'styles/accordion.module.css'

export const Multiple = () => {
  return (
    <Accordion.Root className={styles.Root} defaultValue={['ark-ui']} multiple>
      {items.map((item) => (
        <Accordion.Item className={styles.Item} key={item.value} value={item.value}>
          <Accordion.ItemTrigger className={styles.ItemTrigger}>
            {item.title}
            <Accordion.ItemIndicator className={styles.ItemIndicator}>
              <ChevronDownIcon />
            </Accordion.ItemIndicator>
          </Accordion.ItemTrigger>
          <Accordion.ItemContent className={styles.ItemContent}>
            <div className={styles.ItemBody}>{item.content}</div>
          </Accordion.ItemContent>
        </Accordion.Item>
      ))}
    </Accordion.Root>
  )
}

const items = [
  {
    value: 'ark-ui',
    title: 'What is Ark UI?',
    content: 'A headless component library for building accessible web apps.',
  },
  {
    value: 'getting-started',
    title: 'How to get started?',
    content: 'Install the package and import the components you need.',
  },
  {
    value: 'maintainers',
    title: 'Who maintains this project?',
    content: 'Ark UI is maintained by the Chakra UI team.',
  },
]
```

### Horizontal

By default, the Accordion is oriented vertically. Use the `orientation` prop to switch to a horizontal layout.

```tsx
import { Accordion } from '@ark-ui/react/accordion'
import styles from 'styles/accordion.module.css'

export const Horizontal = () => {
  return (
    <Accordion.Root className={styles.Root} defaultValue={['ark-ui']} orientation="horizontal">
      {items.map((item) => (
        <Accordion.Item className={styles.Item} key={item.value} value={item.value}>
          <Accordion.ItemTrigger className={styles.ItemTrigger}>{item.title}</Accordion.ItemTrigger>
          <Accordion.ItemContent className={styles.ItemContent}>
            <div className={`${styles.ItemBody} ${styles.Centered}`}>{item.content}</div>
          </Accordion.ItemContent>
        </Accordion.Item>
      ))}
    </Accordion.Root>
  )
}

const items = [
  {
    value: 'ark-ui',
    title: 'What is Ark UI?',
    content: 'A headless component library for building accessible web apps.',
  },
  {
    value: 'getting-started',
    title: 'How to get started?',
    content: 'Install the package and import the components you need.',
  },
  {
    value: 'maintainers',
    title: 'Who maintains this project?',
    content: 'Ark UI is maintained by the Chakra UI team.',
  },
]
```

### Lazy Mount

Use the `lazyMount` prop to defer rendering of accordion content until the item is expanded. Combine with
`unmountOnExit` to unmount content when collapsed, freeing up resources.

```tsx
import { Accordion } from '@ark-ui/react/accordion'
import { ChevronDownIcon } from 'lucide-react'
import styles from 'styles/accordion.module.css'

export const LazyMount = () => {
  return (
    <Accordion.Root className={styles.Root} lazyMount unmountOnExit>
      {items.map((item) => (
        <Accordion.Item className={styles.Item} key={item.value} value={item.value}>
          <Accordion.ItemTrigger className={styles.ItemTrigger}>
            {item.title}
            <Accordion.ItemIndicator className={styles.ItemIndicator}>
              <ChevronDownIcon />
            </Accordion.ItemIndicator>
          </Accordion.ItemTrigger>
          <Accordion.ItemContent className={styles.ItemContent}>
            <div className={styles.ItemBody}>{item.content}</div>
          </Accordion.ItemContent>
        </Accordion.Item>
      ))}
    </Accordion.Root>
  )
}

const items = [
  {
    value: 'ark-ui',
    title: 'What is Ark UI?',
    content: 'A headless component library for building accessible web apps.',
  },
  {
    value: 'getting-started',
    title: 'How to get started?',
    content: 'Install the package and import the components you need.',
  },
  {
    value: 'maintainers',
    title: 'Who maintains this project?',
    content: 'Ark UI is maintained by the Chakra UI team.',
  },
]
```

### Context

Use `Accordion.Context` or `useAccordionContext` to access the accordion state.

```tsx
import { Accordion } from '@ark-ui/react/accordion'
import { ChevronDownIcon } from 'lucide-react'
import styles from 'styles/accordion.module.css'

export const Context = () => {
  return (
    <Accordion.Root className={styles.Root} defaultValue={['ark-ui']}>
      <Accordion.Context>
        {(context) => (
          <output>
            <div>context.value: {JSON.stringify(context.value)}</div>
            <div>context.focusedValue: {context.focusedValue || 'null'}</div>
          </output>
        )}
      </Accordion.Context>

      {items.map((item) => (
        <Accordion.Item className={styles.Item} key={item.value} value={item.value}>
          <Accordion.ItemTrigger className={styles.ItemTrigger}>
            {item.title}
            <Accordion.ItemIndicator className={styles.ItemIndicator}>
              <ChevronDownIcon />
            </Accordion.ItemIndicator>
          </Accordion.ItemTrigger>
          <Accordion.ItemContent className={styles.ItemContent}>
            <div className={styles.ItemBody}>{item.content}</div>
          </Accordion.ItemContent>
        </Accordion.Item>
      ))}
    </Accordion.Root>
  )
}

const items = [
  {
    value: 'ark-ui',
    title: 'What is Ark UI?',
    content: 'A headless component library for building accessible web apps.',
  },
  {
    value: 'getting-started',
    title: 'How to get started?',
    content: 'Install the package and import the components you need.',
  },
  {
    value: 'maintainers',
    title: 'Who maintains this project?',
    content: 'Ark UI is maintained by the Chakra UI team.',
  },
]
```

### Item State

Use `Accordion.ItemContext` or `useAccordionItemContext` to access the state of an accordion item.

```tsx
import { Accordion } from '@ark-ui/react/accordion'
import styles from 'styles/accordion.module.css'

export const ItemContext = () => {
  return (
    <Accordion.Root className={styles.Root} defaultValue={['ark-ui']}>
      {items.map((item) => (
        <Accordion.Item className={styles.Item} key={item.value} value={item.value}>
          <Accordion.ItemTrigger className={styles.ItemTrigger}>
            {item.title}
            <Accordion.ItemContext>
              {(context) => (
                <code style={{ display: 'inline-flex', gap: '0.5rem', fontSize: '0.75rem' }}>
                  {context.expanded && <span>Expanded</span>}
                  {context.focused && <span>Focused</span>}
                </code>
              )}
            </Accordion.ItemContext>
          </Accordion.ItemTrigger>
          <Accordion.ItemContent className={styles.ItemContent}>
            <div className={styles.ItemBody}>{item.content}</div>
          </Accordion.ItemContent>
        </Accordion.Item>
      ))}
    </Accordion.Root>
  )
}

const items = [
  {
    value: 'ark-ui',
    title: 'What is Ark UI?',
    content: 'A headless component library for building accessible web apps.',
  },
  {
    value: 'getting-started',
    title: 'How to get started?',
    content: 'Install the package and import the components you need.',
  },
  {
    value: 'maintainers',
    title: 'Who maintains this project?',
    content: 'Ark UI is maintained by the Chakra UI team.',
  },
]
```

## Guides

### Content Animation

Use the `--height` and/or `--width` CSS variables to animate the size of the content when it expands or closes:

```css
@keyframes slideDown {
  from {
    opacity: 0.01;
    height: 0;
  }
  to {
    opacity: 1;
    height: var(--height);
  }
}

@keyframes slideUp {
  from {
    opacity: 1;
    height: var(--height);
  }
  to {
    opacity: 0.01;
    height: 0;
  }
}

[data-scope='accordion'][data-part='item-content'][data-state='open'] {
  animation: slideDown 250ms ease-in-out;
}

[data-scope='accordion'][data-part='item-content'][data-state='closed'] {
  animation: slideUp 200ms ease-in-out;
}
```

## API Reference

### Props

### Root

#### Props

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

**`collapsible`**
Type: `boolean`
Required: false
Default Value: `false`
Description: Whether an accordion item can be closed after it has been expanded.

**`defaultValue`**
Type: `string[]`
Required: false
Default Value: `undefined`
Description: The initial value of the expanded accordion items.
Use when you don't need to control the value of the accordion.

**`disabled`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Whether the accordion items are disabled

**`hideMode`**
Type: `HideMode`
Required: false
Default Value: `'display-none'`
Description: How to hide content when mounted but not present.
- `'display-none'`: HTML `hidden` attribute. Effects stay alive.
- `'activity'`: React 19 `<Activity mode="hidden">`. Effects pause. Requires React 19+.

**`id`**
Type: `string`
Required: false
Default Value: `undefined`
Description: The unique identifier of the machine.

**`ids`**
Type: `Partial<{
  root: string
  item: (value: string) => string
  itemContent: (value: string) => string
  itemTrigger: (value: string) => string
}>`
Required: false
Default Value: `undefined`
Description: The ids of the elements in the accordion. Useful for composition.

**`lazyMount`**
Type: `boolean`
Required: false
Default Value: `false`
Description: Whether to enable lazy mounting

**`multiple`**
Type: `boolean`
Required: false
Default Value: `false`
Description: Whether multiple accordion items can be expanded at the same time.

**`onFocusChange`**
Type: `(details: FocusChangeDetails) => void`
Required: false
Default Value: `undefined`
Description: The callback fired when the focused accordion item changes.

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Required: false
Default Value: `undefined`
Description: The callback fired when the state of expanded/collapsed accordion items changes.

**`orientation`**
Type: `'horizontal' | 'vertical'`
Required: false
Default Value: `"vertical"`
Description: The orientation of the accordion items.

**`unmountOnExit`**
Type: `boolean`
Required: false
Default Value: `false`
Description: Whether to unmount on exit.

**`value`**
Type: `string[]`
Required: false
Default Value: `undefined`
Description: The controlled value of the expanded accordion items.

#### Data Attributes

**`data-scope`**: accordion
**`data-part`**: root
**`data-orientation`**: The orientation of the accordion

### ItemContent

#### Props

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

#### Data Attributes

**`data-scope`**: accordion
**`data-part`**: item-content
**`data-state`**: "open" | "closed"
**`data-disabled`**: Present when disabled
**`data-focus`**: Present when focused
**`data-orientation`**: The orientation of the item

### ItemIndicator

#### Props

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

#### Data Attributes

**`data-scope`**: accordion
**`data-part`**: item-indicator
**`data-state`**: "open" | "closed"
**`data-disabled`**: Present when disabled
**`data-focus`**: Present when focused
**`data-orientation`**: The orientation of the item

### Item

#### Props

**`value`**
Type: `string`
Required: true
Default Value: `undefined`
Description: The value of the accordion item.

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

**`disabled`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Whether the accordion item is disabled.

#### Data Attributes

**`data-scope`**: accordion
**`data-part`**: item
**`data-state`**: "open" | "closed"
**`data-focus`**: Present when focused
**`data-disabled`**: Present when disabled
**`data-orientation`**: The orientation of the item

### ItemTrigger

#### Props

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

#### Data Attributes

**`data-scope`**: accordion
**`data-part`**: item-trigger
**`data-controls`**: 
**`data-orientation`**: The orientation of the item
**`data-state`**: "open" | "closed"
**`data-focus`**: Present when focused

### RootProvider

#### Props

**`value`**
Type: `UseAccordionReturn`
Required: true
Default Value: `undefined`
Description: undefined

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

**`hideMode`**
Type: `HideMode`
Required: false
Default Value: `'display-none'`
Description: How to hide content when mounted but not present.
- `'display-none'`: HTML `hidden` attribute. Effects stay alive.
- `'activity'`: React 19 `<Activity mode="hidden">`. Effects pause. Requires React 19+.

**`lazyMount`**
Type: `boolean`
Required: false
Default Value: `false`
Description: Whether to enable lazy mounting

**`unmountOnExit`**
Type: `boolean`
Required: false
Default Value: `false`
Description: Whether to unmount on exit.

### Context

**API:**

| Property | Type | Description |
|----------|------|-------------|
| `focusedValue` | `string | null` | The value of the focused accordion item. |
| `value` | `string[]` | The value of the accordion |
| `setValue` | `(value: string[]) => void` | Sets the value of the accordion |
| `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of an accordion item. |


## Accessibility

This component complies with the
[Accordion WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/).

### Keyboard Support

**`Space`**
Description: When focus is on an trigger of a collapsed item, the item is expanded

**`Enter`**
Description: When focus is on an trigger of a collapsed section, expands the section.

**`Tab`**
Description: Moves focus to the next focusable element

**`Shift + Tab`**
Description: Moves focus to the previous focusable element

**`ArrowDown`**
Description: Moves focus to the next trigger

**`ArrowUp`**
Description: Moves focus to the previous trigger.

**`Home`**
Description: When focus is on an trigger, moves focus to the first trigger.

**`End`**
Description: When focus is on an trigger, moves focus to the last trigger.