Skip to main content
Vuetify0 v1.0 is here
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

ExpansionPanel

A component for creating accordion-style expansion panels with proper ARIA support.

Edit this page
Report a Bug
Open issues
View on GitHub
Copy Markdown

PreviewRenders elementIntermediateJul 19, 2026

Usage

Group a set of panels into an accordion where opening one can collapse the others. Bind v-model to track which panel is open — or, in multiple mode, which panels.

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.Group
    v-model="model"
    class="border border-divider rounded-lg border-solid overflow-hidden divide-y divide-divider"
    multiple
  >
    <ExpansionPanel.Root
      v-for="item in panels"
      :key="item.id"
      :value="item.id"
    >
      <ExpansionPanel.Activator
        class="w-full px-3 py-2 border-none flex items-center gap-3 text-left cursor-pointer bg-surface hover:bg-surface-tint"
      >
        <ExpansionPanel.Cue class="inline-flex items-center justify-center w-5 text-sm text-on-surface opacity-60 data-[state=open]:text-primary">
          <span class="data-[state=open]:hidden">+</span>
          <span class="hidden data-[state=open]:inline">&minus;</span>
        </ExpansionPanel.Cue>

        <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.Root>
  </ExpansionPanel.Group>

  <p class="mt-4 text-sm text-on-surface opacity-60">
    Expanded: {{ model.join(', ') }}
  </p>
</template>

Anatomy

vue
<script setup lang="ts">
  import { ExpansionPanel } from '@vuetify/v0'
</script>

<template>
  <ExpansionPanel.Group>
    <ExpansionPanel.Root>
      <ExpansionPanel.Header>
        <ExpansionPanel.Activator>
          <ExpansionPanel.Cue />
        </ExpansionPanel.Activator>
      </ExpansionPanel.Header>

      <ExpansionPanel.Content />
    </ExpansionPanel.Root>
  </ExpansionPanel.Group>
</template>

Examples

Product FAQ accordion

This FAQ widget renders an accordion from a plain data array, mapping each entry to an ExpansionPanel.Root keyed by its question id. The ExpansionPanel.Group defaults to single-open mode, so opening one answer collapses the previous one — its v-model holds the id of the open panel, or undefined when every panel is closed. The composable seeds that model with the first question’s id, so the accordion shows one answer on mount instead of opening empty.

Each ExpansionPanel.Header renders a heading that wraps the ExpansionPanel.Activator button — the WAI-ARIA accordion shape that lets screen-reader users jump between questions by heading. The chevron is an ExpansionPanel.Cue, which emits data-state="open" and data-state="closed" on its element; the example rotates it with the data-[state=open]:rotate-180 utility, no JavaScript class toggling. ExpansionPanel.Content shows and hides with the native hidden attribute, keeping the markup accessible and the example free of custom CSS.

Reach for single-open mode when answers are long and you want the reader focused on one at a time; add multiple to ExpansionPanel.Group — and switch the model to an array — when panels are short and comparing them side by side matters. The Group is built on createSelection, so the same mandatory and enroll options apply. For a single standalone disclosure with no sibling coordination, prefer Collapsible.

FileRole
useFaq.tsFAQ data array, the single-open model seeded to the first question, and a collapse helper
FaqAccordion.vueRenders the ExpansionPanel compound — Group, Header, Activator, animated Cue, and Content
faq-accordion.vueWires the composable to the accordion and adds the status line and collapse control

Standard orders ship within 1-2 business days and arrive in 3-5 business days. Express options are offered at checkout.

Reading: How long does shipping take?

One question opens at a time. Pass multiple to ExpansionPanel.Group to let several answers stay open together.

Accessibility

ExpansionPanel follows the WAI-ARIA Accordion pattern↗︎. ExpansionPanel.Header renders a heading (<h3> by default) that wraps the ExpansionPanel.Activator button, so screen-reader users can move between panels by heading.

ARIA Attributes

AttributeValueElement
rolebutton (only when Activator is not a native <button>)Activator
aria-expandedtrue / falseActivator
aria-controlsContent region IDActivator
aria-disabledtrue / falseActivator
roleregionContent
aria-labelledbyActivator IDContent
hiddenPresent when collapsedContent
aria-hiddentrueCue

The Activator and Content IDs are paired: aria-controls on the Activator points at the Content, and aria-labelledby on the Content points back at the Activator. The Cue chevron is decorative and hidden from assistive technology.

Keyboard Navigation

KeyAction
EnterToggles the focused panel
SpaceToggles the focused panel

FAQ

Discord
Need help? Join our community for support and discussions ↗
Was this page helpful?

© 2016-1970 Vuetify, LLC
Services
Ctrl+/