Components
Accordion

Accordion

A collapsible component for displaying content in a vertical stack.

Pudding donut gummies chupa chups oat cake marzipan biscuit tart. Dessert macaroon ice cream bonbon jelly. Jelly topping tiramisu halvah lollipop.

Features

  • Full keyboard navigation
  • Supports horizontal and vertical orientation
  • Right-to-Left (RTL) support
  • Single or multiple item expansion
  • Controlled and uncontrolled modes
  • Collapse each accordion item

Anatomy

To set up the accordion correctly, it's essential to understand its anatomy and the naming of its parts.

Each part includes a data-part attribute to help identify them in the DOM.

Examples

Default Expanded State

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

<script setup lang="ts">
import { Accordion } from '@ark-ui/vue/accordion'
import { ref } from 'vue'
import { ChevronDownIcon } from 'lucide-vue-next'

const items = ref(['React', 'Solid', 'Vue'])
</script>

<template>
  <Accordion.Root :defaultValue="['React']">
    <Accordion.Item v-for="item in items" :key="item" :value="item">
      <Accordion.ItemTrigger>
        What is {{ item }}?
        <Accordion.ItemIndicator>
          <ChevronDownIcon />
        </Accordion.ItemIndicator>
      </Accordion.ItemTrigger>
      <Accordion.ItemContent>
        {{ item }} is a JavaScript library for building user interfaces.
      </Accordion.ItemContent>
    </Accordion.Item>
  </Accordion.Root>
</template>

Collapsible

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

<script setup lang="ts">
import { Accordion } from '@ark-ui/vue/accordion'
import { ref } from 'vue'
import { ChevronDownIcon } from 'lucide-vue-next'

const items = ref(['React', 'Solid', 'Vue'])
</script>

<template>
  <Accordion.Root collapsible>
    <Accordion.Item v-for="item in items" :key="item" :value="item">
      <Accordion.ItemTrigger>
        What is {{ item }}?
        <Accordion.ItemIndicator><ChevronDownIcon /></Accordion.ItemIndicator>
      </Accordion.ItemTrigger>
      <Accordion.ItemContent>
        {{ item }} is a JavaScript library for building user interfaces.
      </Accordion.ItemContent>
    </Accordion.Item>
  </Accordion.Root>
</template>

Multiple Panels

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

<script setup lang="ts">
import { Accordion } from '@ark-ui/vue/accordion'
import { ref } from 'vue'
import { ChevronDownIcon } from 'lucide-vue-next'

const items = ref(['React', 'Solid', 'Vue'])
</script>

<template>
  <Accordion.Root multiple>
    <Accordion.Item v-for="item in items" :key="item" :value="item">
      <Accordion.ItemTrigger>
        What is {{ item }}?
        <Accordion.ItemIndicator><ChevronDownIcon /></Accordion.ItemIndicator>
      </Accordion.ItemTrigger>
      <Accordion.ItemContent>
        {{ item }} is a JavaScript library for building user interfaces.
      </Accordion.ItemContent>
    </Accordion.Item>
  </Accordion.Root>
</template>

Horizontal Orientation

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

<script setup lang="ts">
import { Accordion } from '@ark-ui/vue/accordion'
import { ref } from 'vue'
import { ChevronDownIcon } from 'lucide-vue-next'

const items = ref(['React', 'Solid', 'Vue'])
</script>

<template>
  <Accordion.Root :defaultValue="['React']" orientation="horizontal">
    <Accordion.Item v-for="item in items" :key="item" :value="item">
      <Accordion.ItemTrigger>
        What is {{ item }}?
        <Accordion.ItemIndicator>
          <ChevronDownIcon />
        </Accordion.ItemIndicator>
      </Accordion.ItemTrigger>
      <Accordion.ItemContent>
        {{ item }} is a JavaScript library for building user interfaces.
      </Accordion.ItemContent>
    </Accordion.Item>
  </Accordion.Root>
