容器
Table
一张数据表——对齐、排序、边框都可以按列配置。
什么时候用它
示例
default
| Commit | Branch | State | |
|---|---|---|---|
| a1b2c3d | main | 2m 14s | passed |
| 9f8e7d6 | codex/ui-library | 2m 41s | passed |
| 4c5b6a7 | codex/photo-cache | 1m 02s | failed |
| 77aa2b1 | main | 2m 20s | passed |
borders
rows — the default — read down a column
| Region | Orders | Revenue |
|---|---|---|
| Australia | 1,204 | $48,210 |
| Japan | 862 | $31,940 |
grid — dense numbers, columns kept apart
| Region | Orders | Revenue |
|---|---|---|
| Australia | 1,204 | $48,210 |
| Japan | 862 | $31,940 |
bordered — loose on a page, not inside a card
| Region | Orders | Revenue |
|---|---|---|
| Australia | 1,204 | $48,210 |
| Japan | 862 | $31,940 |
bordered-grid — both
| Region | Orders | Revenue |
|---|---|---|
| Australia | 1,204 | $48,210 |
| Japan | 862 | $31,940 |
说明
一张有线的数据表。
包在它自己的横向滚动容器里,因为表格是唯一一种正当地超出版心的块——整页横向滚动是布局 bug,而表格横向滚动就是表格。
那个容器是可聚焦的,而且必须如此。一个内容本身不可聚焦的滚动区域,键盘是够不着的:没有元素可以 Tab 过去,也就没法对它按方向键,于是对不用鼠标的人来说,折线之外的那些列压根不存在。
任何边框设置下都没有斑马纹。在单色系统里,一条带底色的行是在和页面底色竞争的第二块表面,而行与行之间的细线已经足够让人横着追一行了。
属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| caption必填 | string | 为读屏软件描述这张表,它看不见上面那个标题。渲染成一个视觉隐藏的 `<caption>`——必填,因为一个有三张表的页面里,没有名字的那张是没法导航的。 | |
| borders | TableBorders | 'rows' | 画哪些线。见 。 |
| density | 'comfortable' | 'compact' | 'comfortable' | 收紧行内边距,用于以数字为主的表格。 |
| showCaption | boolean | false | 把标题打印出来,而不是隐藏它。 |
| stickyHeader | boolean | false | 表体滚动时把表头钉住。需要容器有一个确定的高度——否则滚的是页面而不是表格,什么也钉不住。 |
同时接受 TableHTMLAttributes<HTMLTableElement> 里的全部属性,它们会直接透传给底层元素,不再逐条列出。
组成部分
Composed at the call site rather than configured through props, so a layout this component did not anticipate is still expressible.
THead
表头分组。它下面那条线由表格的边框设置决定。
这个组件没有自己的属性。
TBody
这个组件没有自己的属性。
TR
这个组件没有自己的属性。
TH
一个列标签。等宽而且大写,所以它绝不会被读成数据。
可排序时,成为 <button> 的是 <th> 里面的那个标签,而不是让 <th> 自己可点:一个挂了点击处理器的单元格既不可聚焦,也不会被播报成控件,于是这个排序只对鼠标存在。
排序是按列的,而且要显式开启。一个每个表头都是按钮的表格,是在邀请读者去排一列数据根本没法排序的东西。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| align | TableAlign | 'start' | 这一列的内容靠哪一边。数字属于 `end`。 |
| onSort | () => void | — | |
| sortable | boolean | false | 把标签变成按钮,并显示排序标记。 |
| sortDirection | SortDirection | 'none' | 这一列按哪个方向排。同时设为 `aria-sort`,那是读屏软件得知“这张表是排过序的”的唯一途径——表头里画一个小三角对它什么都没说。 |
同时接受 Omit<ThHTMLAttributes<HTMLTableCellElement>, 'align'> 里的全部属性,它们会直接透传给底层元素,不再逐条列出。
TD
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| align | TableAlign | 'start' | 这个单元格的内容靠哪一边。和该列的表头保持一致。 |
同时接受 Omit<TdHTMLAttributes<HTMLTableCellElement>, 'align'> 里的全部属性,它们会直接透传给底层元素,不再逐条列出。
类型
export type TableAlign = 'start' | 'center' | 'end'
export type TableBorders = 'rows' | 'grid' | 'bordered' | 'bordered-grid' | 'none'
export type SortDirection = 'ascending' | 'descending' | 'none'键盘操作
| 按键 | 作用 |
|---|---|
| Tab | 走到滚动区域,以及每一个可排序的表头。 |
| ←→ | 区域拿到焦点后,横向滚动表格。 |
无障碍
- 可排序的表头是 th 里面的 button,而不是给单元格挂 onClick——带 onClick 的单元格既不可聚焦也不会被播报,那个排序就只对鼠标存在。
- aria-sort 由 sortDirection 设置,这是读屏用户得知这张表已被排序的唯一途径。
- 任何边框设置下都没有斑马纹:在单色系统里,一条被染色的行是又一个和页面底色抢注意力的表面。
- caption 必填:一个页面上三张表,其中没有名字的那张是没法导航的。
- 列标题是 <th scope="col">,所以一个单元格能被追溯回它的表头。