Accordion
Usage
아코디언 구성 요소를 사용하여 축소 가능한 항목 목록을 표시합니다.
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
label: 'Is Nuxt UI free to use?',
content: 'Yes! Nuxt UI is completely free and open source under the MIT license. All 125+ components are available to everyone.'
},
{
label: 'Can I use Nuxt UI with Vue without Nuxt?',
content: 'Yes! While optimized for Nuxt, Nuxt UI works perfectly with standalone Vue projects via our Vite plugin. You can follow the [installation guide](/docs/getting-started/installation/vue) to get started.'
},
{
label: 'Is Nuxt UI production-ready?',
content: 'Yes! Nuxt UI is used in production by thousands of applications with extensive tests, regular updates, and active maintenance.'
}
])
</script>
<template>
<UAccordion :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
label: 'Is Nuxt UI free to use?',
content: 'Yes! Nuxt UI is completely free and open source under the MIT license. All 125+ components are available to everyone.'
},
{
label: 'Can I use Nuxt UI with Vue without Nuxt?',
content: 'Yes! While optimized for Nuxt, Nuxt UI works perfectly with standalone Vue projects via our Vite plugin. You can follow the [installation guide](/docs/getting-started/installation/vue) to get started.'
},
{
label: 'Is Nuxt UI production-ready?',
content: 'Yes! Nuxt UI is used in production by thousands of applications with extensive tests, regular updates, and active maintenance.'
}
])
</script>
<template>
<UAccordion :items="items" />
</template>Items 파일
items prop을 다음과 같은 속성을 가진 오브젝트 배열로 사용합니다.
label?: string(-label?: string)icon?: string- {lang="ts-type"}trailingIcon?: string- {lang="ts-type"}content?: string의 발음을 -content?: stringvalue?: string(-value?: string)disabled?: boolean-disabled?: booleanslot?: stringxxx 053 xclass?: anyui?: { item?: ClassNameValue, header?: ClassNameValue, trigger?: ClassNameValue, leadingIcon?: ClassNameValue, label?: ClassNameValue, trailingIcon?: ClassNameValue, content?: ClassNameValue, body?: ClassNameValue }(-ui?: { item?: ClassNameValue, header?: ClassNameValue, trigger?: ClassNameValue, leadingIcon?: ClassNameValue, label?: ClassNameValue, trailingIcon?: ClassNameValue, content?: ClassNameValue, body?: ClassNameValue })
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
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><script setup lang="ts">
import { ref } from 'vue'
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
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>다중
여러 항목이 동시에 활성화되도록 type Prop을 multiple로 설정합니다. 기본값은 single입니다.
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
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><script setup lang="ts">
import { ref } from 'vue'
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
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>Collapable 압축
type가 single일 때 collapsible prop을 false로 설정하여 활성 항목이 축소되지 않도록 할 수 있습니다.
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
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><script setup lang="ts">
import { ref } from 'vue'
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
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>Unmount (### 마운트 해제)
아코디언이 축소될 때 내용이 마운트 해제되지 않도록 하려면 unmount-on-hide 소품을 사용합니다. 기본값은 true입니다.
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
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 :unmount-on-hide="false" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
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 :unmount-on-hide="false" :items="items" />
</template>비활성 화
disabled 속성을 사용하여 아코디언을 비활성화합니다.
item 객체에서 disabled 속성을 사용하여 특정 항목을 비활성화할 수도 있습니다.
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
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><script setup lang="ts">
import { ref } from 'vue'
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
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 소품을 사용하여 각 항목의 후행 Icon를 사용자 정의합니다. 기본값은 i-lucide-chevron-down입니다.
trailingIcon 속성을 사용하여 특정 항목에 대한 아이콘을 설정할 수도 있습니다.<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
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><script setup lang="ts">
import { ref } from 'vue'
import type { AccordionItem } from '@nuxt/ui'
const items = ref<AccordionItem[]>([
{
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 활성화된 항목
default-value prop 또는 v-model 지시어를 사용하여 활성 항목을 제어할 수 있습니다. value가 제공되지 않으면 기본적으로 x 인덱스가 string**로 지정됩니다.
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items: AccordionItem[] = [
{
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>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import type { AccordionItem } from '@nuxt/ui'
const items: AccordionItem[] = [
{
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-key Prop을 사용하여 v-model 또는 default-value가 제공될 때 항목을 일치시키는 키를 변경합니다.type="multiple"에서는 배열을 default-value prop 또는 v-model 지시문으로 전달해야 합니다.드래그 앤 드롭 사용
아코디언에서 드래그 앤 드롭 기능을 활성화하려면 의 useSortable 컴포지션을 사용합니다. 이 통합은 Sortable.js를 래핑하여 원활한 드래그 및 드롭 환경을 제공합니다.
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
import { useSortable } from '@vueuse/integrations/useSortable'
const items = shallowRef<AccordionItem[]>([
{
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 accordion = useTemplateRef<HTMLElement>('accordion')
useSortable(accordion, items, {
animation: 150
})
</script>
<template>
<UAccordion ref="accordion" :items="items" />
</template>
<script setup lang="ts">
import { shallowRef, useTemplateRef } from 'vue'
import type { AccordionItem } from '@nuxt/ui'
import { useSortable } from '@vueuse/integrations/useSortable'
const items = shallowRef<AccordionItem[]>([
{
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 accordion = useTemplateRef<HTMLElement>('accordion')
useSortable(accordion, items, {
animation: 150
})
</script>
<template>
<UAccordion ref="accordion" :items="items" />
</template>
with body slot 본체 슬롯
#body 슬롯을 사용하여 각 항목의 본문을 사용자 지정합니다.
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items: AccordionItem[] = [
{
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 슬롯에는 처음부터 시작하려면 #content slot를 사용하여 미리 정의 된 스타일이 포함되어 있습니다.Content Slot 포함
#content 슬롯을 사용하여 각 항목의 컨텐츠를 사용자 정의합니다.
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
const items: AccordionItem[] = [
{
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-muted">
This is the {{ item.label }} panel.
</p>
</template>
</UAccordion>
</template>
사용자 정의 슬롯 포함
slot 속성을 사용하여 특정 항목을 사용자 정의합니다.
다음과 같은 슬롯에 액세스할 수 있습니다.
#{{ item.slot }}의 발음을 - {lang="ts-type"}#{{ item.slot }}-body
<script setup lang="ts">
import type { AccordionItem } from '@nuxt/ui'
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' as const,
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.'
}
] satisfies AccordionItem[]
</script>
<template>
<UAccordion :items="items">
<template #colors="{ item }">
<p class="text-sm pb-3.5 text-primary">
{{ item.content }}
</p>
</template>
</UAccordion>
</template>
Markdown 콘텐츠 포함
@comark/vue의 Markdown 구성 요소를 사용하여 아코디언 항목에서 Markdown을 렌더링할 수 있습니다.
<script setup lang="ts">
import { Markdown } from '@comark/vue'
const items = [
{
label: 'Is Nuxt UI free to use?',
icon: 'i-lucide-circle-help',
content: 'Yes! Nuxt UI is completely free and open source under the MIT license. All 125+ components are available to everyone.'
},
{
label: 'Can I use Nuxt UI with Vue without Nuxt?',
icon: 'i-lucide-circle-help',
content: 'Yes! While optimized for Nuxt, Nuxt UI works perfectly with standalone Vue projects via our Vite plugin. You can follow the [installation guide](/docs/getting-started/installation/vue) to get started.'
},
{
label: 'Will Nuxt UI work with other CSS frameworks like UnoCSS?',
icon: 'i-lucide-circle-help',
content: 'No. Nuxt UI is designed exclusively for Tailwind CSS. UnoCSS support would require significant architecture changes due to different class naming conventions.'
},
{
label: 'How does Nuxt UI handle accessibility?',
icon: 'i-lucide-circle-help',
content: 'Through [Reka UI](https://reka-ui.com/docs/overview/accessibility) integration, Nuxt UI provides **automatic ARIA attributes**, **keyboard navigation**, **focus management**, and **screen reader support**. While offering a strong foundation, testing in your specific use case remains important.'
},
{
label: 'How is Nuxt UI tested?',
icon: 'i-lucide-circle-help',
content: 'Nuxt UI ensures reliability with 1000+ Vitest tests covering core functionality and accessibility.'
},
{
label: 'Is Nuxt UI production-ready?',
icon: 'i-lucide-circle-help',
content: 'Yes! Nuxt UI is used in production by thousands of applications with extensive tests, regular updates, and active maintenance.'
}
]
</script>
<template>
<UAccordion
type="multiple"
:items="items"
:unmount-on-hide="false"
:default-value="['3']"
:ui="{
trigger: 'text-base',
body: 'text-base text-muted'
}"
>
<template #body="{ item }">
<Markdown :value="item.content" unwrap="p" />
</template>
</UAccordion>
</template>
API 파일
Props (### Props)
| Prop | Default | Type |
|---|---|---|
as | 'div' | anyThe element or component this component should render as. |
items | T[] | |
trailingIcon | appConfig.ui.icons.chevronDown | anyThe icon displayed on the right side of the trigger. |
valueKey | 'value' | keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>The key used to get the value from the item. |
labelKey | 'label' | keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>The key used to get the label from the item. |
collapsible | true | boolean When type is "single", allows closing content when clicking trigger for an open item. When type is "multiple", this prop has no effect. |
defaultValue | string | string[]The default active value of the item(s). Use when you do not need to control the state of the item(s). | |
modelValue | string | string[]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 | 'single' | "single" | "multiple"Determines whether a "single" or "multiple" items can be selected at a time. This prop will overwrite the inferred type from |
disabled | false | boolean When |
unmountOnHide | true | boolean When |
ui | { root?: SlotClass; item?: SlotClass; header?: SlotClass; trigger?: SlotClass; content?: SlotClass; body?: SlotClass; leadingIcon?: SlotClass; trailingIcon?: SlotClass; label?: SlotClass; } |
Slots
| Slot | Type |
|---|---|
default | { item: T; index: number; open: boolean; } |
leading | { item: T; index: number; open: boolean; ui: object; } |
trailing | { item: T; index: number; open: boolean; ui: object; } |
content | { item: T; index: number; open: boolean; ui: object; } |
body | { item: T; index: number; open: boolean; ui: object; } |
Emits
| Event | Type |
|---|---|
update:modelValue | [value: string | string[] | undefined] |
Theme 테마
export default defineAppConfig({
ui: {
accordion: {
slots: {
root: 'w-full',
item: 'border-b border-default last:border-b-0',
header: 'flex',
trigger: 'group flex-1 flex items-center gap-1.5 font-medium text-sm py-3.5 outline-primary/25 focus-visible:outline-3 min-w-0 rounded-md',
content: 'data-[state=open]:animate-[accordion-down_200ms_var(--ease-out)] data-[state=closed]:animate-[accordion-up_200ms_var(--ease-out)] data-[state=closed]: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 ease-out motion-reduce:transition-none',
label: 'text-start break-words'
},
variants: {
disabled: {
true: {
trigger: 'cursor-not-allowed opacity-75'
}
}
}
}
}
})import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
accordion: {
slots: {
root: 'w-full',
item: 'border-b border-default last:border-b-0',
header: 'flex',
trigger: 'group flex-1 flex items-center gap-1.5 font-medium text-sm py-3.5 outline-primary/25 focus-visible:outline-3 min-w-0 rounded-md',
content: 'data-[state=open]:animate-[accordion-down_200ms_var(--ease-out)] data-[state=closed]:animate-[accordion-up_200ms_var(--ease-out)] data-[state=closed]: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 ease-out motion-reduce:transition-none',
label: 'text-start break-words'
},
variants: {
disabled: {
true: {
trigger: 'cursor-not-allowed opacity-75'
}
}
}
}
}
})
]
})