backdrop
组件

手风琴

一组垂直堆叠的交互式标题,每个标题可展开显示关联的内容部分。

Yes. It adheres to the WAI-ARIA design pattern.

功能特性

  • 完整的键盘导航支持。
  • 支持水平/垂直方向。
  • 支持从右到左的布局方向。
  • 可展开单个或多个项目。
  • 支持受控与非受控模式。

安装

通过命令行安装该组件。

sh
$ npm add reka-ui

结构

导入所有部件并组合在一起。

vue
<script setup>
import { AccordionContent, AccordionHeader, AccordionItem, AccordionRoot, AccordionTrigger } from 'reka-ui'
</script>

<template>
  <AccordionRoot>
    <AccordionItem>
      <AccordionHeader>
        <AccordionTrigger />
      </AccordionHeader>
      <AccordionContent />
    </AccordionItem>
  </AccordionRoot>
</template>

API 参考

Root

包含手风琴的所有部件

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChild
boolean

Change 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
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).

dir
'ltr' | 'rtl'

The reading direction of the accordion when applicable. If omitted, assumes LTR (left-to-right) reading mode.

disabled
false
boolean

When true, prevents the user from interacting with the accordion and all its items

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 v-model

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 modelValue and defaultValue.

unmountOnHide
true
boolean

When true, the element will be unmounted on closed state.

EmitPayload
update:modelValue
[value: string | string[]]

Event handler called when the expanded state of an item changes

Slots (default)Payload
modelValue
AcceptableValue | AcceptableValue[] | undefined

Current active value

Data AttributeValue
[data-orientation]"vertical" | "horizontal"

Item

包含可折叠部分的所有部件。

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChild
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

disabled
boolean

Whether or not an accordion item is disabled from user interaction. When true, prevents the user from interacting with the item.

unmountOnHide
boolean

When true, the element will be unmounted on closed state.

value*
string

A string value for the accordion item. All items within an accordion should use a unique value.

Slots (default)Payload
open
boolean

Current open state

Data AttributeValue
[data-state]"open" | "closed"
[data-disabled]禁用时存在
[data-orientation]"vertical" | "horizontal"

包裹 AccordionTrigger。使用 asChild 属性可将其调整为页面合适的标题级别。

PropDefaultType
as
'h3'
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChild
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Data AttributeValue
[data-state]"open" | "closed"
[data-disabled]禁用时存在
[data-orientation]"vertical" | "horizontal"

Trigger

切换其关联项目的折叠状态。应嵌套在 AccordionHeader 内。

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChild
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Data AttributeValue
[data-state]"open" | "closed"
[data-disabled]禁用时存在
[data-orientation]"vertical" | "horizontal"

Content

包含项目的可折叠内容。

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChild
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

forceMount
boolean

Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries.

Data AttributeValue
[data-state]"open" | "closed"
[data-disabled]禁用时存在
[data-orientation]"vertical" | "horizontal"
CSS VariableDescription
--reka-accordion-content-width
内容展开/折叠时的宽度
--reka-accordion-content-height
内容展开/折叠时的高度

示例

默认展开

使用 defaultValue 属性定义默认展开的项目。

vue
<template>
  <AccordionRoot
    type="single"
    default-value="item-2"
  >
    <AccordionItem value="item-1">

    </AccordionItem>
    <AccordionItem value="item-2">

    </AccordionItem>
  </AccordionRoot>
</template>

允许折叠所有项目

使用 collapsible 属性允许关闭所有项目。

vue
<template>
  <AccordionRoot
    type="single"
    collapsible
  >
    <AccordionItem value="item-1">

    </AccordionItem>
    <AccordionItem value="item-2">

    </AccordionItem>
  </AccordionRoot>
</template>

同时展开多个项目

type 属性设置为 multiple 以启用同时展开多个项目。

vue
<template>
  <AccordionRoot type="multiple">
    <AccordionItem value="item-1">

    </AccordionItem>
    <AccordionItem value="item-2">

    </AccordionItem>
  </AccordionRoot>
</template>

展开时旋转图标

可以添加额外的装饰性元素(如 Chevron 图标),并在项目展开时进行旋转。

vue
// 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>
css
/* styles.css */
.AccordionChevron {
  transition: transform 300ms;
}
.AccordionTrigger[data-state="open"] > .AccordionChevron {
  transform: rotate(180deg);
}

水平方向

使用 orientation 属性创建水平方向的手风琴

vue
<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 变量在内容展开/折叠时实现尺寸动画:

vue
// 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>
css
/* 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" 可保持内容始终可用。

这也允许浏览器搜索隐藏文本并展开手风琴。

vue
<template>
  <AccordionRoot :unmount-on-hide="false">
    <AccordionItem value="item-1">

    </AccordionItem>
    <AccordionItem value="item-2">

    </AccordionItem>
  </AccordionRoot>
</template>

无障碍访问

遵循 手风琴 WAI-ARIA 设计模式

键盘交互

KeyDescription
空格键
当焦点位于折叠部分的 AccordionTrigger 上时,展开该部分。
回车键
当焦点位于折叠部分的 AccordionTrigger 上时,展开该部分。
Tab
将焦点移至下一个可聚焦元素。
Shift + Tab
将焦点移至上一个可聚焦元素。
向下箭头
orientationvertical 时,将焦点移至下一个 AccordionTrigger
向上箭头
orientationvertical 时,将焦点移至上一个 AccordionTrigger
向右箭头
orientationhorizontal 时,将焦点移至下一个 AccordionTrigger
向左箭头
orientationhorizontal 时,将焦点移至上一个 AccordionTrigger
Home
当焦点位于 AccordionTrigger 上时,将焦点移至第一个 AccordionTrigger
End
当焦点位于 AccordionTrigger 上时,将焦点移至最后一个 AccordionTrigger