Skip to content

Accordion

A vertically stacked set of interactive headings that reveal related content.

Import

vue
<script setup lang="ts">
import {
  Accordion,
  AccordionBody,
  AccordionHeading,
  AccordionIndicator,
  AccordionItem,
  AccordionPanel,
  AccordionTrigger,
} from '@heroui-vue/vue'
</script>

Usage

Basic

Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.

Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.

We accept all major credit cards, including Visa, Mastercard, and American Express.

Shipping costs vary based on your location and the size of your order. We offer free shipping for orders over $50.

Yes, we ship to most countries. Please check our shipping rates and policies for more information.

If you're not satisfied with your purchase, you can request a refund within 30 days of purchase. Please contact our customer support team for assistance.

<template>
  <Accordion class="demo-accordion">
    <AccordionItem v-for="item in items" :key="item.title" :value="item.title">
      <AccordionHeading>
        <AccordionTrigger>
          <DemoIcon :name="item.icon" class="demo-accordion-icon" />
          {{ item.title }}
          <AccordionIndicator />
        </AccordionTrigger>
      </AccordionHeading>
      <AccordionPanel>
        <AccordionBody>{{ item.content }}</AccordionBody>
      </AccordionPanel>
    </AccordionItem>
  </Accordion>
</template>

<script setup lang="ts">
import { defineComponent, h } from 'vue'
import {
  Accordion,
  AccordionBody,
  AccordionHeading,
  AccordionIndicator,
  AccordionItem,
  AccordionPanel,
  AccordionTrigger,
} from '@heroui-vue/vue'

const items = [
  {
    title: 'How do I place an order?',
    icon: 'shopping-bag',
    content:
      "Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.",
  },
  {
    title: 'Can I modify or cancel my order?',
    icon: 'receipt',
    content:
      "Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.",
  },
  {
    title: 'What payment methods do you accept?',
    icon: 'credit-card',
    content: 'We accept all major credit cards, including Visa, Mastercard, and American Express.',
  },
  {
    title: 'How much does shipping cost?',
    icon: 'box',
    content:
      'Shipping costs vary based on your location and the size of your order. We offer free shipping for orders over $50.',
  },
  {
    title: 'Do you ship internationally?',
    icon: 'globe',
    content:
      'Yes, we ship to most countries. Please check our shipping rates and policies for more information.',
  },
  {
    title: 'How do I request a refund?',
    icon: 'refresh',
    content:
      "If you're not satisfied with your purchase, you can request a refund within 30 days of purchase. Please contact our customer support team for assistance.",
  },
]

const iconPaths: Record<string, string[]> = {
  box: ['M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z', 'M3.3 7 12 12l8.7-5', 'M12 22V12'],
  'credit-card': ['M3 6h18v12H3z', 'M3 10h18', 'M7 15h3'],
  globe: ['M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20Z', 'M2 12h20', 'M12 2a15.3 15.3 0 0 1 0 20', 'M12 2a15.3 15.3 0 0 0 0 20'],
  receipt: ['M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2Z', 'M8 7h8', 'M8 11h8', 'M8 15h5'],
  refresh: ['M3 12a9 9 0 0 1 15-6.7L21 8', 'M21 3v5h-5', 'M21 12a9 9 0 0 1-15 6.7L3 16', 'M3 21v-5h5'],
  'shopping-bag': ['M6 8h12l-1 13H7L6 8Z', 'M9 8a3 3 0 0 1 6 0'],
}

const DemoIcon = defineComponent({
  props: {
    name: {
      type: String,
      required: true,
    },
  },
  setup(props) {
    return () =>
      h(
        'svg',
        {
          viewBox: '0 0 24 24',
          fill: 'none',
          stroke: 'currentColor',
          'stroke-width': '2',
          'stroke-linecap': 'round',
          'stroke-linejoin': 'round',
          'aria-hidden': 'true',
        },
        iconPaths[props.name]?.map((d) => h('path', { d })) ?? [],
      )
  },
})
</script>

