跳到正文
册页

表单

Slider - 滑块

在一段范围里选一个值。

用法

TSX
import { Slider } from '@misoto22/folio'

说明

在一段范围里选一个值。

键盘契约归 Radix——方向键走一步,Page 键跳一大步,Home 和 End 到两端——报告值的那套 ARIA 也归它。留在这里的是外观,以及命名,而后者正是滑块最常做错的那一半:一个只报「42」、别的什么都不说的滑块,留给读屏用户的是一个数字,和不知道它在量什么。

16px 的滑块外面有一圈看不见的 44px 命中区,因为一个按设计尺寸做的滑块,远在任何指针目标准则之下。

editable 是滑块做不到的那件事的答案。只要确切的数字才是重点——预算、超时、价格——就打开它;而当这个值本来就是个大概时,把它关掉,因为一个框会招来这项设置未必具备的精度。

放在 Field 里时,hint、error 和必填标记落在滑块上,也就是带着 role="slider" 的那个元素——落在根节点上的话,它们会待在一个没有 role 的 <span> 上,什么都播报不出来。名字仍然来自这里的 label:Field 上方那个标签指的是同一个没有 role 的根节点,所以它既命名不了这个控件,也点不进去。

结构

Slider anatomy
部件说明
轨道必填一条 --stone 的 1px 细线;只要指针落在这个控件上的任何位置——不必落在滑块上——它就加粗到 1.5。
已选区间从最小值到滑块的那段 --accent 填充;范围滑块则是两个滑块之间的那一段。
滑块value 数组里每有一项就有一个——所以滑块的个数来自值,不来自某个属性;而一个既没给 value 也没给 defaultValue 的滑块,会退回原语自己的默认:一个停在最小值上的滑块。每一个都是 16px 的圆,外面有一圈由 before 伪元素撑出来的、看不见的 44px 命中区。
数值行只有设了 showValue 才有:轨道上方一行等宽字,名字靠行首、格式化后的值靠行尾,各自用一个连接号连起来,顺序和滑块本身的顺序一致——所以一个两端的范围读出来是「Minimum – Maximum」压在「10 – 90」上面。
可编辑读数editable 会把那些数字变成这个:每个滑块一个框,静止时显示 format 的输出,拿到焦点时显示光秃秃的数字,所以读者看到的仍然是「$1,200」,而打字的人从不会被要求把货币符号也敲一遍。每个框都和它驱动的那个滑块分开命名——两个控件都播报成「Quality」,等于同一个控件被念了两遍。

实践建议

推荐

  • 只要它不止一端,就要传 defaultValue 或 value。滑块的个数来自那个数组,所以一个放任默认的价格筛选,是一个停在最小值上的单滑块。
  • 双滑块的范围要传两个名字的数组:第一个之后的每一个滑块都退回 names[0],否则价格筛选的两端都把自己播报成「最小值」。
  • 确切的数字要紧时,把 editable 打开。滑块自己没法打字,而一个要的是 37、不是「大概 40」的人,只能拖着 16px 的滑块在一百个步长里挪过去——读数里那个框就是出路,它顶替了这里过去要求的第二个 Input。

避免

  • format 会成为每个滑块的 aria-valuetext,而它是顶替那个数字,不是给它加装饰——所以一个把数字狠狠取整、或者把单位丢掉的格式化函数,就是读屏用户拿到的全部,值本身他拿不到。
  • editable 打进去的数字,除了受 min 和 max 约束,也受相邻那个滑块约束,而且只能这样:往一个上端停在 70 的区间的下端里打 90,否则两个滑块就交叉过去了。所以一个数字可以被接受、然后落在别处,而那个框显示的是它落在了哪儿。
  • 不要靠禁用一个滑块来让它只读:整个控件会变淡、不再接收指针,Radix 还会把滑块从 Tab 顺序里丢出去,于是那个值变成了够不着,而不是不可编辑。
  • 不要给单滑块传两个名字:那一行是每个滑块打印一个名字,所以第二个名字哪儿都没画出来,也哪儿都没播报出来。
  • Field 上方那个标签既命名不了它,也点不进去:role 长在滑块上,而根节点是一个 <span>,所以这里的 label 属性是读者唯一听得到的名字。hint 和 error 倒是抵达得了滑块。

示例

default

一个值,然后两个,都开着读数。永远要传 defaultValue 或 value:那些滑块是从这个组件自己的数组渲染出来的,不是从 Radix 的默认值,所以一个两个都没给的 Slider,画出来是一条轨道,上面没有任何可拖的东西。一个双滑块的区间需要两个 name——第一个之后的每个滑块都会退回用第一个名字,否则价格筛选的两端都会把自己播报成 Minimum。数字上方那个标题只印第一个名字,所以要把它当成这一对的开头来读,而不是两个的标签。

Quality80%
Minimum price – Maximum price$20 – $70

typing the exact value

滑块是一个管大致区间的控件,而这是它的出路。一个要的是 1,150 而不是「大概 1,200」的人,以前只能把 16px 的滑块横着拖过一百个刻度,或者在轨道旁边被塞第二个输入框、然后靠手工把两边同步住;editable 把那个框开在数字本来就在的地方。它静止时显示 format 的输出,拿到焦点时显示光秃秃的数字,所以读者看到的仍然是 $1,200,而打字的人从不会被要求把货币符号也敲一遍。区间上每一端各有自己的框,而且各自被对方兜住——往一个上端停在 70 的区间的下端里打 90,落点是 70,因为两个滑块过不去对方。

Monthly budget
Minimum price – Maximum price

naming the unit

format 只管印,别的什么都不干:它渲染轨道上方那个读数,而这里没有任何东西设置 aria-valuetext,所以一个显示 12s 的滑块,播报出来是光秃秃的 12。单位属于名字,因为名字是会被播报的——「请求超时秒数」和 12 一起读出来是一个事实,而「超时」和 12 一起读出来是一个谜语。第二个滑块完全没有 format,一个普通计数就该长这样。

Request timeout in seconds12s
Retries before giving up3

键盘操作

Slider keyboard interactions
按键作用
←→移动一个步长。
Page UpPage Down移动一个更大的步长。
HomeEnd跳到最小值或最大值。

无障碍

  • label 必填。一个只报“42”的滑块,给读屏用户留下一个数字和不知道它在量什么。
  • 16px 的滑块外面有一个看不见的 44px 命中区。
  • format 会作为 aria-valuetext 播报,所以一个显示着「$1,200」的滑块,念出来就是这个,而不是 1200。
  • 方向键走一步,Page 键走一大步,Home 和 End 到两端。