跳到正文
册页

表单

Checkbox - 复选框

一个在表单提交时才生效的选择。

用法

什么时候用它

立刻生效的开关是 Switch。
TSX
import { Checkbox } from '@misoto22/folio'

说明

一个在表单提交时才生效的选择。

支持不确定状态(checked="indeterminate"),这正是“全选”表头在只选中了部分行时需要的——那里放一个普通的未勾选框,是在告诉读者与事实相反的话。

受控非受控都行:字形跟着这个框实际所处的状态走,所以非受控的 defaultChecked="indeterminate" 画出来的是那道横杠,而不是那个说反话的对勾。

和 Field 搭配使用,或者在调用处用 <label> 包住它,让旁边的文字也成为点击目标的一部分。

结构

Checkbox anatomy
部件说明
方框必填一个 18px 的 <button role="checkbox">,圆角取 --radius-xs。勾选和不确定它都填 --accent,所以这块填充说的是「不是关」,而不是「开」。
勾那个勾形字符,aria-hidden——Radix 负责显示这个指示符,状态由 role 承担。
横杠顶替勾的那个减号,按方框实际所处的状态来挑——受控与否都一样,所以 defaultChecked="indeterminate" 画出来的是它承诺过的那根横杠,而不是一个勾。
标签这里不渲染。和 RadioGroupItem 不同,没有任何东西把这个方框包进 <label>,所以旁边那几个字、以及它们带来的那块点击区域,都是调用处的事。

实践建议

推荐

  • 把它和它的文字一起包进 <label>,或者放进 Field:这个控件自己不渲染标签,所以一个光秃秃的 Checkbox 没有无障碍名称,而那 18px 的方框就是全部的点击区域。
  • 不确定态的方框要托在受控状态上。它报告的是别的那些行的情况,而点它一下拿回来的是 true——一个自己保管答案的「全选」表头,从第一次被点击起就不再描述它底下那份列表了。
  • 默认值要在服务端定。没勾的方框在表单提交里根本不发送任何条目,所以读者特意清掉的字段,和一个压根没渲染过的字段,到达时一模一样,都是 undefined。

避免

  • 只给 checked 不给 onCheckedChange,得到的是一个永远不动的方框:Radix 把这个属性当作唯一的事实来源,于是读者点着一个既没坏也没在工作的控件,两边都得不到任何回应。
  • Radix 的 checkbox 上没有 readOnly。disabled 是唯一的锁,而它会把方框从 Tab 顺序里、也从表单里丢出去,所以一个必须展示但不许改动的值,画成文字更好。
  • 不要把不确定态放在叶子节点上。它的意思是「它底下的一部分」,所以一个底下什么都没有、却画着横杠的方框,报告的是一个它自己的值根本承载不了的状态。

示例

default

一个「全选」表头,管着它所概括的那些行。选中了一部分、又不是全部,就是 indeterminate 状态,而它必须通过受控的 checked 传进来:那个字形是从 props.checked 挑出来的,所以一个非受控的框永远画不出那道横杠,报出来的还正好是事实的反面。这个状态的意思是「它下面的东西里有一些」,所以它只属于表头——一个叶子节点画出横杠,是在宣称一个它自己的值根本承载不了的状态。注意那些文字:控件自己一个字都不渲染,所以那些词、以及它们给出的点击区域,是调用处的活儿。

with descriptions

框、名字,以及那句说明「答应下来到底要付什么代价」的话——三样都在 label 里面,于是整行都是点击目标,而不是一个 18px 的方块,而且那句话是无障碍名称的一部分。这既是把细节放进去而不是摆在旁边的理由,也是把它压到一个从句以内的理由:每次读到这一行,它都会被念出来。各行按第一行文字对齐,因为一个对着两行文字居中的框,会从它所属的那个词旁边飘走。这些是表单保存时才生效的;当场就生效的设置是 Switch。

inside a form

一个提交出去的表单真正携带的东西。没勾的框根本不发送任何条目——不是 false,是什么都没有——所以一个读者特意清掉的字段,和一个压根没渲染过的字段,到了服务端一模一样,默认值只能在那边定,不能从载荷里推。把两个都取消勾选再保存,看着那两个键消失。每个框都得有 name 才发得出东西;value 是它开着的时候发送的内容。

键盘操作

Checkbox keyboard interactions
按键作用
Space切换勾选状态。

无障碍

  • 支持不确定态,这正是“全选”表头在只选了一部分时需要的——普通的未勾选状态在那里表达的是相反的意思。