</template>

Animate Content Size

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

@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;
}

Using the Root Provider

The RootProvider component provides a context for the accordion. It accepts the value of the useAccordion hook. You can leverage it to access the component state and methods from outside the accordion.

<script setup lang="ts">
import { Accordion, useAccordion } from '@ark-ui/vue/accordion'
import { ref } from 'vue'
import { ChevronDownIcon } from 'lucide-vue-next'

const items = ref(['React', 'Solid', 'Vue'])

const accordion = useAccordion({ defaultValue: ['React'] })
</script>

<template>
  <button @click="accordion.setValue(['Vue'])">Set to Vue</button>

  <Accordion.RootProvider :value="accordion">
    <Accordion.Item v-for="item in items" :key="item" :value="item">
      <Accordion.ItemTrigger>
        What is {{ item }}?
        <Accordion.ItemIndicator>
          <ChevronDownIcon />
        </Accordion.ItemIndicator>
      </Accordion.ItemTrigger>
      <Accordion.ItemContent>
        {{ item }} is a JavaScript library for building user interfaces.
      </Accordion.ItemContent>
    </Accordion.Item>
  </Accordion.RootProvider>
</template>

If you're using the RootProvider component, you don't need to use the Root component.

Acessing the focused item

Use the focusedValue property to get the value of the focused accordion item.

<script setup lang="ts">
import { Accordion } from '@ark-ui/vue/accordion'
import { ref } from 'vue'
import { ChevronDownIcon } from '../icons'

const items = ref(['React', 'Solid', 'Vue'])
</script>

<template>
  <Accordion.Root :defaultValue="['React']">
    <Accordion.Context v-slot="context">
      <span>Focused item: {{ context.focusedValue }}</span>
    </Accordion.Context>
    <Accordion.Item v-for="item in items" :key="item" :value="item">
      <Accordion.ItemTrigger>
        What is {{ item }}?
        <Accordion.ItemIndicator>
          <ChevronDownIcon />
        </Accordion.ItemIndicator>
      </Accordion.ItemTrigger>
      <Accordion.ItemContent>
        {{ item }} is a JavaScript library for building user interfaces.
      </Accordion.ItemContent>
    </Accordion.Item>
  </Accordion.Root>
</template>

Acessing the selected items

Use the value property to get the selected accordion items.

<script setup lang="ts">
import { Accordion } from '@ark-ui/vue/accordion'
import { ref } from 'vue'
import { ChevronDownIcon } from '../icons'

const items = ref(['React', 'Solid', 'Vue'])
</script>

<template>
  <Accordion.Root :defaultValue="['React']">
    <Accordion.Context v-slot="context">
      <span>Selected items: {{ context.value.join(', ') }}</span>
    </Accordion.Context>
    <Accordion.Item v-for="item in items" :key="item" :value="item">
      <Accordion.ItemTrigger>
        What is {{ item }}?
        <Accordion.ItemIndicator>
          <ChevronDownIcon />
        </Accordion.ItemIndicator>
      </Accordion.ItemTrigger>
      <Accordion.ItemContent>
        {{ item }} is a JavaScript library for building user interfaces.
      </Accordion.ItemContent>
    </Accordion.Item>
  </Accordion.Root>
</template>

Setting the selected items

Use the setValue method to set the selected accordion items.

<script setup lang="ts">
import { Accordion } from '@ark-ui/vue/accordion'
import { ref } from 'vue'
import { ChevronDownIcon } from '../icons'

const items = ref(['React', 'Solid', 'Vue'])
</script>

<template>
  <Accordion.Root :defaultValue="['React']">
    <Accordion.Context v-slot="context">
      <button @click="context.setValue(['Vue'])">Select Vue</button>
    </Accordion.Context>
    <Accordion.Item v-for="item in items" :key="item" :value="item">
      <Accordion.ItemTrigger>
        What is {{ item }}?
        <Accordion.ItemIndicator>
          <ChevronDownIcon />
        </Accordion.ItemIndicator>
      </Accordion.ItemTrigger>
      <Accordion.ItemContent>
        {{ item }} is a JavaScript library for building user interfaces.
      </Accordion.ItemContent>
    </Accordion.Item>
  </Accordion.Root>
