Tabs
一组分层的内容部分(称为选项卡面板),一次显示一个。
<script setup lang="ts">
import { TabsContent, TabsIndicator, TabsList, TabsRoot, TabsTrigger } from 'reka-ui'
</script>
<template>
<TabsRoot
class="flex flex-col w-full sm:w-[300px] shadow-sm rounded-lg border"
default-value="tab1"
>
<TabsList
class="relative shrink-0 flex border-b border-mauve6"
aria-label="Manage your account"
>
<TabsIndicator class="absolute px-8 left-0 h-[2px] bottom-0 w-[--reka-tabs-indicator-size] translate-x-[--reka-tabs-indicator-position] translate-y-[1px] rounded-full transition-[width,transform] duration-300">
<div class="bg-green-500 w-full h-full" />
</TabsIndicator>
<TabsTrigger
class="bg-white px-5 h-[45px] flex-1 flex items-center justify-center text-sm leading-none text-mauve11 select-none rounded-tl-md hover:text-green-900 data-[state=active]:text-green-900 outline-none cursor-default focus-visible:relative focus-visible:shadow-[0_0_0_2px] focus-visible:shadow-black"
value="tab1"
>
Account
</TabsTrigger>
<TabsTrigger
class="bg-white px-5 h-[45px] flex-1 flex items-center justify-center text-sm leading-none text-mauve11 select-none rounded-tr-md hover:text-green-900 data-[state=active]:text-green-900 outline-none cursor-default focus-visible:relative focus-visible:shadow-[0_0_0_2px] focus-visible:shadow-black"
value="tab2"
>
Password
</TabsTrigger>
</TabsList>
<TabsContent
class="grow p-5 bg-white rounded-b-md outline-none focus:shadow-[0_0_0_2px] focus:shadow-black"
value="tab1"
>
<p class="mb-5 !mt-0 text-mauve11 text-sm !leading-normal">
Make changes to your account here. Click save when you're done.
</p>
<fieldset class="mb-[15px] w-full flex flex-col justify-start">
<label
class="text-xs leading-none mb-2.5 text-green12 block"
for="name"
> Name </label>
<input
id="name"
class="bg-stone-50 grow shrink-0 rounded-md px-2.5 text-sm leading-none text-grass11 shadow-[0_0_0_1px] shadow-green7 h-[35px] focus:shadow-[0_0_0_2px] focus:shadow-green8 outline-none"
value="Pedro Duarte"
>
</fieldset>
<fieldset class="mb-[15px] w-full flex flex-col justify-start">
<label
class="text-xs leading-none mb-2.5 text-green12 block"
for="username"
> Username </label>
<input
id="username"
class="bg-stone-50 grow shrink-0 rounded-md px-2.5 text-sm leading-none text-grass11 shadow-[0_0_0_1px] shadow-green7 h-[35px] focus:shadow-[0_0_0_2px] focus:shadow-green8 outline-none"
value="@peduarte"
>
</fieldset>
<div class="flex justify-end mt-5">
<button
class="inline-flex items-center justify-center rounded-md px-[15px] text-sm leading-none font-medium h-[35px] bg-green-400 text-green-900 hover:bg-green-500 focus:shadow-[0_0_0_2px] focus:shadow-green-700 outline-none cursor-default"
>
Save changes
</button>
</div>
</TabsContent>
<TabsContent
class="grow p-5 bg-white rounded-b-md outline-none focus:shadow-[0_0_0_2px] focus:shadow-black"
value="tab2"
>
<p class="mb-5 !mt-0 text-mauve11 text-sm !leading-normal">
Change your password here. After saving, you'll be logged out.
</p>
<fieldset class="mb-[15px] w-full flex flex-col justify-start">
<label
class="text-xs leading-none mb-2.5 text-green12 block"
for="currentPassword"
>
Current password
</label>
<input
id="currentPassword"
class="bg-stone-50 grow shrink-0 rounded-md px-2.5 text-sm leading-none text-grass11 shadow-[0_0_0_1px] shadow-green7 h-[35px] focus:shadow-[0_0_0_2px] focus:shadow-green8 outline-none"
type="password"
>
</fieldset>
<fieldset class="mb-[15px] w-full flex flex-col justify-start">
<label
class="text-xs leading-none mb-2.5 text-green12 block"
for="newPassword"
> New password </label>
<input
id="newPassword"
class="bg-stone-50 grow shrink-0 rounded-md px-2.5 text-sm leading-none text-grass11 shadow-[0_0_0_1px] shadow-green7 h-[35px] focus:shadow-[0_0_0_2px] focus:shadow-green8 outline-none"
type="password"
>
</fieldset>
<fieldset class="mb-[15px] w-full flex flex-col justify-start">
<label
class="text-xs leading-none mb-2.5 text-green12 block"
for="confirmPassword"
>
Confirm password
</label>
<input
id="confirmPassword"
class="bg-stone-50 grow shrink-0 rounded-md px-2.5 text-sm leading-none text-grass11 shadow-[0_0_0_1px] shadow-green7 h-[35px] focus:shadow-[0_0_0_2px] focus:shadow-green8 outline-none"
type="password"
>
</fieldset>
<div class="flex justify-end mt-5">
<button
class="inline-flex items-center justify-center rounded-md px-[15px] text-sm leading-none font-medium h-[35px] bg-green4 text-green11 hover:bg-green5 focus:shadow-[0_0_0_2px] focus:shadow-green7 outline-none cursor-default"
>
Change password
</button>
</div>
</TabsContent>
</TabsRoot>
</template>
功能特点
- 可控或不可控。
- 支持水平/垂直方向。
- 支持自动/手动激活。
- 完整的键盘导航。
安装
从命令行安装组件。
$ npm add reka-ui
$ pnpm add reka-ui
$ yarn add reka-ui
$ bun add reka-ui
结构
导入所有部分并将其组合在一起。
<script setup>
import { TabsContent, TabsIndicator, TabsList, TabsRoot, TabsTrigger } from 'reka-ui'
</script>
<template>
<TabsRoot>
<TabsList>
<TabsIndicator />
<TabsTrigger />
</TabsList>
<TabsContent />
</TabsRoot>
</template>
API 参考
Root
包含所有选项卡组件部分。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
activationMode | 'automatic' | 'automatic' | 'manual' | 选项卡是自动激活(聚焦时)还是手动激活(点击时)。 |
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
defaultValue | string | number | 选项卡首次渲染时应激活的值。当您不需要控制选项卡状态时使用。 | |
dir | 'ltr' | 'rtl' | 组合框(如果适用)的阅读方向。如果省略,则从 ConfigProvider 全局继承或假定为从左到右 (LTR) 阅读模式。 | |
modelValue | string | number | 要激活的选项卡的受控值。可以绑定为 v-model。 | |
orientation | 'horizontal' | 'vertical' | 'horizontal' | 选项卡的布局方向。主要用于相应地进行箭头导航(左右 vs. 上下)。 |
unmountOnHide | true | boolean | 当为 true 时,元素将在关闭状态时卸载。 |
触发事件 (Emit)
| 事件名称 | Payload | 描述 |
|---|---|---|
update:modelValue | [payload: StringOrNumber] | 值更改时调用的事件处理程序。 |
默认插槽
| 插槽参数 | 插槽参数类型 | 描述 |
|---|---|---|
modelValue | string | number | 当前输入值 |
数据属性
| 属性 | 值 |
|---|---|
[data-orientation] | "vertical" | "horizontal" |
List
包含与活动内容边缘对齐的触发器。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
loop | true | boolean | 当为 true 时,键盘导航将从最后一个选项卡循环到第一个选项卡,反之亦然。 |
数据属性
| 属性 | 值 |
|---|---|
[data-orientation] | "vertical" | "horizontal" |
Trigger
激活其关联内容的按钮。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'button' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
disabled | false | boolean | 当为 true 时,阻止用户与选项卡交互。 |
value* | string | number | 将触发器与内容关联的唯一值。 |
数据属性
| 属性 | 值 |
|---|---|
[data-state] | "active" | "inactive" |
[data-disabled] | 禁用时存在 |
[data-orientation] | "vertical" | "horizontal" |
Indicator
突出显示当前活动选项卡的指示器。
| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
CSS 变量
| 变量 | 描述 |
|---|---|
--reka-tabs-indicator-size | 指示器的大小 |
--reka-tabs-indicator-position | 指示器的位置 |
Content
包含与每个触发器关联的内容。
使用
Presence 组件构建 - 支持任何[动画技术](animation techniques),同时保持对存在(presence)触发事件的访问。| 属性 | 默认值 | 类型 | 描述 |
|---|---|---|---|
as | 'div' | AsTag | Component | 此组件应渲染为的元素或组件。可以通过 asChild 覆盖。 |
asChild | false | boolean | 将默认渲染的元素更改为作为子元素传递的元素,合并它们的 props 和行为。有关详细信息,请阅读我们的组合指南。 |
forceMount | false | boolean | 当需要更多控制时,用于强制挂载。在与 Vue 动画库控制动画时很有用。 |
value* | string | number | 将内容与触发器关联的唯一值。 |
数据属性
| 属性 | 值 |
|---|---|
[data-state] | "active" | "inactive" |
[data-orientation] | "vertical" | "horizontal" |
示例
垂直
您可以使用 orientation prop 创建垂直选项卡。
<script setup>
import { TabsContent, TabsList, TabsRoot, TabsTrigger } from 'reka-ui'
</script>
<template>
<TabsRoot
default-value="tab1"
orientation="vertical"
>
<TabsList aria-label="tabs example">
<TabsTrigger value="tab1">
One
</TabsTrigger>
<TabsTrigger value="tab2">
Two
</TabsTrigger>
<TabsTrigger value="tab3">
Three
</TabsTrigger>
</TabsList>
<TabsContent value="tab1">
Tab one content
</TabsContent>
<TabsContent value="tab2">
Tab two content
</TabsContent>
<TabsContent value="tab3">
Tab three content
</TabsContent>
</TabsRoot>
</template>
可访问性
键盘交互
| 按键 | 描述 |
|---|---|
Tab | 当焦点移动到选项卡时,聚焦活动触发器。当触发器聚焦时,将焦点移动到活动内容。 |
ArrowDown | 根据 orientation 将焦点移动到下一个触发器并激活其关联内容。 |
ArrowRight | 根据 orientation 将焦点移动到下一个触发器并激活其关联内容。 |
ArrowUp | 根据 orientation 将焦点移动到上一个触发器并激活其关联内容。 |
ArrowLeft | 根据 orientation 将焦点移动到上一个触发器并激活其关联内容。 |
Home | 将焦点移动到第一个触发器并激活其关联内容。 |
End | 将焦点移动到最后一个触发器并激活其关联内容。 |