<style lang="less">
.demo-accordion {
  width: 100%;
  max-width: 28rem;
  text-align: left;
}

.demo-accordion-icon {
  width: 1rem;
  height: 1rem;
  margin-right: 0.75rem;
  flex-shrink: 0;
  color: var(--color-muted-foreground);
}
</style>

Surface

Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.

Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.

We accept all major credit cards, including Visa, Mastercard, and American Express.

<template>
  <Accordion class="demo-accordion" variant="surface">
    <AccordionItem v-for="item in items" :key="item.title" :value="item.title">
      <AccordionHeading>
        <AccordionTrigger>
          <DemoIcon :name="item.icon" class="demo-accordion-icon" />
          {{ item.title }}
          <AccordionIndicator />
        </AccordionTrigger>
      </AccordionHeading>
      <AccordionPanel>
        <AccordionBody>{{ item.content }}</AccordionBody>
      </AccordionPanel>
    </AccordionItem>
  </Accordion>
</template>

<script setup lang="ts">
import { defineComponent, h } from 'vue'
import {
  Accordion,
  AccordionBody,
  AccordionHeading,
  AccordionIndicator,
  AccordionItem,
  AccordionPanel,
  AccordionTrigger,
} from '@heroui-vue/vue'

const items = [
  {
    title: 'How do I place an order?',
    icon: 'shopping-bag',
    content:
      "Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.",
  },
  {
    title: 'Can I modify or cancel my order?',
    icon: 'receipt',
    content:
      "Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.",
  },
  {
    title: 'What payment methods do you accept?',
    icon: 'credit-card',
    content: 'We accept all major credit cards, including Visa, Mastercard, and American Express.',
  },
]

const iconPaths: Record<string, string[]> = {
  'credit-card': ['M3 6h18v12H3z', 'M3 10h18', 'M7 15h3'],
  receipt: ['M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2Z', 'M8 7h8', 'M8 11h8', 'M8 15h5'],
  'shopping-bag': ['M6 8h12l-1 13H7L6 8Z', 'M9 8a3 3 0 0 1 6 0'],
}

const DemoIcon = defineComponent({
  props: {
    name: {
      type: String,
      required: true,
    },
  },
  setup(props) {
    return () =>
      h(
        'svg',
        {
          viewBox: '0 0 24 24',
          fill: 'none',
          stroke: 'currentColor',
          'stroke-width': '2',
          'stroke-linecap': 'round',
          'stroke-linejoin': 'round',
          'aria-hidden': 'true',
        },
        iconPaths[props.name]?.map((d) => h('path', { d })) ?? [],
      )
  },
})
</script>

<style lang="less">
.demo-accordion {
  width: 100%;
  max-width: 28rem;
  text-align: left;
}

.demo-accordion-icon {
  width: 1rem;
  height: 1rem;
  margin-right: 0.75rem;
  flex-shrink: 0;
  color: var(--color-muted-foreground);
}
</style>

Controlled

Expanded: getting-started

Learn the basics of HeroUI and how to integrate it into your Vue project. This section covers installation, setup, and your first component.

Understand the fundamental concepts behind HeroUI, including the compound component pattern, styling with Tailwind CSS, and accessibility features.

Explore advanced features like custom variants, theme customization, and integration with other libraries in your Vue ecosystem.

