Usage
Items
Use the items prop as an array of objects with the following properties:
label?: stringicon?: stringtrailingIcon?: stringcontent?: stringvalue?: stringdisabled?: booleanslot?: 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.  | 
type | 
  | 
 Determines whether a "single" or "multiple" items can be pressed at a time. This prop will be ignored if any of   | 
disabled | 
  | 
 When   | 
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   | |
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'
          }
        }
      }
    }
  }
})