表单
NumberField 数字输入框
一个数字,打出来的,或者扫出来的。
用法
什么时候用它
import { NumberField } from '@misoto22/design'说明
一个数字,打出来的,或者扫出来的。
Input 加 type="number",是一个恰好不收字母的框。这一个是给有范围、也有一个合理步长的数字用的控件:方向键按步长走,那个把手一扫就过去,而 min、max 和 step 是在值出去的路上被真正兑现的,不是只被播报一下。
当值在范围里的位置才是信息时,改用 Slider——音量、把握程度,任何一个读者靠滑块停在哪儿来判断的东西。当那几位数字才是信息时,用这一个。一个还得精确的滑块,是带 editable 的 Slider,不是在它旁边再摆一个这个。
夹取发生在离开这个框的时候,不是在打字的过程中。否则一个 10 的下限会让 50 永远够不着:5 会在 0 到达之前先被顶到 10。所以 onValueChange 在敲键的中途可以报出一个越界的数字,而最终落定的那个值,永远在范围之内。
原生的上下按钮被藏了——三个浏览器里是三种不同的控件,没有一个属于这套系统。指针那一边由把手接手;键盘那一边,答案从来都是方向键。
结构
| 部件 | 说明 |
|---|---|
| 输入框必填 | 一个穿着 CONTROL_BASE 的原生 number 输入框,所以它和 Input、Textarea、Select 是同一个盒子——一样的内边距、一样的聚焦、一样的禁用透明度。原生的上下按钮被藏了:三个浏览器里是三种不同的控件,没有一个属于这套系统。 |
| 扫动把手 | 行首的一个左右箭头图形,除非 scrub 为 false,否则一直在。拖它,每 4px 改变一个步长,按住 Shift 一次十步,而且它跟着阅读方向走——在 RTL 页面里,往左是变大。只给指针用,并且是 aria-hidden,因为键盘早就有方向键了。 |
| 单位 | unit,画在框尾内侧,并经由 aria-describedby 播报。这个槽位固定 3rem,所以一个超过四个字符左右的单位,会被一个长数字压到下面。 |
实践建议
推荐
- 当一个值是被调出来、而不是被填进去的时候用它——一段时长、一个行高、一个偏移。那个把手就是它胜过 Input 的全部理由:读者是靠从邻近的值上扫过去找到这些的,不是靠一个一个把候选值打进去。
- 把它套在 Field 里。根节点是一个 div,而 id 会落到里面那个 input 上,所以标签绑得住、也点得进去,和 Input 一模一样——但前提是有一个 Field 来做这件事。
- 要传 min、max 和 step。它们是方向键一步的分量、扫动一格的分量,也是离开这个框时值被对齐的依据;不传的话,这个控件就是一个带把手的 Input。
避免
- 不要指望范围在敲键的中途就成立。夹取发生在失焦时,不是每个字符一次,因为一个 10 的下限否则会让 50 永远够不着——5 会在 0 到达之前先被顶上去。onValueChange 可以报出一个越界的数字;而落定的那个值,永远在范围之内。
- 不要一边关掉把手,一边指望指针还有别的路。它背后没有上下按钮——藏掉它们正是重点——所以 scrub={false} 留给鼠标的只剩打字。要关就为一个被选定、而不是被扫出来的数量而关,并且清楚这笔交换。
- 超过四个字符左右的单位,不要只塞在框里。那个槽位是固定的,所以「requests」会被数字压到下面;一个长单位属于 Field 的标签,在那儿它是被读到的,而不是被裁掉的。
示例
default
每个框首那个把手,就是它值得取代 Input 的理由:拖着它,值会从邻近的值上扫过去,每几个像素一步,按住 Shift 一次十步。一个行高、一个圆角,本来就是这么找到的——从一堆不对的答案里穿过去,直到有一个看着对了,而不是一个一个把候选值打进去。方向键在键盘上走的是同一段路,这也是那个把手不被播报的原因。
Between 1 and 3.
clamping on the way out
范围是在离开这个框的时候生效的,不是每敲一下就生效一次。只能这样:下限是 10 时,边打边夹会让 50 永远够不着——5 会在 0 到达之前先被顶到 10。所以只要有人还在一个数字的中途,下面那个实时数字就可以待在范围之外,而最终落定的那个值从不会。打一个 4,然后 Tab 出去看看。
Between 10 and 100.
Reported: 30
键盘操作
| 按键 | 作用 |
|---|---|
| ↑↓ | 按一个步长走,并遵守 min 和 max。 |
| Enter | 把已经打进去的内容与范围和步长对齐。 |
| Escape | 放弃这次编辑,恢复到上一个落定的值。 |
无障碍
- 它是一个真的 <input type="number">,所以 spinbutton 这个 role、当前值、以及播报时对照的那个范围,都由平台提供。
- unit 会经由 aria-describedby 抵达辅助技术,所以「300」不会被播报成一个没有量纲的数字。
- 那个把手是 aria-hidden 的,也不可聚焦:它做不到任何键盘够不着的事,而把它播报出来,等于递给读者一个按下去什么都不会发生的控件。
- invalid 和 aria-invalid 是一起读的,所以表单库设了其中任何一个,画出来的都是同一种边框。