<template>
  <div class="demo-accordion-controlled">
    <div class="demo-accordion-controlled__bar">
      <p class="demo-accordion-controlled__state">
        Expanded: <strong>{{ expandedKey || 'none' }}</strong>
      </p>
      <div class="demo-accordion-controlled__actions">
        <Button
          aria-label="Previous item"
          :is-disabled="previousDisabled"
          is-icon-only
          size="sm"
          variant="secondary"
          @click="selectPrevious"
        >
          <DemoIcon name="chevron-up" />
        </Button>
        <Button
          aria-label="Next item"
          :is-disabled="nextDisabled"
          is-icon-only
          size="sm"
          variant="secondary"
          @click="selectNext"
        >
          <DemoIcon name="chevron-down" />
        </Button>
      </div>
    </div>

    <Accordion v-model="expandedKey" class="demo-accordion">
      <AccordionItem v-for="item in items" :key="item.id" :value="item.id">
        <AccordionHeading>
          <AccordionTrigger>
            {{ item.title }}
            <AccordionIndicator />
          </AccordionTrigger>
        </AccordionHeading>
        <AccordionPanel>
          <AccordionBody>{{ item.content }}</AccordionBody>
        </AccordionPanel>
      </AccordionItem>
    </Accordion>
  </div>
</template>

<script setup lang="ts">
import { computed, defineComponent, h, ref } from 'vue'
import {
  Accordion,
  AccordionBody,
  AccordionHeading,
  AccordionIndicator,
  AccordionItem,
  AccordionPanel,
  AccordionTrigger,
  Button,
} from '@heroui-vue/vue'

const items = [
  {
    id: 'getting-started',
    title: 'Getting Started',
    content:
      'Learn the basics of HeroUI and how to integrate it into your Vue project. This section covers installation, setup, and your first component.',
  },
  {
    id: 'core-concepts',
    title: 'Core Concepts',
    content:
      'Understand the fundamental concepts behind HeroUI, including the compound component pattern, styling with Tailwind CSS, and accessibility features.',
  },
  {
    id: 'advanced-usage',
    title: 'Advanced Usage',
    content:
      'Explore advanced features like custom variants, theme customization, and integration with other libraries in your Vue ecosystem.',
  },
]

const expandedKey = ref<string | undefined>('getting-started')
const currentIndex = computed(() => items.findIndex((item) => item.id === expandedKey.value))
const previousDisabled = computed(() => currentIndex.value <= 0)
const nextDisabled = computed(() => currentIndex.value === -1 || currentIndex.value >= items.length - 1)

const selectPrevious = () => {
  if (previousDisabled.value) return
  expandedKey.value = items[currentIndex.value - 1]?.id
}

const selectNext = () => {
  if (nextDisabled.value) return
  expandedKey.value = items[currentIndex.value + 1]?.id
}

const DemoIcon = defineComponent({
  props: {
    name: {
      type: String,
      required: true,
    },
  },
  setup(props) {
    return () =>
      h(
        'svg',
        {
          viewBox: '0 0 24 24',
          fill: 'none',
          stroke: 'currentColor',
          'stroke-width': '2',
          'stroke-linecap': 'round',
          'stroke-linejoin': 'round',
          'aria-hidden': 'true',
          class: 'demo-accordion-controlled__icon',
        },
        [h('path', { d: props.name === 'chevron-up' ? 'm18 15-6-6-6 6' : 'm6 9 6 6 6-6' })],
      )
  },
})
</script>

<style lang="less">
.demo-accordion-controlled {
  width: 100%;
  max-width: 28rem;
  text-align: left;
}

