手风琴
功能特性
- 完整的键盘导航支持。
- 支持水平/垂直方向。
- 支持从右到左的布局方向。
- 可展开单个或多个项目。
- 支持受控与非受控模式。
安装
通过命令行安装该组件。
$ npm add reka-ui结构
导入所有部件并组合在一起。
<script setup>
import { AccordionContent, AccordionHeader, AccordionItem, AccordionRoot, AccordionTrigger } from 'reka-ui'
</script>
<template>
<AccordionRoot>
<AccordionItem>
<AccordionHeader>
<AccordionTrigger />
</AccordionHeader>
<AccordionContent />
</AccordionItem>
</AccordionRoot>
</template>API 参考
Root
包含手风琴的所有部件
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
collapsible | false | booleanWhen 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). | |
dir | 'ltr' | 'rtl'The reading direction of the accordion when applicable. If omitted, assumes LTR (left-to-right) reading mode. | |
disabled | false | booleanWhen |
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 | |
orientation | 'vertical' | 'vertical' | 'horizontal'The orientation of the accordion. |
type | 'single' | 'multiple'Determines whether a "single" or "multiple" items can be selected at a time. This prop will overwrite the inferred type from | |
unmountOnHide | true | booleanWhen |
| Emit | Payload |
|---|---|
update:modelValue | [value: string | string[]]Event handler called when the expanded state of an item changes |
| Slots (default) | Payload |
|---|---|
modelValue | AcceptableValue | AcceptableValue[] | undefinedCurrent active value |
| Data Attribute | Value |
|---|---|
[data-orientation] | "vertical" | "horizontal" |
Item
包含可折叠部分的所有部件。
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
disabled | booleanWhether or not an accordion item is disabled from user interaction.
When | |
unmountOnHide | booleanWhen | |
value* | stringA string value for the accordion item. All items within an accordion should use a unique value. |
| Slots (default) | Payload |
|---|---|
open | booleanCurrent open state |
| Data Attribute | Value |
|---|---|
[data-state] | "open" | "closed" |
[data-disabled] | 禁用时存在 |
[data-orientation] | "vertical" | "horizontal" |
Header
包裹 AccordionTrigger。使用 asChild 属性可将其调整为页面合适的标题级别。
| Prop | Default | Type |
|---|---|---|
as | 'h3' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
| Data Attribute | Value |
|---|---|
[data-state] | "open" | "closed" |
[data-disabled] | 禁用时存在 |
[data-orientation] | "vertical" | "horizontal" |
Trigger
切换其关联项目的折叠状态。应嵌套在 AccordionHeader 内。
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
| Data Attribute | Value |
|---|---|
[data-state] | "open" | "closed" |
[data-disabled] | 禁用时存在 |
[data-orientation] | "vertical" | "horizontal" |
Content
包含项目的可折叠内容。
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
forceMount | booleanUsed to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries. |
| Data Attribute | Value |
|---|---|
[data-state] | "open" | "closed" |
[data-disabled] | 禁用时存在 |
[data-orientation] | "vertical" | "horizontal" |
| CSS Variable | Description |
|---|---|
--reka-accordion-content-width | 内容展开/折叠时的宽度 |
--reka-accordion-content-height | 内容展开/折叠时的高度 |
示例
默认展开
使用 defaultValue 属性定义默认展开的项目。
<template>
<AccordionRoot
type="single"
default-value="item-2"
>
<AccordionItem value="item-1">
…
</AccordionItem>
<AccordionItem value="item-2">
…
</AccordionItem>
</AccordionRoot>
</template>允许折叠所有项目
使用 collapsible 属性允许关闭所有项目。
<template>
<AccordionRoot
type="single"
collapsible
>
<AccordionItem value="item-1">
…
</AccordionItem>
<AccordionItem value="item-2">
…
</AccordionItem>
</AccordionRoot>
</template>同时展开多个项目
将 type 属性设置为 multiple 以启用同时展开多个项目。
<template>
<AccordionRoot type="multiple">
<AccordionItem value="item-1">
…
</AccordionItem>
<AccordionItem value="item-2">
…
</AccordionItem>
</AccordionRoot>
</template>展开时旋转图标
可以添加额外的装饰性元素(如 Chevron 图标),并在项目展开时进行旋转。
// index.vue
<script setup>
import { Icon } from '@iconify/vue'
import { AccordionContent, AccordionHeader, AccordionItem, AccordionRoot, AccordionTrigger } from 'reka-ui'
import './styles.css'
</script>
<template>
<AccordionRoot type="single">
<AccordionItem value="item-1">
<AccordionHeader>
<AccordionTrigger class="AccordionTrigger">
<span>触发文本</span>
<Icon
icon="radix-icons:chevron-down"
class="AccordionChevron"
/>
</AccordionTrigger>
</AccordionHeader>
<AccordionContent>…</AccordionContent>
</AccordionItem>
</AccordionRoot>
</template>/* styles.css */
.AccordionChevron {
transition: transform 300ms;
}
.AccordionTrigger[data-state="open"] > .AccordionChevron {
transform: rotate(180deg);
}水平方向
使用 orientation 属性创建水平方向的手风琴
<template>
<AccordionRoot orientation="horizontal">
<AccordionItem value="item-1">
…
</AccordionItem>
<AccordionItem value="item-2">
…
</AccordionItem>
</AccordionRoot>
</template>内容尺寸动画
使用 --reka-accordion-content-width 和/或 --reka-accordion-content-height CSS 变量在内容展开/折叠时实现尺寸动画:
// index.vue
<script setup>
import { AccordionContent, AccordionHeader, AccordionItem, AccordionRoot, AccordionTrigger } from 'reka-ui'
import './styles.css'
</script>
<template>
<AccordionRoot type="single">
<AccordionItem value="item-1">
<AccordionHeader>…</AccordionHeader>
<AccordionContent class="AccordionContent">
…
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</template>/* styles.css */
.AccordionContent {
overflow: hidden;
}
.AccordionContent[data-state="open"] {
animation: slideDown 300ms ease-out;
}
.AccordionContent[data-state="closed"] {
animation: slideUp 300ms ease-out;
}
@keyframes slideDown {
from {
height: 0;
}
to {
height: var(--reka-accordion-content-height);
}
}
@keyframes slideUp {
from {
height: var(--reka-accordion-content-height);
}
to {
height: 0;
}
}即使折叠也渲染内容
默认情况下隐藏的内容会被移除,使用 :unmountOnHide="false" 可保持内容始终可用。
这也允许浏览器搜索隐藏文本并展开手风琴。
<template>
<AccordionRoot :unmount-on-hide="false">
<AccordionItem value="item-1">
…
</AccordionItem>
<AccordionItem value="item-2">
…
</AccordionItem>
</AccordionRoot>
</template>无障碍访问
键盘交互
| Key | Description |
|---|---|
空格键 | 当焦点位于折叠部分的 AccordionTrigger 上时,展开该部分。 |
回车键 | 当焦点位于折叠部分的 AccordionTrigger 上时,展开该部分。 |
Tab | 将焦点移至下一个可聚焦元素。 |
Shift + Tab | 将焦点移至上一个可聚焦元素。 |
向下箭头 | 当 orientation 为 vertical 时,将焦点移至下一个 AccordionTrigger。 |
向上箭头 | 当 orientation 为 vertical 时,将焦点移至上一个 AccordionTrigger。 |
向右箭头 | 当 orientation 为 horizontal 时,将焦点移至下一个 AccordionTrigger。 |
向左箭头 | 当 orientation 为 horizontal 时,将焦点移至上一个 AccordionTrigger。 |
Home | 当焦点位于 AccordionTrigger 上时,将焦点移至第一个 AccordionTrigger。 |
End | 当焦点位于 AccordionTrigger 上时,将焦点移至最后一个 AccordionTrigger。 |
