Lzh on GitHub

Accordion

一组垂直堆叠的交互式标题,每个标题可展开或折叠其关联的内容区块。
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { AccordionContent, AccordionHeader, AccordionItem, AccordionRoot, AccordionTrigger } from 'reka-ui'

const accordionItems = [
  {
    value: 'item-1',
    title: 'Is it accessible?',
    content: 'Yes. It adheres to the WAI-ARIA design pattern.',
  },
  {
    value: 'item-2',
    title: 'Is it unstyled?',
    content: 'Yes. It\'s unstyled by default, giving you freedom over the look and feel.',
  },
  {
    value: 'item-3',
    title: 'Can it be animated?',
    content: 'Yes! You can use the transition prop to configure the animation.',
  },
]
</script>

<template>
  <AccordionRoot
    class="bg-mauve6 w-[300px] rounded-lg shadow-[0_2px_10px] shadow-black/5 border"
    default-value="item-1"
    type="single"
    :collapsible="true"
  >
    <template
      v-for="item in accordionItems"
      :key="item.value"
    >
      <AccordionItem
        class="focus-within:shadow-mauve12 mt-px overflow-hidden first:mt-0 first:rounded-t-[7px] last:rounded-b-[7px] focus-within:relative focus-within:z-10 focus-within:shadow-[0_0_0_2px]"
        :value="item.value"
      >
        <AccordionHeader class="flex">
          <AccordionTrigger class="text-grass11 shadow-mauve6 hover:bg-mauve2 flex h-[45px] flex-1 cursor-default items-center justify-between bg-white px-5 text-sm leading-none shadow-[0_1px_0] outline-none group">
            <span>{{ item.title }}</span>
            <Icon
              icon="radix-icons:chevron-down"
              class="text-green10 ease-[cubic-bezier(0.87,_0,_0.13,_1)] transition-transform duration-300 group-data-[state=open]:rotate-180"
              aria-label="Expand/Collapse"
            />
          </AccordionTrigger>
        </AccordionHeader>
        <AccordionContent class="text-mauve11 bg-mauve2 data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp overflow-hidden text-sm">
          <div class="px-5 py-4">
            {{ item.content }}
          </div>
        </AccordionContent>
      </AccordionItem>
    </template>
  </AccordionRoot>
</template>

特性

  • 完整的键盘导航。
  • 支持水平/垂直方向。
  • 支持从右到左方向。
  • 可以展开一个或多个项(item)。
  • 可以受控或不受控。

安装

从命令行安装组件。

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

包含 Accordion 的所有部分

Prop默认值类型说明
as'div'AsTag | Component此组件应渲染为的元素或组件。可以被 asChild 覆盖。
asChildboolean更改作为子元素传递的默认渲染元素,合并它们的 props 和行为。请阅读我们的 Composition 指南以了解更多详细信息。
collapsiblefalseboolean当类型为“single”时,允许在点击打开项目的触发器时关闭内容。当类型为“multiple”时,此属性无效。
defaultValuestring | string[]项目的默认值。当您不需要控制项目的状态时使用。
dir'ltr' | 'rtl'适用时折叠面板的阅读方向。如果省略,则假定采用 LTR(从左到右)阅读模式。
disabledfalseboolean如果为 true ,则阻止用户与 accordion 及其所有项目进行交互。
modelValuestring | string[]当你需要控制项目状态时使用。可以与 v-model 绑定。
orientation'vertical''vertical' | 'horizontal'手风琴的方向。
type'single' | 'multiple'确定是否可以一次选择“单个”还是“多个”项目。此 prop 将覆盖从 modelValue 和 defaultValue 推断出的类型。
unmountOnHidetrueboolean当为 true 时,元素将在关闭状态下卸载。

事件

事件名称Payload 类型说明
update:modelValue[value: string | string[]]当项目的展开状态发生改变时调用的事件处理程序

默认插槽

Slot 名称Payload 类型说明
modelValueAcceptableValue | AcceptableValue[] | undefined当前活跃值

数据属性

属性名称
[data-orientation]"vertical" | "horizontal"

Item

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

Prop默认值类型说明
as'div'AsTag | Component此组件应渲染为的元素或组件。可以被 asChild 覆盖。
asChildboolean更改作为子元素传递的默认渲染元素,合并它们的 props 和行为。请阅读我们的 Composition 指南以了解更多详细信息。
disabledboolean是否禁用折叠面板项目的用户交互。如果为 true ,则禁止用户与该项目交互。
unmountOnHideboolean当为 true 时,元素将在关闭状态下卸载。
value*string折叠面板项的字符串值。折叠面板内的所有项都应使用唯一值。

