ExpansionPanel
A component for creating accordion-style expansion panels with proper ARIA support.
Usage
The ExpansionPanel component provides a wrapper and item pattern for managing expansion state in accordion-style interfaces. It uses the createSelection composable internally and provides full v-model support with automatic state synchronization.
Expanded:
<script setup lang="ts">
import { ExpansionPanel } from '@vuetify/v0'
import { shallowRef } from 'vue'
const panels = [
{ id: 'panel-1', title: 'Panel 1', content: 'This is the content for panel 1.' },
{ id: 'panel-2', title: 'Panel 2', content: 'This is the content for panel 2.' },
{ id: 'panel-3', title: 'Panel 3', content: 'This is the content for panel 3.' },
]
const model = shallowRef<string[]>([])
</script>
<template>
<ExpansionPanel.Root
v-model="model"
class="border border-divider rounded-lg border-solid overflow-hidden divide-y divide-divider"
multiple
>
<ExpansionPanel.Item
v-for="item in panels"
:key="item.id"
:value="item.id"
>
<ExpansionPanel.Activator
v-slot="{ isSelected }"
class="w-full px-3 py-2 border-none flex items-center gap-3 text-left cursor-pointer bg-surface hover:bg-surface-tint"
>
<span
class="inline-flex items-center justify-center w-5 text-sm text-on-surface opacity-60"
:class="isSelected ? 'text-primary' : undefined"
>
{{ isSelected ? '−' : '+' }}
</span>
<span class="flex-1 font-medium text-on-surface text-base">{{ item.title }}</span>
</ExpansionPanel.Activator>
<ExpansionPanel.Content class="p-4">
{{ item.content }}
</ExpansionPanel.Content>
</ExpansionPanel.Item>
</ExpansionPanel.Root>
<p class="mt-4 text-sm text-on-surface opacity-60">
Expanded: {{ model.join(', ') }}
</p>
</template>
Anatomy
<script setup lang="ts">
import { ExpansionPanel } from '@vuetify/v0'
</script>
<template>
<ExpansionPanel.Root>
<ExpansionPanel.Item>
<ExpansionPanel.Activator />
<ExpansionPanel.Content />
</ExpansionPanel.Item>
</ExpansionPanel.Root>
</template>For instances where you need to wrap the activator in a heading element (h3) for semantic purposes and WAI-ARIA, use the ExpansionPanel.Header component:
<script setup lang="ts">
import { ExpansionPanel } from '@vuetify/v0'
</script>
<template>
<ExpansionPanel.Root>
<ExpansionPanel.Item>
<ExpansionPanel.Header>
<ExpansionPanel.Activator />
</ExpansionPanel.Header>
<ExpansionPanel.Content />
</ExpansionPanel.Item>
</ExpansionPanel.Root>
</template>ExpansionPanel.Root
Props
namespace
stringNamespace for dependency injection (default: 'v0:expansion-panel')
Default: "v0:expansion-panel"
mandatory
boolean | "force"Mandatory expansion behavior: - false (default): All panels can be collapsed - true: Prevents collapsing the last expanded panel - 'force': Automatically expands the first non-disabled panel
Default: false
multiple
booleanEnable multi-expansion mode - false (default): Single panel expanded at a time (accordion mode) - true: Multiple panels can be expanded simultaneously Note: Changes v-model type from T to T[]
Default: false
modelValue
T | T[]Events
update:model-value
T | T[]Slots
default
ExpansionPanelRootSlotPropsExpansionPanel.Activator
Props
Slots
default
ExpansionPanelActivatorSlotPropsExpansionPanel.Content
Props
Slots
default
ExpansionPanelContentSlotPropsExpansionPanel.Header
Props
namespace
stringNamespace for retrieving the parent ExpansionPanelItem context (default: 'v0:expansion-panel')
Default: "v0:expansion-panel"
Slots
default
ExpansionPanelHeaderSlotPropsExpansionPanel.Item
Props
namespace
stringNamespace to retrieve the parent ExpansionPanelRoot context (default: 'v0:expansion-panel')
Default: "v0:expansion-panel"
Slots
default
ExpansionPanelItemSlotProps