用法
使用手风琴组件显示可折叠项目的列表。
<script setup lang="ts">
const items = ref([
{
label: 'Is Nuxt UI free to use?',
content: 'Yes! Nuxt UI is completely free and open source under the MIT license. All 100+ 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
属性用作具有以下属性的对象数组
label?: string
icon?: string
trailingIcon?: string
content?: string
value?: string
disabled?: boolean
slot?: string
class?: any
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>
多选
将 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>
Collapsible
当 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>
卸载
使用 unmount-on-hide
prop 可防止手风琴折叠时内容被卸载。默认为 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>
禁用
使用 disabled
属性来禁用手风琴。
您还可以通过在项目对象中使用 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>
尾部图标
使用 trailing-icon
prop 来自定义每个项目的右侧 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>
示例
控制活动项目
您可以通过 default-value
prop 或使用项目索引的 v-model
指令来控制活动项目。
<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>
type="multiple"
时,请确保将数组传递给 default-value
prop 或 v-model
指令。支持拖放
使用useSortable
组合式函数,来自@vueuse/integrations
以启用手风琴组件的拖放功能。此集成封装了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>
使用 body 插槽
使用 #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
插槽如果您想从头开始。使用 `content` 插槽
使用 `#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 }}
#{{ 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 内容
您可以使用MDC组件来自 @nuxtjs/mdc
,用于在手风琴项目中渲染 markdown。
<script setup lang="ts">
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 100+ 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.cn/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 }">
<MDC :value="item.content" unwrap="p" />
</template>
</UAccordion>
</template>
API
属性
属性 | 默认值 | 类型 |
---|---|---|
as |
|
此组件应渲染为的元素或组件。 |
items |
| |
trailingIcon |
|
显示在触发器右侧的图标。 |
labelKey |
|
用于从项中获取标签的键。 |
collapsible |
|
当类型为“single”时,允许在点击已打开的项目触发器时关闭内容。当类型为“multiple”时,此属性无效。 |
defaultValue |
项目(s) 的默认活动值。 当您不需要控制项目(s) 的状态时使用。 | |
modelValue |
活动项目(s) 的受控值。 当您需要控制项目状态时使用此项。可以与 | |
type |
|
确定一次可以选择“单个”还是“多个”项目。 此 prop 将覆盖从 |
disabled |
|
当为 `true` 时,防止用户与折叠面板及其所有项目交互。 |
unmountOnHide |
|
当为 `true` 时,元素在关闭状态下将被卸载。 |
ui |
|
插槽
插槽 | 类型 |
---|---|
前置 |
|
default |
|
尾部 |
|
内容 |
|
主体 |
|
事件
事件 | 类型 |
---|---|
update:modelValue |
|
主题
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 focus-visible:outline-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'
}
}
}
}
}
})
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 focus-visible:outline-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'
}
}
}
}
}
})
]
})