Usage
Items
Use the items prop as an array of objects with the following properties:
- label?: string
- icon?: string
- trailingIcon?: string
- content?: string
- value?: string
- disabled?: boolean
- slot?: string
<script setup lang="ts">
const items = ref([
  {
    label: 'Icons',
    icon: 'i-lucide-smile',
    content: 'You have nothing to do, @nuxt/icon will handle it automatically.'
  },
  {
    label: 'Colors',
    icon: 'i-lucide-swatch-book',
    content: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
  },
  {
    label: 'Components',
    icon: 'i-lucide-box',
    content: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
  }
])
</script>
<template>
  <UAccordion :items="items" />
</template>
Multiple
Set the type prop to multiple to allow multiple items to be active at the same time. Defaults to single.
<script setup lang="ts">
const items = ref([
  {
    label: 'Icons',
    icon: 'i-lucide-smile',
    content: 'You have nothing to do, @nuxt/icon will handle it automatically.'
  },
  {
    label: 'Colors',
    icon: 'i-lucide-swatch-book',
    content: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
  },
  {
    label: 'Components',
    icon: 'i-lucide-box',
    content: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
  }
])
</script>
<template>
  <UAccordion type="multiple" :items="items" />
</template>
Collapsible
When type is single, you can set the collapsible prop to false to prevent the active item from collapsing.
<script setup lang="ts">
const items = ref([
  {
    label: 'Icons',
    icon: 'i-lucide-smile',
    content: 'You have nothing to do, @nuxt/icon will handle it automatically.'
  },
  {
    label: 'Colors',
    icon: 'i-lucide-swatch-book',
    content: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
  },
  {
    label: 'Components',
    icon: 'i-lucide-box',
    content: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
  }
])
</script>
<template>
  <UAccordion :collapsible="false" :items="items" />
</template>
Disabled
Use the disabled property to disable the Accordion.
You can also disable a specific item by using the disabled property in the item object.
<script setup lang="ts">
const items = ref([
  {
    label: 'Icons',
    icon: 'i-lucide-smile',
    content: 'You have nothing to do, @nuxt/icon will handle it automatically.'
  },
  {
    label: 'Colors',
    icon: 'i-lucide-swatch-book',
    content: 'Choose a primary and a neutral color from your Tailwind CSS theme.',
    disabled: true
  },
  {
    label: 'Components',
    icon: 'i-lucide-box',
    content: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
  }
])
</script>
<template>
  <UAccordion disabled :items="items" />
</template>
Trailing Icon
Use the trailing-icon prop to customize the trailing Icon of each item. Defaults to i-lucide-chevron-down.
trailingIcon property in the item object.<script setup lang="ts">
const items = ref([
  {
    label: 'Icons',
    icon: 'i-lucide-smile',
    content: 'You have nothing to do, @nuxt/icon will handle it automatically.',
    trailingIcon: 'i-lucide-plus'
  },
  {
    label: 'Colors',
    icon: 'i-lucide-swatch-book',
    content: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
  },
  {
    label: 'Components',
    icon: 'i-lucide-box',
    content: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
  }
])
</script>
<template>
  <UAccordion trailing-icon="i-lucide-arrow-down" :items="items" />
</template>
Examples
Control active item(s)
You can control the active item(s) by using the default-value prop or the v-model directive with the index of the item.
<script setup lang="ts">
const items = [
  {
    label: 'Icons',
    icon: 'i-lucide-smile',
    content: 'You have nothing to do, @nuxt/icon will handle it automatically.'
  },
  {
    label: 'Colors',
    icon: 'i-lucide-swatch-book',
    content: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
  },
  {
    label: 'Components',
    icon: 'i-lucide-box',
    content: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
  }
]
const active = ref('0')
// Note: This is for demonstration purposes only. Don't do this at home.
onMounted(() => {
  setInterval(() => {
    active.value = String((Number(active.value) + 1) % items.length)
  }, 2000)
})
</script>
<template>
  <UAccordion v-model="active" :items="items" />