</template>

Accessing an item's state

Use the getItemState method to get the state of an accordion item.

<script setup lang="ts">
import { Accordion } from '@ark-ui/vue/accordion'
import { ref } from 'vue'
import { ChevronDownIcon } from '../icons'

const items = ref([{ value: 'React' }, { value: 'Solid', disabled: true }, { value: 'Vue' }])
</script>

<template>
  <Accordion.Root :defaultValue="['React']">
    <Accordion.Context v-slot="context">
      <b>Vue State:</b>
      <span>Disabled: {{ context.getItemState(items[2]).disabled ? 'Y' : 'N' }}</span>
      <span>Expanded: {{ context.getItemState(items[2]).expanded ? 'Y' : 'N' }}</span>
      <span>Focused: {{ context.getItemState(items[2]).focused ? 'Y' : 'N' }}</span>
    </Accordion.Context>
    <Accordion.Item v-for="item in items" :key="item.value" v-bind="item">
      <Accordion.ItemTrigger>
        What is {{ item }}?
        <Accordion.ItemIndicator>
          <ChevronDownIcon />
        </Accordion.ItemIndicator>
      </Accordion.ItemTrigger>
      <Accordion.ItemContent>
        {{ item }} is a JavaScript library for building user interfaces.
      </Accordion.ItemContent>
    </Accordion.Item>
  </Accordion.Root>
</template>

API Reference

Root

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
collapsiblefalse
boolean

Whether an accordion item can be closed after it has been expanded.

defaultValue
string[]

The initial value of the accordion that are expanded. Use this when you do not need to control the state of the accordion.

disabled
boolean

Whether the accordion items are disabled

id
string

The unique identifier of the machine.

ids
Partial<{ root: string item(value: string): string itemContent(value: string): string itemTrigger(value: string): string }>

The ids of the elements in the accordion. Useful for composition.

lazyMountfalse
boolean

Whether to enable lazy mounting

modelValue
string[]

The accordion items that are currently expanded. Use this prop to control the state of the items via v-model.

multiplefalse
boolean

Whether multple accordion items can be expanded at the same time.

orientation'vertical'
'horizontal' | 'vertical'

The orientation of the accordion items.

unmountOnExitfalse
boolean

Whether to unmount on exit.

EmitEvent
focusChange
[details: FocusChangeDetails]

The callback fired when the focused accordion item changes.

update:modelValue
[value: string[]]

The callback fired when the model value changes.

valueChange
[details: ValueChangeDetails]

The callback fired when the state of expanded/collapsed accordion items changes.

Data AttributeValue
[data-scope]accordion
[data-part]root
[data-orientation]The orientation of the accordion

ItemContent

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[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

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[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

PropDefaultType
value
string

The value of the accordion item.

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
disabled
boolean

Whether the accordion item is disabled.

Data AttributeValue
[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

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]accordion
[data-part]item-trigger
[data-orientation]The orientation of the item
[data-state]"open" | "closed"

RootProvider

PropDefaultType
value
MachineApi<PropTypes>

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
lazyMountfalse
boolean

Whether to enable lazy mounting

unmountOnExitfalse
boolean

Whether to unmount on exit.

Accessibility

This component complies with the Accordion WAI-ARIA design pattern.

Keyboard Support

KeyDescription
Space
When focus is on an trigger of a collapsed item, the item is expanded
Enter
When focus is on an 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 trigger
ArrowUp
Moves focus to the previous trigger.
Home
When focus is on an trigger, moves focus to the first trigger.
End
When focus is on an trigger, moves focus to the last trigger.