.demo-accordion-controlled__bar {
  margin-bottom: 1rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.demo-accordion-controlled__state {
  margin: 0;
  color: var(--color-muted-foreground);
  font-size: 0.875rem;
}

.demo-accordion-controlled__actions {
  display: flex;
  gap: 0.5rem;
}

.demo-accordion-controlled__icon {
  width: 1rem;
  height: 1rem;
}

.demo-accordion {
  width: 100%;
  max-width: 28rem;
}
</style>

Multiple

Learn the basics of HeroUI and how to integrate it into your Vue project. This section covers installation, setup, and your first component.

Understand the fundamental concepts behind HeroUI, including the compound component pattern, styling with Tailwind CSS, and accessibility features.

Explore advanced features like custom variants, theme customization, and integration with other libraries in your Vue ecosystem.

Follow our recommended best practices for building performant, accessible, and maintainable applications with HeroUI components.

<template>
  <Accordion allows-multiple-expanded class="demo-accordion">
    <AccordionItem v-for="item in items" :key="item.title" :value="item.title">
      <AccordionHeading>
        <AccordionTrigger>
          {{ item.title }}
          <AccordionIndicator />
        </AccordionTrigger>
      </AccordionHeading>
      <AccordionPanel>
        <AccordionBody>{{ item.content }}</AccordionBody>
      </AccordionPanel>
    </AccordionItem>
  </Accordion>
</template>

<script setup lang="ts">
import {
  Accordion,
  AccordionBody,
  AccordionHeading,
  AccordionIndicator,
  AccordionItem,
  AccordionPanel,
  AccordionTrigger,
} from '@heroui-vue/vue'

const items = [
  {
    title: 'Getting Started',
    content:
      'Learn the basics of HeroUI and how to integrate it into your Vue project. This section covers installation, setup, and your first component.',
  },
  {
    title: 'Core Concepts',
    content:
      'Understand the fundamental concepts behind HeroUI, including the compound component pattern, styling with Tailwind CSS, and accessibility features.',
  },
  {
    title: 'Advanced Usage',
    content:
      'Explore advanced features like custom variants, theme customization, and integration with other libraries in your Vue ecosystem.',
  },
  {
    title: 'Best Practices',
    content:
      'Follow our recommended best practices for building performant, accessible, and maintainable applications with HeroUI components.',
  },
]
</script>

<style lang="less">
.demo-accordion {
  width: 100%;
  max-width: 28rem;
  text-align: left;
}
</style>

Custom Indicator

This accordion uses a plus icon that changes when expanded.

This item uses a caret icon for the indicator. The rotation animation is applied automatically.

This item uses an arrow icon. Any icon you pass receives the expanded state styles.

<template>
  <Accordion v-model="expandedKey" class="demo-accordion" variant="surface">
    <AccordionItem value="1">
      <AccordionHeading>
        <AccordionTrigger>
          Using Plus/Minus Icon
          <AccordionIndicator>
            <DemoIcon :name="expandedKey === '1' ? 'minus' : 'plus'" />
          </AccordionIndicator>
        </AccordionTrigger>
      </AccordionHeading>
      <AccordionPanel>
        <AccordionBody>
          This accordion uses a plus icon that changes when expanded.
        </AccordionBody>
      </AccordionPanel>
    </AccordionItem>

    <AccordionItem value="2">
      <AccordionHeading>
        <AccordionTrigger>
          Using Caret Icon
          <AccordionIndicator>
            <DemoIcon name="circle-chevron-down" />
          </AccordionIndicator>
        </AccordionTrigger>
      </AccordionHeading>
      <AccordionPanel>
        <AccordionBody>
          This item uses a caret icon for the indicator. The rotation animation is applied automatically.
        </AccordionBody>
      </AccordionPanel>
    </AccordionItem>

    <AccordionItem value="3">
      <AccordionHeading>
        <AccordionTrigger>
          Using Arrow Icon
          <AccordionIndicator>
            <DemoIcon name="chevrons-down" />
          </AccordionIndicator>
        </AccordionTrigger>
      </AccordionHeading>
      <AccordionPanel>
        <AccordionBody>
          This item uses an arrow icon. Any icon you pass receives the expanded state styles.
        </AccordionBody>
      </AccordionPanel>
    </AccordionItem>
  </Accordion>
</template>

<script setup lang="ts">
import { defineComponent, h, ref } from 'vue'
import {
  Accordion,
  AccordionBody,
  AccordionHeading,
  AccordionIndicator,
  AccordionItem,
  AccordionPanel,
  AccordionTrigger,
} from '@heroui-vue/vue'

const expandedKey = ref<string | undefined>()

const paths: Record<string, string[]> = {
  'chevrons-down': ['m7 6 5 5 5-5', 'm7 13 5 5 5-5'],
  'circle-chevron-down': ['M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20Z', 'm8 10 4 4 4-4'],
  minus: ['M5 12h14'],
  plus: ['M12 5v14', 'M5 12h14'],
}

const DemoIcon = defineComponent({
  props: {
    name: {
      type: String,
      required: true,
    },
  },
  setup(props) {
    return () =>
      h(
        'svg',
        {
          viewBox: '0 0 24 24',
          fill: 'none',
          stroke: 'currentColor',
          'stroke-width': '2',
          'stroke-linecap': 'round',
          'stroke-linejoin': 'round',
          'aria-hidden': 'true',
        },
        paths[props.name]?.map((d) => h('path', { d })) ?? [],
      )
  },
})
</script>

<style lang="less">
.demo-accordion {
  width: 100%;
  max-width: 28rem;
  text-align: left;
}
</style>

Without Separator

Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.

Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.

We accept all major credit cards, including Visa, Mastercard, and American Express.

<template>
  <Accordion hide-separator class="demo-accordion">
    <AccordionItem v-for="item in items" :key="item.title" :value="item.title">
      <AccordionHeading>
        <AccordionTrigger>
          <DemoIcon :name="item.icon" class="demo-accordion-icon" />
          {{ item.title }}
          <AccordionIndicator />
        </AccordionTrigger>
      </AccordionHeading>
      <AccordionPanel>
        <AccordionBody>{{ item.content }}</AccordionBody>
      </AccordionPanel>
    </AccordionItem>
  </Accordion>
</template>

<script setup lang="ts">
import { defineComponent, h } from 'vue'
import {
  Accordion,
  AccordionBody,
  AccordionHeading,
  AccordionIndicator,
  AccordionItem,
  AccordionPanel,
  AccordionTrigger,
} from '@heroui-vue/vue'

const items = [
  {
    title: 'How do I place an order?',
    icon: 'shopping-bag',
    content:
      "Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.",
  },
  {
    title: 'Can I modify or cancel my order?',
    icon: 'receipt',
    content:
      "Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.",
  },
  {
    title: 'What payment methods do you accept?',
    icon: 'credit-card',
    content: 'We accept all major credit cards, including Visa, Mastercard, and American Express.',
  },
]

const iconPaths: Record<string, string[]> = {
  'credit-card': ['M3 6h18v12H3z', 'M3 10h18', 'M7 15h3'],
  receipt: ['M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2Z', 'M8 7h8', 'M8 11h8', 'M8 15h5'],
  'shopping-bag': ['M6 8h12l-1 13H7L6 8Z', 'M9 8a3 3 0 0 1 6 0'],
}

const DemoIcon = defineComponent({
  props: {
    name: {
      type: String,
      required: true,
    },
  },
  setup(props) {
    return () =>
      h(
        'svg',
        {
          viewBox: '0 0 24 24',
          fill: 'none',
          stroke: 'currentColor',
          'stroke-width': '2',
          'stroke-linecap': 'round',
          'stroke-linejoin': 'round',
          'aria-hidden': 'true',
        },
        iconPaths[props.name]?.map((d) => h('path', { d })) ?? [],
      )
  },
})
</script>

<style lang="less">
.demo-accordion {
  width: 100%;
  max-width: 28rem;
  text-align: left;
}

.demo-accordion-icon {
  width: 1rem;
  height: 1rem;
  margin-right: 0.75rem;
  flex-shrink: 0;
  color: var(--color-muted-foreground);
}
</style>

Custom Styles

Stay informed about your account activity with real-time notifications.

Enhance your browsing experience by installing our official browser extension.

Begin your journey into the world of digital collectibles by creating your first NFT.

<template>
  <Accordion class="demo-accordion-custom" variant="surface">
    <AccordionItem v-for="item in items" :key="item.title" class="demo-accordion-custom__item" :value="item.title">
      <AccordionHeading>
        <AccordionTrigger class="demo-accordion-custom__trigger">
          <img :alt="item.title" class="demo-accordion-custom__image" :src="item.iconUrl">
          <div class="demo-accordion-custom__content">
            <span class="demo-accordion-custom__title">{{ item.title }}</span>
            <span class="demo-accordion-custom__subtitle">{{ item.subtitle }}</span>
          </div>
          <AccordionIndicator class="demo-accordion-custom__indicator" />
        </AccordionTrigger>
      </AccordionHeading>
      <AccordionPanel>
        <AccordionBody class="demo-accordion-custom__body">{{ item.content }}</AccordionBody>
      </AccordionPanel>
    </AccordionItem>
  </Accordion>
</template>

<script setup lang="ts">
import {
  Accordion,
  AccordionBody,
  AccordionHeading,
  AccordionIndicator,
  AccordionItem,
  AccordionPanel,
  AccordionTrigger,
} from '@heroui-vue/vue'

const items = [
  {
    title: 'Set Up Notifications',
    subtitle: 'Receive account activity updates',
    content: 'Stay informed about your account activity with real-time notifications.',
    iconUrl: 'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/3dicons/bell-small.png',
  },
  {
    title: 'Set up Browser Extension',
    subtitle: 'Connect you browser to your account',
    content: 'Enhance your browsing experience by installing our official browser extension.',
    iconUrl: 'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/3dicons/compass-small.png',
  },
  {
    title: 'Mint Collectible',
    subtitle: 'Create your first collectible',
    content: 'Begin your journey into the world of digital collectibles by creating your first NFT.',
    iconUrl: 'https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/3dicons/mint-collective-small.png',
  },
]
</script>

<style lang="less">
.demo-accordion-custom {
  width: 100%;
  max-width: 28rem;
  border-radius: 1rem;
  background: color-mix(in oklab, var(--color-surface) 10%, transparent);
  text-align: left;
}

.demo-accordion-custom__item {
  &:first-child [data-slot='accordion-trigger'] {
    border-top-left-radius: 1rem;
    border-top-right-radius: 1rem;
  }

  &:last-child:not(:has([data-slot='accordion-trigger'][aria-expanded='true'])) [data-slot='accordion-trigger'] {
    border-bottom-right-radius: 1rem;
    border-bottom-left-radius: 1rem;
  }
}

.demo-accordion-custom__trigger {
  gap: 0.5rem;
  transition: none;
}

.demo-accordion-custom__image {
  width: 2.75rem;
  height: 2.75rem;
  transition:
    scale 300ms var(--ease-out),
    rotate 300ms var(--ease-out),
    filter 300ms var(--ease-out);
}

.demo-accordion-custom__item:hover .demo-accordion-custom__image {
  filter: drop-shadow(0 10px 8px rgb(0 0 0 / 12%));
  rotate: -10deg;
  scale: 1.2;
}

.demo-accordion-custom__content {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.demo-accordion-custom__title {
  font-weight: 500;
  line-height: 1.25rem;
}

.demo-accordion-custom__subtitle,
.demo-accordion-custom__body {
  color: color-mix(in oklab, var(--color-muted-foreground) 80%, transparent);
}

.demo-accordion-custom__subtitle {
  font-weight: 400;
  line-height: 1.5rem;
}

.demo-accordion-custom__indicator {
  color: color-mix(in oklab, var(--color-muted-foreground) 50%, transparent);
}
</style>

Disabled

Entire accordion disabled

This content cannot be accessed when the accordion is disabled.

This content cannot be accessed when the accordion is disabled.

Individual items disabled

This item is active and can be toggled normally.

This content cannot be accessed when the item is disabled.

This item is also active and can be toggled.

<template>
  <div class="demo-accordion-disabled">
    <div class="demo-accordion-section">
      <h3 class="demo-accordion-heading">Entire accordion disabled</h3>
      <Accordion is-disabled class="demo-accordion">
        <AccordionItem value="disabled-1">
          <AccordionHeading>
            <AccordionTrigger>
              Disabled Item 1
              <AccordionIndicator />
            </AccordionTrigger>
          </AccordionHeading>
          <AccordionPanel>
            <AccordionBody>This content cannot be accessed when the accordion is disabled.</AccordionBody>
          </AccordionPanel>
        </AccordionItem>
        <AccordionItem value="disabled-2">
          <AccordionHeading>
            <AccordionTrigger>
              Disabled Item 2
              <AccordionIndicator />
            </AccordionTrigger>
          </AccordionHeading>
          <AccordionPanel>
            <AccordionBody>This content cannot be accessed when the accordion is disabled.</AccordionBody>
          </AccordionPanel>
        </AccordionItem>
      </Accordion>
    </div>

    <div class="demo-accordion-section">
      <h3 class="demo-accordion-heading">Individual items disabled</h3>
      <Accordion class="demo-accordion">
        <AccordionItem value="active">
          <AccordionHeading>
            <AccordionTrigger>
              Active Item
              <AccordionIndicator />
            </AccordionTrigger>
          </AccordionHeading>
          <AccordionPanel>
            <AccordionBody>This item is active and can be toggled normally.</AccordionBody>
          </AccordionPanel>
        </AccordionItem>
        <AccordionItem is-disabled value="disabled">
          <AccordionHeading>
            <AccordionTrigger>
              Disabled Item
              <AccordionIndicator />
            </AccordionTrigger>
          </AccordionHeading>
          <AccordionPanel>
            <AccordionBody>This content cannot be accessed when the item is disabled.</AccordionBody>
          </AccordionPanel>
        </AccordionItem>
        <AccordionItem value="another-active">
          <AccordionHeading>
            <AccordionTrigger>
              Another Active Item
              <AccordionIndicator />
            </AccordionTrigger>
          </AccordionHeading>
          <AccordionPanel>
            <AccordionBody>This item is also active and can be toggled.</AccordionBody>
          </AccordionPanel>
        </AccordionItem>
      </Accordion>
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  Accordion,
  AccordionBody,
  AccordionHeading,
  AccordionIndicator,
  AccordionItem,
  AccordionPanel,
  AccordionTrigger,
} from '@heroui-vue/vue'
</script>

<style lang="less">
.demo-accordion-disabled {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: center;
  gap: 2rem;
  text-align: left;
}

.demo-accordion-section,
.demo-accordion {
  width: 100%;
  max-width: 28rem;
}

.demo-accordion-section {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.demo-accordion-heading {
  margin: 0;
  color: var(--color-muted-foreground);
  font-size: 0.875rem;
  font-weight: 500;
}
</style>

Anatomy

vue
<template>
  <Accordion>
    <AccordionItem value="item-1">
      <AccordionHeading>
        <AccordionTrigger>
          Title
          <AccordionIndicator />
        </AccordionTrigger>
      </AccordionHeading>
      <AccordionPanel>
        <AccordionBody>Content</AccordionBody>
      </AccordionPanel>
    </AccordionItem>
  </Accordion>
</template>

API

Accordion Props

PropTypeDefaultDescription
modelValuestring | string[]undefinedControlled expanded item value.
defaultValuestring | string[]undefinedInitial expanded item value.
allowsMultipleExpandedbooleanfalseAllow multiple items to stay open.
collapsiblebooleantrueAllow the currently open single item to close.
variant'default' | 'surface''default'Visual variant.
isDisabledbooleanfalseDisable every accordion item.
hideSeparatorbooleanfalseHide item separators.

AccordionItem Props

PropTypeDefaultDescription
valuestringrequiredUnique item value.
isDisabledbooleanfalseDisable this item.
classstringundefinedAdditional classes for the item.

Released under the Apache-2.0 License.