反馈
Spinner - 加载环
系统唯一的“正在处理”指示——一个环,永远不是流光。
用法
什么时候用它
import { Spinner } from '@misoto22/folio'说明
这套系统唯一的“正在处理”指示。
一个圆环,不是模糊的光晕,也不是流光:归白没有光源,所以深度和柔化这两样它都用不了。领先的那四分之一是唯一让这个环区别于一个普通圆圈的东西,这也是为什么轨道保持细线——spinner 是“时间在过去”的提示,不是页面的一个功能。
它只在 motion-safe 下转。一个要求减少动效的读者拿到的是静止的环,而它依然读作“还没完”,因为领先那四分之一比轨道更深。
当等待长到读者会开始怀疑页面是不是坏了的时候,优先用 Skeleton——一个描述“将要出现什么”的形状,胜过一个什么都不描述的点。
className 到的是那个环,和 size、tone 落在一起,并且盖过它们:调用方为一个 spinner 准备的每一个工具类说的都是那个环,而合并到外层包装上时,className="size-8" 长出来的是一个围着那个 18px 圆圈、圆圈本身纹丝不动的隐形盒子。布局照样从这里生效——包装层是 inline-flex,把环的外边距盒当成自己的。
结构
| 部件 | 说明 |
|---|---|
| 播报区域必填 | 外层那个 span,也是整个组件唯一有声音的部分。只要有 label,它就带着 role="status";传 label={null},它就变成一个没有任何 role 的 aria-hidden 盒子。 |
| 环必填 | 里层那个 span——一个透明盒子上 14px、18px 或 26px 的边框,也是 size、tone 和 className 唯一够得到的元素。 |
| 领头的四分之一必填 | border-t:默认 tone 下用 --ink 画,current 下用继承来的颜色画。一个环和一个普通圆圈的差别全在这里——这也是为什么静止的环照样读作「还没完」。 |
| 读屏标签 | 一个装着 label 的 sr-only span,除非 label 是 null,否则一直在。它在 spinner 挂载时播报一次,之后再也不播。 |
实践建议
推荐
- 放在任何实色底上的 spinner 都要传 tone="current":默认是在 --rule-2 的轨道上用 --ink 画那四分之一,而在 primary Button 里,这两个颜色正是它所站的底色。
- 到货这件事要在别处播报。label 只在挂载时念一次,卸载时什么都不说,所以听到「正在加载项目」的读者,永远不会被告知项目已经到了。
- 只在本身已经说明了这个操作的控件里用 label={null}——它是把整个元素对辅助技术隐藏,而不只是去掉那行字,所以一个被静音、又孤零零站着的 spinner,是一场没有人被告知的等待。
避免
- label 的默认值就是光秃秃一个「Loading」,所以不写这个属性的 Spinner,交付的正是这个属性本来要避免的那句播报——那个默认值是占位,不是取值。
- className 是在 size 和 tone 之后才合并到环上的,所以它把两个都盖掉:<Spinner size="lg" className="size-4" /> 画出来是一个 16px 的环,而那个本职就是指定尺寸的属性,成了输掉的那一个。
- 这里没有任何东西会设置 aria-busy——Button 只为它自己的控件设——所以盖在面板上的 spinner,会让那个面板被播报成已就绪,而它的内容还是旧的、按钮还照单全收点击。
示例
sizes
三个圆环——14px、18px、26px——是对着它们旁边的字号配的,不是为了强调挑出来的。size 是唯一能改它大小的东西:className 落在外层容器上,所以那样传一个尺寸工具类,只会在一个没变过的圆环外面撑出一个空盒子。label 默认是光秃秃的一个「Loading」,而那恰恰是这个属性存在要防住的播报——把具体在等什么写出来,因为三个都说着「Loading」的转圈,对读屏软件而言什么都没说,而且每一个只在挂载时被读一次,此后再不会读。
on a filled ground
两个转圈,站在一块不是纸色的底上。默认的 tone 会在一条 --rule-2 的轨道上,用 --ink 画出领头那四分之一,而在一个有填充的控件里,这两个颜色都正是它所站的那块底——所以传 tone current,让圆环去继承文字颜色。label 传 null 恰恰属于这个场景:控件本身已经把这个操作命名了,而传它会把整个元素对辅助技术隐藏起来,不只是把文字去掉,所以一个被消了音、又独自站着的转圈,是一次没人被告知的等待。
which wait shape
三种等待、三种形状,以及每一种回答的问题。Spinner 是给那种没人知道要多久、结果也没有值得预告的形状的等待用的。Skeleton 是给形状已知的等待用的——它把布局占住,好让记录落下来时页面不跳。Progress 是给有真实分数的等待用的,而且只给真实的那种:一条按编出来的估计填的进度条,是一个会撒谎的转圈。三种情况一律拿转圈,是常见的失败,而它恰恰是三者里说得最少的那一个。
Unknown duration
Checking the deployKnown shape
Known fraction
无障碍
- label 要写明在等什么;三个都写“Loading”的转圈对读屏用户等于什么都没说。
- label={null} 让它闭嘴,用在本身已经会播报操作的控件里。
- 只在 motion-safe 下旋转;静止时前四分之一仍然更深,所以照样读作“还没完”。