默认插槽

插槽参数插槽参数类型说明
openboolean当前打开状态

数据属性值

属性名称
[data-state]"open" | "closed"
[data-disabled]Present when disabled
[data-orientation]"vertical" | "horizontal"

包裹一个 AccordionTrigger。使用 asChild prop 将其更新为页面上适当的标题级别。

Prop默认值类型说明
as'h3'AsTag | Component此组件应渲染为的元素或组件。可以被 asChild 覆盖。
asChildboolean更改作为子元素传递的默认渲染元素,合并它们的 prop 和行为。请阅读我们的 Composition 指南以了解更多详细信息。

数据属性值

属性名称
[data-state]"open" | "closed"
[data-disabled]Present when disabled
[data-orientation]"vertical" | "horizontal"

Trigger

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

Prop默认值类型说明
as'div'AsTag | Component此组件应渲染为的元素或组件。可以被 asChild 覆盖。
asChildboolean更改作为子元素传递的默认渲染元素,合并它们的 prop 和行为。请阅读我们的 Composition 指南以了解更多详细信息。

数据属性值

属性名称
[data-state]"open" | "closed"
[data-disabled]Present when disabled
[data-orientation]"vertical" | "horizontal"

Content

包含项目的可折叠内容。

Prop默认值类型说明
as'div'AsTag | Component此组件应渲染为的元素或组件。可以被 asChild 覆盖。
asChildboolean更改作为子元素传递的默认渲染元素,合并它们的 prop 和行为。请阅读我们的 Composition 指南以了解更多详细信息。
forceMountboolean当需要更多控制时,用于强制挂载。在使用 Vue 动画库控制动画时非常有用。

数据属性值

属性名称
[data-state]"open" | "closed"
[data-disabled]Present when disabled
[data-orientation]"vertical" | "horizontal"

CSS 变量

变量名称描述
--reka-accordion-content-width内容打开/关闭时的宽度
--reka-accordion-content-height内容打开/关闭时的高度

示例

默认展开

使用 defaultValue prop 默认定义打开的项目。

<template>
  <AccordionRoot
    type="single"
    default-value="item-2" <!-- 默认打开项 -->
  >
    <AccordionItem value="item-1">
    </AccordionItem>
    <AccordionItem value="item-2">
    </AccordionItem>
  </AccordionRoot>
</template>

允许折叠所有项目

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

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

同时打开多个项目

type prop 设置为 multiple 以启用同时打开多个项目。

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

打开时旋转图标

您可以添加额外的装饰元素,例如人字形,并在项目打开时旋转它(通过动画实现)。

// 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>Trigger text</span>
          <Icon
            icon="radix-icons:chevron-down"
            class="AccordionChevron"
          />
        </AccordionTrigger>
      </AccordionHeader>
      <AccordionContent></AccordionContent>
    </AccordionItem>
  </AccordionRoot>
</template>

水平方向

使用 orientation prop 创建一个水平 Accordion。

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

即使在关闭时也渲染内容

默认情况下,隐藏内容将被移除,使用 :unmountOnHide="false" 来使内容始终可用。这将允许浏览器搜索隐藏文本并打开手风琴。

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

可访问性

遵循 Accordion WAI-ARIA 设计模式。

键盘交互

描述
Space当焦点在折叠部分的 AccordionTrigger 上时,展开该部分。
Enter当焦点在折叠部分的 AccordionTrigger 上时,展开该部分。
Tab将焦点移动到下一个可聚焦元素。
Shift + Tab将焦点移动到上一个可聚焦元素。
ArrowDownorientationvertical 时,将焦点移动到下一个 AccordionTrigger
ArrowUporientationvertical 时,将焦点移动到上一个 AccordionTrigger
ArrowRightorientationhorizontal 时,将焦点移动到下一个 AccordionTrigger
ArrowLeftorientationhorizontal 时,将焦点移动到上一个 AccordionTrigger
Home当焦点在 AccordionTrigger 上时,将焦点移动到起始 AccordionTrigger
End当焦点在 AccordionTrigger 上时,将焦点移动到最后一个 AccordionTrigger