导航
Tabs - 标签页
一条,若干面板。
用法
import { Tabs } from '@misoto22/folio'说明
无障碍标签页,配有滑动选中标记,并支持可选的横向拖拽手势。
结构
| 部件 | 说明 |
|---|---|
| 根节点必填 | Tabs——Radix 的根节点,原样再导出。它什么都不画,却拥有一切:value 或 defaultValue,以及 activationMode。value 和 defaultValue 都不给,就没有任何标签被选中,也没有任何面板被挂载。 |
| 标签条必填 | TabsList——那一行 role="tablist",坐在一条发丝线上,用 scroll-slim 在自己这条轴上滚动。你不给,它就没有无障碍名称。 |
| 标签必填 | TabsTrigger,md 控件高度,标签文字只占一行。每个标签都带着那道 2px 的选中记号,在它成为选中项之前是透明的;这道记号用 -mb-px 拉到标签条自己的边框上,所以两者共用一条线,而不是叠成一道 3px 的边。 |
| 面板 | TabsContent,靠 value 相等和它的标签配对。只有在它是选中项时才挂载,并且标了 data-folio-animated,所以对要求少一点动效的读者,它的入场是被直接去掉的。 |
实践建议
推荐
- 根节点要给 defaultValue 或 value:两个都不给,就什么都匹配不上,每个面板都不挂载,页面渲染出来是一条标签条加一片空白,没有任何东西说明缺了什么。
- 每个触发器的 value 要和某个面板的 value 完全一致——配对靠的是字符串相等,所以打错一个字不会报错,只会得到一个点开什么都没有的标签。
- 面板要发请求、或者要渲染很贵的东西时,传 activationMode="manual":默认是 automatic,← 和 → 一边移动一边选中,横着划过四个标签,就在读者停下之前起了四次加载。
- 一个页面上不止一组标签页时,给 TabsList 一个 aria-label:Radix 不会拿任何东西给这个 tablist 命名,而两个没有名字的 tablist,就是读者分不出彼此的两个「tab list」。
避免
- 没被选中的面板是被卸载,不是被隐藏——页内查找够不到它的文字,打印只会带上当时打开的那一个,而另一个标签里填了一半的表单,等读者回来时,打进去的东西已经没了。
- 当前选中的标签活在 React state 里,不在 URL 里:刷新或者把页面分享出去的读者,落到的是第一个面板——所以任何值得被链接的东西,都得把 value 提到一个查询参数里。
- 标签页不是用来多塞东西的:那条标签条是无声滚动的,而折线之外的第六个标签,看起来和一个只有五个标签的页面一模一样。
示例
default
一条标签条、三块面板,靠字符串相等配对——value 里一个拼写错误不会报错,只会得到一个打开后什么都没有的标签页。给根节点一个 defaultValue 或 value:两个都不给,就什么都匹配不上,每块面板都不挂载,页面渲染出来是一条标签条上面顶着一片空白,且没有任何东西说明缺了什么。整条标签条是一个 tab 停靠点;左右键在标签之间移动,Home 和 End 跳到两端。被选中的标签活在 React 状态里、不在 URL 里,所以任何值得被链接到的东西,都需要把 value 提升到一个查询参数里。
manual activation
activationMode 用 manual,配一条有名字的标签条。默认是 automatic,于是方向键一边移动一边选中,用方向键横着扫过四个标签,会在读者还没停下之前就发起四次加载——manual 会等 Enter 或空格,而那正是一块要取数、或者要渲染点昂贵东西的面板所需要的。TabsList 默认不叫任何名字,所以一个带着不止一组标签的页面要给每一组一个 aria-label:两个没名字的标签列表,是两个读者无从选择的标签列表。
18,402 visits over the last 30 days, up 6% on the month before.
what gets hidden
把同一句话藏起来的三种方式,以及三种方式共同的后果:被关起来的东西是被卸载的、不是被隐藏的,所以页内查找够不着它,打印只会拿到碰巧开着的那部分,而且三者都不会把当前打开的那个写进 URL。按读者在做什么来选。Tabs 是同一个主题下互斥的几个视图,代价是读者在离开的那块面板里输入过的一切。Accordion 是一组可以互相协同的东西——type 用 multiple 能让两行相互对照着读,而且每一行都往大纲里加一个 h3。Collapsible 是单独一次展开,没有谁可以协同,它也完全不添加标题。任何必须可搜索、可打印的东西,都属于页面本身,敞开着。
Tabs — one of several views
Billed at $18 a seat each month.
Accordion — a set of answers
Collapsible — detail on one thing
组成部分
在调用处组合,而不是通过 props 配置——所以这个组件没有预料到的布局,依然表达得出来。
TabsList
标签条。
横向滚动而不是折行。折出来的第二行标签,会在标签条变长时把它下面的每一个标签都推走,读者正要点的那个就没了。
这个组件没有自己的属性。
TabsTrigger
一个标签。
选中标记是一条 2px 的墨色线,用 -mb-px 拉到标签条自己的边框上,所以两者占同一条线,而不是叠成 3px 的边。高 44px,因为标签和别的东西一样是指针目标。
这个组件没有自己的属性。
TabsContent
通过 value 与某个 TabsTrigger 配对的面板。
这个组件没有自己的属性。
键盘操作
| 按键 | 作用 |
|---|---|
| Tab | 进入和离开标签条——整条只占一个 Tab 停靠点。 |
| ←→ | 在标签之间移动,面板跟着换。 |
| HomeEnd | 跳到第一个或最后一个标签。 |
无障碍
- 这条会横向滚动而不是折行:折到第二行会把下面每个标签都推走,读者刚要点的那个就没了。
- 高 44px,标签页也是指针目标。