</template>
value of one of the items if provided.type="multiple", ensure to pass an array to the default-value prop or the v-model directive.With body slot
Use the #body slot to customize the body of each item.
<script setup lang="ts">
const items = [
  {
    label: 'Icons',
    icon: 'i-lucide-smile'
  },
  {
    label: 'Colors',
    icon: 'i-lucide-swatch-book'
  },
  {
    label: 'Components',
    icon: 'i-lucide-box'
  }
]
</script>
<template>
  <UAccordion :items="items">
    <template #body="{ item }">
      This is the {{ item.label }} panel.
    </template>
  </UAccordion>
</template>
#body slot includes some pre-defined styles, use the #content slot if you want to start from scratch.With content slot
Use the #content slot to customize the content of each item.
<script setup lang="ts">
const items = [
  {
    label: 'Icons',
    icon: 'i-lucide-smile'
  },
  {
    label: 'Colors',
    icon: 'i-lucide-swatch-book'
  },
  {
    label: 'Components',
    icon: 'i-lucide-box'
  }
]
</script>
<template>
  <UAccordion :items="items">
    <template #content="{ item }">
      <p class="pb-3.5 text-sm text-[var(--ui-text-muted)]">
        This is the {{ item.label }} panel.
      </p>
    </template>
  </UAccordion>
</template>
With custom slot
Use the slot property to customize a specific item.
You will have access to the following slots:
- #{{ item.slot }}
- #{{ item.slot }}-body
<script setup lang="ts">
const items = [
  {
    label: 'Icons',
    icon: 'i-lucide-smile',
    content: 'You have nothing to do, @nuxt/icon will handle it automatically.'
  },
  {
    label: 'Colors',
    icon: 'i-lucide-swatch-book',
    slot: 'colors',
    content: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
  },
  {
    label: 'Components',
    icon: 'i-lucide-box',
    content: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
  }
]
</script>
<template>
  <UAccordion :items="items">
    <template #colors="{ item }">
      <p class="text-sm pb-3.5 text-[var(--ui-primary)]">
        {{ item.content }}
      </p>
    </template>
  </UAccordion>
</template>
API
Props
| Prop | Default | Type | 
|---|---|---|
| as | 
 | 
 The element or component this component should render as. | 
| items | 
 | |
| trailingIcon | 
 | 
 The icon displayed on the right side of the trigger. | 
| labelKey | 
 | 
 The key used to get the label from the item. | 
| collapsible | 
 | 
 When type is "single", allows closing content when clicking trigger for an open item. When type is "multiple", this prop has no effect. | 
| defaultValue | 
 The default active value of the item(s). Use when you do not need to control the state of the item(s). | |
| modelValue | 
 The controlled value of the active item(s). Use this when you need to control the state of the items. Can be binded with  | |
| type | 
 | 
 Determines whether a "single" or "multiple" items can be pressed at a time. This prop will be ignored if any of  | 
| disabled | 
 | 
 When  | 
| ui | 
 | 
Slots
| Slot | Type | 
|---|---|
| leading | 
 | 
| default | 
 | 
| trailing | 
 | 
| content | 
 | 
| body | 
 | 
Emits
| Event | Type | 
|---|---|
| update:modelValue | 
 | 
Theme
export default defineAppConfig({
  ui: {
    accordion: {
      slots: {
        root: 'w-full',
        item: 'border-b border-[var(--ui-border)] last:border-b-0',
        header: 'flex',
        trigger: 'group flex-1 flex items-center gap-1.5 font-medium text-sm py-3.5 focus-visible:outline-[var(--ui-primary)] min-w-0',
        content: 'data-[state=open]:animate-[accordion-down_200ms_ease-out] data-[state=closed]:animate-[accordion-up_200ms_ease-out] overflow-hidden focus:outline-none',
        body: 'text-sm pb-3.5',
        leadingIcon: 'shrink-0 size-5',
        trailingIcon: 'shrink-0 size-5 ms-auto group-data-[state=open]:rotate-180 transition-transform duration-200',
        label: 'text-start break-words'
      },
      variants: {
        disabled: {
          true: {
            trigger: 'cursor-not-allowed opacity-75'
          }
        }
      }
    }
  }
})