Accordion
A collapsible component for displaying content in a vertical stack.
A collapsible component for displaying content in a vertical stack.
import { Accordion } from '@ark-ui/react'
import { ChevronDownIcon } from 'lucide-react'
const Basic = () => {
return (
<Accordion.Root defaultValue={['React']}>
{['React', 'Solid', 'Vue'].map((item, id) => (
<Accordion.Item key={id} 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>
)
}
import { Accordion } from '@ark-ui/solid'
import { ChevronDownIcon } from 'lucide-solid'
import { Index } from 'solid-js'
const Basic = () => {
return (
<Accordion.Root value={['React']}>
<Index each={['React', 'Solid', 'Vue']}>
{(item) => (
<Accordion.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>
)}
</Index>
</Accordion.Root>
)
}
<script setup lang="ts">
import { ChevronDownIcon } from 'lucide-vue-next'
import { ref } from 'vue'
import { Accordion } from '@ark-ui/vue'
const items = ref(['React', 'Solid', 'Vue'])
const value = ref(['React'])
</script>
<template>
<Accordion.Root>
<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>
Understanding the Accordion’s anatomy is crucial for proper setup:
Each component part is marked with a
data-part
attribute for easy DOM identification.
To create a collapsible Accordion where all panels can be closed simultaneously,
utilize the collapsible
prop:
import { Accordion } from '@ark-ui/react'
import { ChevronDownIcon } from 'lucide-react'
const Collapsible = () => {
return (
<Accordion.Root defaultValue={['React']} collapsible>
{['React', 'Solid', 'Vue'].map((item, id) => (
<Accordion.Item key={id} value={item}>
<Accordion.ItemTrigger>
{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>
)
}
import { Accordion } from '@ark-ui/solid'
import { ChevronDownIcon } from 'lucide-solid'
import { Index } from 'solid-js'
const Collapsible = () => {
return (
<Accordion.Root value={['React']} collapsible>
<Index each={['React', 'Solid', 'Vue']}>
{(item) => (
<Accordion.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>
)}
</Index>
</Accordion.Root>
)
}
<script setup lang="ts">
import { ChevronDownIcon } from 'lucide-vue-next'
import { ref } from 'vue'
import { Accordion } from '@ark-ui/vue'
const items = ref(['React', 'Solid', 'Vue'])
const value = ref(['React'])
</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>
For an Accordion that allows keeping multiple panels open, apply the multiple
prop:
import { Accordion } from '@ark-ui/react'
import { ChevronDownIcon } from 'lucide-react'
const Multiple = () => {
return (
<Accordion.Root defaultValue={['React']} multiple>
{['React', 'Solid', 'Vue'].map((item, id) => (
<Accordion.Item key={id} value={item}>
<Accordion.ItemTrigger>
{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>
)
}
import { Accordion } from '@ark-ui/solid'
import { ChevronDownIcon } from 'lucide-solid'
import { Index } from 'solid-js'
const Multiple = () => {
return (
<Accordion.Root value={['React']} multiple>
<Index each={['React', 'Solid', 'Vue']}>
{(item) => (
<Accordion.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>
)}
</Index>
</Accordion.Root>
)
}
<script setup lang="ts">
import { ChevronDownIcon } from 'lucide-vue-next'
import { ref } from 'vue'
import { Accordion } from '@ark-ui/vue'
const items = ref(['React', 'Solid', 'Vue'])
const value = ref(['React'])
</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>
For advanced control, access the Accordion API using a function as a child component:
import { Accordion } from '@ark-ui/react'
const RenderProp = () => {
const items = ['panel-1', 'panel-2', 'panel-3']
return (
<Accordion.Root>
{items.map((item, id) => (
<Accordion.Item key={id} value={item}>
{(api) => (
<>
<Accordion.ItemTrigger>{api.isOpen ? 'Close' : 'Open'}</Accordion.ItemTrigger>
<Accordion.ItemContent>{item} content</Accordion.ItemContent>
</>
)}
</Accordion.Item>
))}
</Accordion.Root>
)
}
import { Accordion } from '@ark-ui/solid'
import { Index } from 'solid-js'
const RenderProp = () => {
const items = ['panel-1', 'panel-2', 'panel-3']
return (
<Accordion.Root>
<Index each={items}>
{(item) => (
<Accordion.Item value={item()}>
{(api) => (
<>
<Accordion.ItemTrigger>{api().isOpen ? 'Close' : 'Open'}</Accordion.ItemTrigger>
<Accordion.ItemContent>{item()} content</Accordion.ItemContent>
</>
)}
</Accordion.Item>
)}
</Index>
</Accordion.Root>
)
}
<script setup lang="ts">
import { ChevronDownIcon } from 'lucide-vue-next'
import { ref } from 'vue'
import { Accordion } from '@ark-ui/vue'
const items = ref(['React', 'Solid', 'Vue'])
const value = ref(['React'])
</script>
<template>
<Accordion.Root>
<Accordion.Item v-for="item in items" :key="item" :value="item" v-slot="{ isOpen }">
<Accordion.ItemTrigger>{{ isOpen ? 'Close' : 'Open' }}</Accordion.ItemTrigger>
<Accordion.ItemContent>{{ item }} content</Accordion.ItemContent>
</Accordion.Item>
</Accordion.Root>
</template>
To manage the Accordion’s state, use the value
prop and update it with the
onValueChange
event:
import { Accordion } from '@ark-ui/react'
import { useState } from 'react'
const Controlled = () => {
const items = ['panel-1', 'panel-2', 'panel-3']
const [value, setValue] = useState<string[]>([])
return (
<Accordion.Root value={value} onValueChange={(details) => setValue(details.value)}>
{items.map((item, id) => (
<Accordion.Item key={id} value={item}>
<Accordion.ItemTrigger>{item} trigger</Accordion.ItemTrigger>
<Accordion.ItemContent>{item} content</Accordion.ItemContent>
</Accordion.Item>
))}
</Accordion.Root>
)
}
import { Accordion } from '@ark-ui/solid'
import { Index, createSignal } from 'solid-js'
const Controlled = () => {
const [value, setValue] = createSignal<string[]>([])
const items = ['panel-1', 'panel-2', 'panel-3']
return (
<Accordion.Root value={value()} onValueChange={(details) => setValue(details.value)}>
<Index each={items}>
{(item) => (
<Accordion.Item value={item()}>
<Accordion.ItemTrigger>{item()} trigger</Accordion.ItemTrigger>
<Accordion.ItemContent>{item()} content</Accordion.ItemContent>
</Accordion.Item>
)}
</Index>
</Accordion.Root>
)
}
<script setup lang="ts">
import { ChevronDownIcon } from 'lucide-vue-next'
import { ref } from 'vue'
import { Accordion } from '@ark-ui/vue'
const items = ref(['React', 'Solid', 'Vue'])
const value = ref(['React'])
</script>
<template>
<Accordion.Root v-model="value">
<Accordion.Item v-for="item in items" :key="item" :value="item">
<Accordion.ItemTrigger>{{ item }} trigger</Accordion.ItemTrigger>
<Accordion.ItemContent>{{ item }} content</Accordion.ItemContent>
</Accordion.Item>
</Accordion.Root>
</template>
Set the Accordion’s orientation to vertical with the orientation
prop:
import { Accordion } from '@ark-ui/react'
const Vertical = () => {
const items = ['panel-1', 'panel-2', 'panel-3']
return (
<Accordion.Root orientation="vertical">
{items.map((item, id) => (
<Accordion.Item key={id} value={item} disabled={item === 'panel-2'}>
<Accordion.ItemTrigger>{item} trigger</Accordion.ItemTrigger>
<Accordion.ItemContent>{item} content</Accordion.ItemContent>
</Accordion.Item>
))}
</Accordion.Root>
)
}
import { Accordion } from '@ark-ui/solid'
import { Index } from 'solid-js'
const Vertical = () => {
const items = ['panel-1', 'panel-2', 'panel-3']
return (
<Accordion.Root orientation="vertical">
<Index each={items}>
{(item) => (
<Accordion.Item value={item()}>
<Accordion.ItemTrigger>{item()} trigger</Accordion.ItemTrigger>
<Accordion.ItemContent>{item()} content</Accordion.ItemContent>
</Accordion.Item>
)}
</Index>
</Accordion.Root>
)
}
<script setup lang="ts">
import { ChevronDownIcon } from 'lucide-vue-next'
import { ref } from 'vue'
import { Accordion } from '@ark-ui/vue'
const items = ref(['React', 'Solid', 'Vue'])
const value = ref(['React'])
</script>
<template>
<Accordion.Root orientation="vertical">
<Accordion.Item v-for="item in items" :key="item" :value="item">
<Accordion.ItemTrigger>{{ item }} trigger</Accordion.ItemTrigger>
<Accordion.ItemContent>{{ item }} content</Accordion.ItemContent>
</Accordion.Item>
</Accordion.Root>
</template>
Disable any Accordion Item using the disabled
prop:
import { Accordion } from '@ark-ui/react'
const Disabled = () => {
const items = ['panel-1', 'panel-2', 'panel-3']
return (
<Accordion.Root>
{items.map((item, id) => (
<Accordion.Item key={id} value={item} disabled={item === 'panel-2'}>
<Accordion.ItemTrigger>{item} trigger</Accordion.ItemTrigger>
<Accordion.ItemContent>{item} content</Accordion.ItemContent>
</Accordion.Item>
))}
</Accordion.Root>
)
}
import { Accordion } from '@ark-ui/solid'
import { Index } from 'solid-js'
const Disabled = () => {
const items = ['panel-1', 'panel-2', 'panel-3']
return (
<Accordion.Root>
<Index each={items}>
{(item) => (
<Accordion.Item value={item()} disabled={item() === 'panel-2'}>
<Accordion.ItemTrigger>{item()} trigger</Accordion.ItemTrigger>
<Accordion.ItemContent>{item()} content</Accordion.ItemContent>
</Accordion.Item>
)}
</Index>
</Accordion.Root>
)
}
<script setup lang="ts">
import { ChevronDownIcon } from 'lucide-vue-next'
import { ref } from 'vue'
import { Accordion } from '@ark-ui/vue'
const items = ref(['React', 'Solid', 'Vue'])
const value = ref(['React'])
</script>
<template>
<Accordion.Root>
<Accordion.Item v-for="item in items" :key="item" :value="item" :disabled="item === 'Solid'">
<Accordion.ItemTrigger>{{ item }} trigger</Accordion.ItemTrigger>
<Accordion.ItemContent>{{ item }} content</Accordion.ItemContent>
</Accordion.Item>
</Accordion.Root>
</template>
Explore our detailed API Reference for further customization:
Prop | Type | Default |
---|---|---|
asChild Render as a different element type. | boolean | |
collapsible Whether an accordion item can be collapsed after it has been opened. | boolean | false |
defaultValue The initial value of the accordion. | string[] | |
dir The document's text/writing direction. | 'ltr' | 'rtl' | "ltr" |
disabled Whether the accordion items are disabled | boolean | |
getRootNode A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. | () => Node | ShadowRoot | Document | |
id The unique identifier of the machine. | string | |
ids The ids of the elements in the accordion. Useful for composition. | Partial<{
root: string
item(value: string): string
content(value: string): string
trigger(value: string): string
}> | |
lazyMount Whether to enable lazy mounting | boolean | false |
multiple Whether multple accordion items can be open at the same time. | boolean | false |
onExitComplete Function called when the animation ends in the closed state. | () => void | |
onFocusChange The callback fired when the focused accordion item changes. | (details: FocusChangeDetails) => void | |
onValueChange The callback fired when the state of opened/closed accordion items changes. | (details: ValueChangeDetails) => void | |
orientation The orientation of the accordion items. | 'horizontal' | 'vertical' | |
present Whether the node is present (controlled by the user) | boolean | |
unmountOnExit Whether to unmount on exit. | boolean | false |
value The `id` of the accordion item that is currently being opened. | string[] |
Prop | Type | Default |
---|---|---|
value | string | |
asChild Render as a different element type. | boolean | |
disabled | boolean |
Prop | Type | Default |
---|---|---|
asChild Render as a different element type. | boolean |
Prop | Type | Default |
---|---|---|
asChild Render as a different element type. | boolean |
Prop | Type | Default |
---|---|---|
asChild Render as a different element type. | boolean |