チェックボックス
独立した 1 つの選択をオンまたはオフにします。一部だけがオンになった親の選択や、必須なのに選ばれていない選択も示せます。
- カテゴリ
- 選択
- トークン
comp.checkbox- レベル
- 基礎
- 使用先
- Checkbox group
- Web
tanrei-checkboxschedule - SwiftUI
TanreiCheckboxschedule - Jetpack Compose
TanreiCheckboxschedule - Flutter
TanreiCheckboxschedule - React Native
Checkboxschedule
生成元 docs/status/status.json, specs/checkbox.spec.json
未チェック、チェック、中間状態
チェックボックスに今の寸法とアイコンセットのグリフを取り入れた改訂で変わったのは見た目と動きだけなので、以下の例はどれも現在の仕様に沿っています。Web は仕様どおりに描き、動かします。SwiftUI、Compose、Flutter、React Native は追従待ちで、新しい寸法にはすでに従っていますが、追従するまではチェックと横線を独自の印で描き、独自の動きで切り替えます。その後の 2 つの調整は、いまのところ Web だけにあります。チェックと横線が印専用の太さで、ほかのアイコンより太く描かれること、ボックスの輪郭線と塗りが 1 つの形として描かれることです。
<tanrei-checkbox label="更新情報をメールで受け取る"></tanrei-checkbox>
<tanrei-checkbox checked label="更新情報をメールで受け取る"></tanrei-checkbox>
<!-- 子のチェックが混在している親です。操作するとチェックが入り、indeterminate は解除されます。 -->
<tanrei-checkbox indeterminate label="すべて選択"></tanrei-checkbox>
<!-- フォームの中では、チェックが入っている間 name で value(既定値は "on")を送信し、required にも従います。 -->
<form>
<tanrei-checkbox name="terms" required label="利用規約に同意する"></tanrei-checkbox>
</form>
<script type="module">
import '@tanrei/web/components/checkbox';
// 要素は change を発火する前に、自分の checked を切り替えます。
document.querySelector('tanrei-checkbox').addEventListener('change', (e) => save(e.detail.checked));
const terms = document.querySelector('[name="terms"]');
terms.error = submitted && !terms.checked;
</script>import { Checkbox } from '@tanrei/react';
<Checkbox checked={updates} label="更新情報をメールで受け取る" onChange={(e) => setUpdates(e.detail.checked)} />
<Checkbox checked={all} indeterminate={some && !all} label="すべて選択" onChange={(e) => selectAll(e.detail.checked)} />
<Checkbox checked={terms} error={submitted && !terms} label="利用規約に同意する" onChange={(e) => setTerms(e.detail.checked)} />import Tanrei
TanreiCheckbox("更新情報をメールで受け取る", isOn: $updates)
// isIndeterminate はデータから導きます。操作すると isOn が true になり、その後データの側で解除します。
TanreiCheckbox("すべて選択", isOn: $allSelected, isIndeterminate: someSelected)import androidx.compose.ui.state.ToggleableState
import io.github.chnotchy.tanrei.components.TanreiCheckbox
TanreiCheckbox(checked = updates, onCheckedChange = { updates = it }, label = "更新情報をメールで受け取る")
// 一部だけオンになりうる親は ToggleableState を受け取ります。次の状態は呼び出し側が決めます。
// 中間状態のチェックボックスを操作したら On にします。
TanreiCheckbox(
state = allState,
onClick = { selectAll(allState != ToggleableState.On) },
label = "すべて選択",
)
TanreiCheckbox(
checked = terms,
onCheckedChange = { terms = it },
label = "利用規約に同意する",
isError = submitted && !terms,
)import 'package:tanrei/tanrei.dart';
TanreiCheckbox(
value: updates,
onChanged: (bool value) => setState(() => updates = value), // null で無効になります
label: '更新情報をメールで受け取る',
);
// tristate では、value が null のとき中間状態です。操作すると onChanged(true) が呼ばれます。
TanreiCheckbox(
value: allSelected, // bool?:一部だけが選ばれている間は null
tristate: true,
onChanged: (bool value) => setState(() => selectAll(value)),
label: 'すべて選択',
);
TanreiCheckbox(
value: terms,
onChanged: (bool value) => setState(() => terms = value),
isError: submitted && !terms,
label: '利用規約に同意する',
);import { Checkbox } from '@tanrei/react-native';
<Checkbox value={updates} onValueChange={setUpdates} label="更新情報をメールで受け取る" />
<Checkbox value={all} indeterminate={some && !all} onValueChange={selectAll} label="すべて選択" />
<Checkbox value={terms} onValueChange={setTerms} error={submitted && !terms} label="利用規約に同意する" />状態、エラー、無効状態
既定のシステムでは、チェックボックスのボックスは 18 で、輪郭線は 2、角の丸みは 2、その後ろに直径 40 の丸いステートレイヤーがあり、ターゲットは 48 です。ラベル付きの高さは 40 になります。チェックと横線は、システムのアイコンセットの check と remove のグリフで、ボックスの上に 20 の大きさで描きます。太さは印専用のもので、システムのほかのアイコンより太くなります(既定のシステムでは、アイコンの 300 に対して 500)。この大きさでは、アイコンの太さのままだと線の幅が 1 ピクセルほどしかなく見えにくいため、大きさは変えずに太くしています。プリセットは自分のアイコンの太さを保ちます。チェックボックスは独自の印を描かないので、アイコンセットを変えたデザインシステムでは、ほかのグリフと一緒にこれらも変わります。ボックスの輪郭線と塗りは 1 つの形です。どの拡大率や画面密度でも、両者の間から背後が透けることはなく、チェックありのボックスは端から印まで均一な 1 色になります。cupertino では、チェックボックスは小さめのボックスと 16 のグリフのままです。
状態が変わると、ボックス、輪郭線、グリフの色が変わります。現れるグリフは、フェードインしながら半分の大きさから大きくなり、わずかに行き過ぎてから落ち着きます。消えるグリフは同じようにフェードアウトしながら縮み、チェックありと中間状態の間では、チェックが消えるのと同時に横線が現れます。動くのはグリフだけで、ボックスの大きさや位置は変わりません。初めて描かれたチェックボックスは、状態をすぐに示します。そのため、チェック済みのボックスがあるページを読み込んでも、アニメーションは起きません。動きを減らす設定では、新しい状態を次のフレームで完全に描きます。
構成要素
構成要素
unselected の上に描いています。| パーツ | 説明 |
|---|---|
1 container | The round state layer behind the box (Material Design 3's 40). It carries hover, focus and press and is invisible at rest. |
2 box | The small square that shows the condition (Material Design 3's 18, with a 2 corner): empty with an outline when unchecked, filled when checked or indeterminate. |
3 outline | The border of the box, drawn inside its edge. The fill sits inside the border, so a translucent fill and border never overlap; where the two meet they are drawn as one shape, so nothing behind the box shows between them. |
4 mark | The glyph check (checked) or the glyph remove (indeterminate) of the system's icon set, centered on the box and drawn with the icon set's family, fill and optical size at the mark's own weight, comp.checkbox.mark.weight: in the default system heavier than the system's icons, because the mark is a thin stroke on a small filled box and is what tells checked from indeterminate. The checkbox draws no mark of its own; a system that wants another check chooses another icon set. The glyph is decorative: the condition is announced from the state. |
5 label · 任意 | The visible text that names the choice. A click on it toggles the checkbox. |
6 focus-ring | Gap-then-ring indicator shown for keyboard focus, following the box's shape. |
寸法
寸法
| 長さ | トークン | 値(px) |
|---|---|---|
container size | tanrei.comp.checkbox.container.size | 40 |
box size | tanrei.comp.checkbox.box.size | 18 |
mark size | tanrei.comp.checkbox.mark.size | 20 |
unselected の上に描いています。プロパティ
| プロパティ | 型 | 既定値 | 説明 |
|---|---|---|---|
checked | boolean | false | Whether the choice is on. |
indeterminate | boolean | false | Shows the choice as partly on (a parent whose children are mixed). Wins over checked for what is drawn and announced; activation clears it. |
error | boolean | false | Marks the choice as invalid (a required choice left unmade). Draws the error form of the condition and is exposed as invalid; the message itself belongs to the surrounding form. |
disabled | boolean | false | Prevents interaction and removes the checkbox from the focus order. |
readOnly | boolean | false | Shows the choice and keeps it: the checkbox can be focused and read and is submitted with its form, but the person cannot switch it. Drawn as an enabled checkbox, without the hover and press answers (CHK-24). |
label | string | "" | The text that names the choice: drawn next to the box and used as the accessible name. |
labelHidden | boolean | false | Draws no visible label but keeps label as the accessible name (a row-selection checkbox in a table whose row already says what it is). |
イベント
| イベント | 説明 |
|---|---|
change | The user switched the checkbox; carries the new value of checked (indeterminate is then false). |
状態
振る舞い
EARS 記法による要件です。各プラットフォームの実装は、この ID に対応するテストで検証されます。要件の原文は仕様ファイルのものをそのまま掲載しています。
| ID | 要件 |
|---|---|
CHK-1 | WHEN the user activates the checkbox by pointer, touch, Space, assistive technology or a click on its label THE checkbox SHALL switch checked and emit change exactly once with the new value; Enter SHALL activate it only on a platform whose convention activates any focused control with Enter (Android, tvOS), and SHALL NOT on the web, where Enter submits the form. |
CHK-2 | WHEN the user activates the checkbox while indeterminate is true THE checkbox SHALL set checked to true, clear indeterminate, and emit change with true. |
CHK-3 | WHILE disabled is true THE checkbox SHALL NOT change or emit change, SHALL NOT be focusable, SHALL ignore clicks on its label and SHALL expose the disabled state to assistive technology. |
CHK-4 | THE checkbox SHALL draw the condition its props select: indeterminate when indeterminate is true, otherwise selected when checked is true, otherwise unselected; and the error- form of that condition while error is true. |
CHK-5 | WHILE hovered, keyboard-focused or pressed THE checkbox SHALL render its container, box, mark, outline, label and opacity from the component tokens of its condition in the highest-precedence active state, with precedence pressed over focused over hovered; focus gained by pointer or touch SHALL NOT select the focused state. A part the interaction states recolor changes over the component's state motion, as the container does; only a change of condition uses the selection motion. |
CHK-6 | WHEN the checkbox receives keyboard focus THE checkbox SHALL show the focus ring around its box without animation; focus gained by pointer or touch SHALL NOT show it. |
CHK-7 | WHERE the visual size is below the minimum target THE checkbox SHALL extend its hit area on both axes to sys.target.touch for touch input and sys.target.pointer for fine pointers, without changing its visual size; a platform that cannot tell the input type SHALL use sys.target.touch. The visible label SHALL be part of the hit area as well. |
CHK-8 | WHILE disabled is true THE checkbox SHALL render its container, box, mark, outline, label and opacity from the disabled component tokens of its condition. |
CHK-9 | WHEN the checkbox is pressed by pointer, touch or Space, or by Enter where Enter activates it (Android, tvOS; never on the web, where Enter submits the form) THE checkbox SHALL show the pressed state without delay and SHALL keep it visible for at least sys.motion.duration.press-hold, even when the press ends sooner. |
CHK-10 | WHILE pressed THE checkbox SHALL answer as sys.behavior.pressed-feedback names: overlay applies the pressed tokens to the whole container at once; ripple grows the pressed state layer from the point of contact (from the center for keyboard activation; a press outside the container (on the label) grows it from the container's center); dim applies the pressed opacity to the whole control and draws no state layer; none draws no answer to the press. Under ripple and dim only the container color stays with the state under the press; box, mark, outline, label, opacity and shape still come from the pressed tokens. Under none every part stays with the state under the press. The ripple grows over comp.checkbox.motion.feedback-duration with motion.state-easing, fades over motion.state-duration with motion.state-easing once the press has ended and press-hold has passed, and appears whole where motion is reduced. |
CHK-11 | THE checkbox SHALL ease its container and box corners by sys.shape.corner-smoothing (0 is a quarter circle, 0.6 the iOS continuous corner; a platform with only the OS curve draws it for any amount above 0) and show its keyboard focus as sys.behavior.focus-style names (ring or glow); a platform that cannot draw a choice SHALL fall back to the first value and state that in its README. |
CHK-12 | THE checkbox SHALL draw a box of side comp.checkbox.box.size with corners comp.checkbox.box.shape, centered in a round container of diameter comp.checkbox.container.size; its outline of width comp.checkbox.outline.width SHALL lie inside the box's edge and its fill inside the outline, never under it. Its mark SHALL be a glyph of the system's icon set, check while selected and remove while indeterminate, and SHALL NOT be drawn while unselected: centered on the box at comp.checkbox.mark.size, with sys.icon.family.selected, sys.icon.fill.selected, the weight comp.checkbox.mark.weight (not sys.icon.weight) and an optical size clamped between sys.icon.optical-size.min and sys.icon.optical-size.max, not clipped by the box, and hidden from assistive technology. THE checkbox SHALL draw no mark of its own (no path, shape or character of its own for the check or the dash). The weight SHALL change the stroke of the glyph only: the glyph box stays comp.checkbox.mark.size, and the box, the container and the place of the glyph are the same at every weight. |
CHK-13 | WHEN the condition changes after the checkbox was first drawn THE checkbox SHALL change the box, outline and mark colors over comp.checkbox.motion.selection-duration with comp.checkbox.motion.selection-easing; a glyph that appears SHALL fade in over the same duration and curve while growing about the box's center from comp.checkbox.motion.mark-enter-scale of its size to its full size over comp.checkbox.motion.mark-scale-duration with comp.checkbox.motion.mark-scale-easing, and a glyph that goes SHALL fade out and shrink to comp.checkbox.motion.mark-enter-scale the same way; between checked and indeterminate the check goes and the dash appears at the same time. A change of error alone SHALL only recolor, and the box and container SHALL NOT change size or move. |
CHK-14 | THE checkbox SHALL expose the role checkbox with the state checked, not checked or mixed (mixed while indeterminate is true), and SHALL expose the invalid state while error is true. |
CHK-15 | WHILE label is not empty and labelHidden is false THE checkbox SHALL draw label at the inline end of the container, comp.checkbox.label.gap away, in comp.checkbox.label.typescale, wrapping rather than truncating, the control centered on the label's first line; right-to-left layouts SHALL mirror the order. |
CHK-16 | WHILE labelHidden is true THE checkbox SHALL draw no label and SHALL still expose label as its accessible name; WHILE label is not empty, or a Field that frames it gives it a label, THE checkbox SHALL expose that label as its accessible name, over a name the product gives it on the element (aria-label or aria-labelledby); WHILE label is empty and the product gives the checkbox a name of its own on the element — aria-label, or aria-labelledby naming an element — THE checkbox SHALL expose that name as its accessible name; WHILE label is empty and the product gives it none THE checkbox SHALL still render, and in debug builds report that it has no accessible name. |
CHK-17 | WHERE motion is reduced THE checkbox SHALL draw the new condition whole in the first frame after the change: the box, outline and mark colors of the new condition, the new glyph at its full size and full opacity, and the old glyph gone, with no frame in between; a change that arrives while a selection motion is running SHALL end that motion in the same frame. The change SHALL be neither delayed nor skipped. |
CHK-18 | WHEN the condition changes again before the selection motion of CHK-13 has ended THE checkbox SHALL move from what it draws at that moment to the latest condition, never first jumping to the end of the earlier change, and SHALL end on the latest condition's colors and glyph alone. |
CHK-19 | IF the icon set cannot draw the glyph yet (its font is still loading or failed to load) THE checkbox SHALL draw nothing in the glyph's place, never the glyph's name as text, SHALL still draw the box, its fill and its outline and expose its state, and SHALL show the glyph once the icon set can draw it, without the selection motion. |
CHK-20 | THE checkbox SHALL take its layout direction from where it is used — the direction of the nearest ancestor that sets one, and the platform's own where none does — and SHALL have no direction setting of its own; WHEN that direction changes while the checkbox is shown THE checkbox SHALL draw itself for the new direction at once, without a motion of its own, keeping its selection and its focus. |
CHK-21 | THE checkbox SHALL lay out its label as text of its own direction, isolated from the text around it: each takes the base direction of its first strong character, or the layout direction where it has none, so that a left-to-right word, a number with its sign or unit, a telephone number and an address keep their own order in a right-to-left layout and reorder nothing beside them; THE checkbox SHALL still place the label and align its lines by the layout direction, not by the text's own. |
CHK-22 | THE checkbox SHALL draw the outline and the fill of its box as one shape: every point inside the box's outer edge SHALL be painted by the outline, by the fill, or, along the line where the two meet, by both in shares that add up to the whole, so that nothing behind the box shows between them at any zoom, display density or fractional position, in any frame of the selection motion (CHK-13), and so that a box whose outline and fill have the same color is that one color, evenly, from its edge to its mark; the two SHALL NOT be painted over one another either (CHK-12), so that a translucent outline or fill is nowhere darker than its token. |
CHK-23 | WHILE the checkbox stands in a checkbox group THE checkbox SHALL take its checked from the group's value and from the value the group reads from it (CKG-2), SHALL be disabled WHILE the group is (CKG-6), SHALL have its switching by the person reported by the group's change and by no event of its own that a listener on the group would receive as well (CKG-4), and WHERE the platform has forms SHALL submit nothing of its own, whatever name it carries (CKG-8). WHERE the checkbox stands in no checkbox group it SHALL be as it is anywhere — in a field, in a field group, in a table's row or alone: checked is its own, change is its own, and on the web it submits its own entry under its own name. |
CHK-24 | WHILE readOnly is true and disabled is false THE checkbox SHALL stay focusable and in the focus order; SHALL NOT change checked or indeterminate, and SHALL NOT emit change, on any activation — pointer, touch, Space, Enter where Enter activates it, assistive technology, a click on its label or a click dispatched on the element; SHALL expose the read-only state to assistive technology beside its checked, not checked or mixed state; WHERE the platform has forms SHALL be submitted with its form as it is drawn, and SHALL NOT report a missing value to the form's own validation, because the person cannot give one; and SHALL be drawn from the resting component tokens of its condition — the enabled ones, never the disabled ones — and SHALL show no hovered and no pressed state, under any pressed feedback (no overlay, no ripple, no dim), while keyboard focus still selects the focused state and shows the focus ring (CHK-5, CHK-6). The product may still set checked and indeterminate, which then take the selection motion (CHK-13). WHILE disabled is true as well, disabled wins (CHK-3). |
CHK-25 | WHERE the platform has ARIA attributes (the web), WHEN the product sets an aria- attribute on the host, by the attribute or by the ARIA property that reflects it, THE checkbox SHALL move it to the data-aria- attribute of the same name, so that the host is no second node with its name, description or state, and SHALL expose it on the element that carries its role — an id reference by the elements it names in the host's tree or a tree around it, an error message as part of the description while the checkbox is invalid — except those the checkbox owns (aria-checked, aria-pressed, aria-disabled), which it SHALL move and not expose. WHEN the product removes the aria- attribute or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaDescribedByElements…) to null, THE checkbox SHALL take it off that element. WHEN the product sets an aria- attribute the checkbox owns THE checkbox SHALL report it in debug builds. |
プラットフォーム別の名前対応
パリティは API が同一であることを意味しません。同じ契約を、各プラットフォームの流儀で表現します。
| 仕様 | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| コンポーネント | tanrei-checkbox | TanreiCheckbox | TanreiCheckbox | TanreiCheckbox | Checkbox |
checked · プロパティ | checked | isOn | checked | value | value |
indeterminate · プロパティ | indeterminate | isIndeterminate | state | tristate | indeterminate |
error · プロパティ | error | isError | isError | isError | error |
disabled · プロパティ | disabled | disabled | enabled | onChanged | disabled |
readOnly · プロパティ | readOnly | readOnly | readOnly | readOnly | readOnly |
label · プロパティ | label | title | label | label | label |
labelHidden · プロパティ | labelHidden | labelsHidden | labelHidden | labelHidden | labelHidden |
change · イベント | change | isOn | onCheckedChange | onChanged | onValueChange |
| 備考 | Form-associated (ElementInternals): it takes part in a form with name and value (default "on"), resets with it, and honours required as the native checkbox does; those three are web attributes, not spec props. It switches its own checked before firing change (and input), as a native checkbox does. labelHidden is the label-hidden attribute. Inside a tanrei-checkbox-group (found with closest() when it connects) it takes checked from the group, ignores name and required, submits nothing and fires no input or change of its own (CHK-23); a value attribute it does not carry is no value there, not "on". readOnly is the readonly attribute (HTML's name; the native attribute does not apply to a checkbox, so the element cancels the activation itself and writes aria-readonly on its native checkbox). | Toggle idiom: TanreiCheckbox(_ title:, isOn: Binding<Bool>, isIndeterminate: Bool = false); activation writes the binding, which is the change event. isIndeterminate is a value the caller derives from its data (a select-all is derived state), so activation sets isOn to true and the caller's data clears it. disabled follows .disabled(_:); labelsHidden follows .labelsHidden(). | Two overloads, as Compose's own: TanreiCheckbox(checked, onCheckedChange, …) and, for a parent that can be indeterminate, TanreiCheckbox(state: ToggleableState, onClick, …) in the TriStateCheckbox idiom, where the caller computes the next state (CHK-2 says it is On). enabled is the inverse flag; a null onCheckedChange draws a checkbox that only displays. | Flutter idiom: value is bool?; with tristate: true a null value is indeterminate. Unlike Flutter's Material checkbox, which cycles null → false, activation from null calls onChanged(true) (CHK-2). A null onChanged disables it. | Controlled, in React Native's value / onValueChange idiom: the caller sets value from the callback. |
トークン
| トークン | 参照先 | 解決値(ライト) |
|---|---|---|
--tanrei-comp-checkbox-box-shape | — | 2px |
--tanrei-comp-checkbox-box-size | — | 18px |
--tanrei-comp-checkbox-container-shape | sys.shape.corner.full | 9999px |
--tanrei-comp-checkbox-container-size | — | 40px |
--tanrei-comp-checkbox-disabled-container-shape | — | 9999px |
--tanrei-comp-checkbox-disabled-opacity | — | 1 |
--tanrei-comp-checkbox-error-indeterminate-box-color | sys.color.error | |
--tanrei-comp-checkbox-error-indeterminate-container-color | — | |
--tanrei-comp-checkbox-error-indeterminate-disabled-box-color | — | |
--tanrei-comp-checkbox-error-indeterminate-disabled-container-color | — | |
--tanrei-comp-checkbox-error-indeterminate-disabled-label-color | — | |
--tanrei-comp-checkbox-error-indeterminate-disabled-mark-color | — | |
--tanrei-comp-checkbox-error-indeterminate-disabled-outline-color | — | |
--tanrei-comp-checkbox-error-indeterminate-disabled-state-layer-color | — | |
--tanrei-comp-checkbox-error-indeterminate-focused-box-color | — | |
--tanrei-comp-checkbox-error-indeterminate-focused-container-color | — | |
--tanrei-comp-checkbox-error-indeterminate-focused-label-color | — | |
--tanrei-comp-checkbox-error-indeterminate-focused-mark-color | — | |
--tanrei-comp-checkbox-error-indeterminate-focused-outline-color | — | |
--tanrei-comp-checkbox-error-indeterminate-focused-state-layer-color | — | |
--tanrei-comp-checkbox-error-indeterminate-hovered-box-color | — | |
--tanrei-comp-checkbox-error-indeterminate-hovered-container-color | — | |
--tanrei-comp-checkbox-error-indeterminate-hovered-label-color | — | |
--tanrei-comp-checkbox-error-indeterminate-hovered-mark-color | — | |
--tanrei-comp-checkbox-error-indeterminate-hovered-outline-color | — | |
--tanrei-comp-checkbox-error-indeterminate-hovered-state-layer-color | — | |
--tanrei-comp-checkbox-error-indeterminate-label-color | sys.color.on-surface | |
--tanrei-comp-checkbox-error-indeterminate-mark-color | sys.color.on-error | |
--tanrei-comp-checkbox-error-indeterminate-outline-color | sys.color.error | |
--tanrei-comp-checkbox-error-indeterminate-pressed-box-color | — | |
--tanrei-comp-checkbox-error-indeterminate-pressed-container-color | — | |
--tanrei-comp-checkbox-error-indeterminate-pressed-label-color | — | |
--tanrei-comp-checkbox-error-indeterminate-pressed-mark-color | — | |
--tanrei-comp-checkbox-error-indeterminate-pressed-outline-color | — | |
--tanrei-comp-checkbox-error-indeterminate-pressed-state-layer-color | — | |
--tanrei-comp-checkbox-error-indeterminate-state-layer-color | comp.checkbox.error-indeterminate.outline.color | |
--tanrei-comp-checkbox-error-selected-box-color | sys.color.error | |
--tanrei-comp-checkbox-error-selected-container-color | — | |
--tanrei-comp-checkbox-error-selected-disabled-box-color | — | |
--tanrei-comp-checkbox-error-selected-disabled-container-color | — | |
--tanrei-comp-checkbox-error-selected-disabled-label-color | — | |
--tanrei-comp-checkbox-error-selected-disabled-mark-color | — | |
--tanrei-comp-checkbox-error-selected-disabled-outline-color | — | |
--tanrei-comp-checkbox-error-selected-disabled-state-layer-color | — | |
--tanrei-comp-checkbox-error-selected-focused-box-color | — | |
--tanrei-comp-checkbox-error-selected-focused-container-color | — | |
--tanrei-comp-checkbox-error-selected-focused-label-color | — | |
--tanrei-comp-checkbox-error-selected-focused-mark-color | — | |
--tanrei-comp-checkbox-error-selected-focused-outline-color | — | |
--tanrei-comp-checkbox-error-selected-focused-state-layer-color | — | |
--tanrei-comp-checkbox-error-selected-hovered-box-color | — | |
--tanrei-comp-checkbox-error-selected-hovered-container-color | — | |
--tanrei-comp-checkbox-error-selected-hovered-label-color | — | |
--tanrei-comp-checkbox-error-selected-hovered-mark-color | — | |
--tanrei-comp-checkbox-error-selected-hovered-outline-color | — | |
--tanrei-comp-checkbox-error-selected-hovered-state-layer-color | — | |
--tanrei-comp-checkbox-error-selected-label-color | sys.color.on-surface | |
--tanrei-comp-checkbox-error-selected-mark-color | sys.color.on-error | |
--tanrei-comp-checkbox-error-selected-outline-color | sys.color.error | |
--tanrei-comp-checkbox-error-selected-pressed-box-color | — | |
--tanrei-comp-checkbox-error-selected-pressed-container-color | — | |
--tanrei-comp-checkbox-error-selected-pressed-label-color | — | |
--tanrei-comp-checkbox-error-selected-pressed-mark-color | — | |
--tanrei-comp-checkbox-error-selected-pressed-outline-color | — | |
--tanrei-comp-checkbox-error-selected-pressed-state-layer-color | — | |
--tanrei-comp-checkbox-error-selected-state-layer-color | comp.checkbox.error-selected.outline.color | |
--tanrei-comp-checkbox-error-unselected-box-color | — | |
--tanrei-comp-checkbox-error-unselected-container-color | — | |
--tanrei-comp-checkbox-error-unselected-disabled-box-color | — | |
--tanrei-comp-checkbox-error-unselected-disabled-container-color | — | |
--tanrei-comp-checkbox-error-unselected-disabled-label-color | — | |
--tanrei-comp-checkbox-error-unselected-disabled-mark-color | — | |
--tanrei-comp-checkbox-error-unselected-disabled-outline-color | — | |
--tanrei-comp-checkbox-error-unselected-disabled-state-layer-color | — | |
--tanrei-comp-checkbox-error-unselected-focused-box-color | — | |
--tanrei-comp-checkbox-error-unselected-focused-container-color | — | |
--tanrei-comp-checkbox-error-unselected-focused-label-color | — | |
--tanrei-comp-checkbox-error-unselected-focused-mark-color | — | |
--tanrei-comp-checkbox-error-unselected-focused-outline-color | — | |
--tanrei-comp-checkbox-error-unselected-focused-state-layer-color | — | |
--tanrei-comp-checkbox-error-unselected-hovered-box-color | — | |
--tanrei-comp-checkbox-error-unselected-hovered-container-color | — | |
--tanrei-comp-checkbox-error-unselected-hovered-label-color | — | |
--tanrei-comp-checkbox-error-unselected-hovered-mark-color | — | |
--tanrei-comp-checkbox-error-unselected-hovered-outline-color | — | |
--tanrei-comp-checkbox-error-unselected-hovered-state-layer-color | — | |
--tanrei-comp-checkbox-error-unselected-label-color | sys.color.on-surface | |
--tanrei-comp-checkbox-error-unselected-mark-color | — | |
--tanrei-comp-checkbox-error-unselected-outline-color | sys.color.error | |
--tanrei-comp-checkbox-error-unselected-pressed-box-color | — | |
--tanrei-comp-checkbox-error-unselected-pressed-container-color | — | |
--tanrei-comp-checkbox-error-unselected-pressed-label-color | — | |
--tanrei-comp-checkbox-error-unselected-pressed-mark-color | — | |
--tanrei-comp-checkbox-error-unselected-pressed-outline-color | — | |
--tanrei-comp-checkbox-error-unselected-pressed-state-layer-color | — | |
--tanrei-comp-checkbox-error-unselected-state-layer-color | comp.checkbox.error-unselected.outline.color | |
--tanrei-comp-checkbox-focused-container-shape | — | 9999px |
--tanrei-comp-checkbox-focused-opacity | — | 1 |
--tanrei-comp-checkbox-hovered-container-shape | — | 9999px |
--tanrei-comp-checkbox-hovered-opacity | — | 1 |
--tanrei-comp-checkbox-indeterminate-box-color | sys.color.primary | |
--tanrei-comp-checkbox-indeterminate-container-color | — | |
--tanrei-comp-checkbox-indeterminate-disabled-box-color | — | |
--tanrei-comp-checkbox-indeterminate-disabled-container-color | — | |
--tanrei-comp-checkbox-indeterminate-disabled-label-color | — | |
--tanrei-comp-checkbox-indeterminate-disabled-mark-color | — | |
--tanrei-comp-checkbox-indeterminate-disabled-outline-color | — | |
--tanrei-comp-checkbox-indeterminate-disabled-state-layer-color | — | |
--tanrei-comp-checkbox-indeterminate-focused-box-color | — | |
--tanrei-comp-checkbox-indeterminate-focused-container-color | — | |
--tanrei-comp-checkbox-indeterminate-focused-label-color | — | |
--tanrei-comp-checkbox-indeterminate-focused-mark-color | — | |
--tanrei-comp-checkbox-indeterminate-focused-outline-color | — | |
--tanrei-comp-checkbox-indeterminate-focused-state-layer-color | — | |
--tanrei-comp-checkbox-indeterminate-hovered-box-color | — | |
--tanrei-comp-checkbox-indeterminate-hovered-container-color | — | |
--tanrei-comp-checkbox-indeterminate-hovered-label-color | — | |
--tanrei-comp-checkbox-indeterminate-hovered-mark-color | — | |
--tanrei-comp-checkbox-indeterminate-hovered-outline-color | — | |
--tanrei-comp-checkbox-indeterminate-hovered-state-layer-color | — | |
--tanrei-comp-checkbox-indeterminate-label-color | sys.color.on-surface | |
--tanrei-comp-checkbox-indeterminate-mark-color | sys.color.on-primary | |
--tanrei-comp-checkbox-indeterminate-outline-color | sys.color.primary | |
--tanrei-comp-checkbox-indeterminate-pressed-box-color | — | |
--tanrei-comp-checkbox-indeterminate-pressed-container-color | — | |
--tanrei-comp-checkbox-indeterminate-pressed-label-color | — | |
--tanrei-comp-checkbox-indeterminate-pressed-mark-color | — | |
--tanrei-comp-checkbox-indeterminate-pressed-outline-color | — | |
--tanrei-comp-checkbox-indeterminate-pressed-state-layer-color | — | |
--tanrei-comp-checkbox-indeterminate-state-layer-color | comp.checkbox.indeterminate.outline.color | |
--tanrei-comp-checkbox-label-gap | sys.space.space50 | 4px |
--tanrei-comp-checkbox-mark-size | sys.icon.small | 20px |
--tanrei-comp-checkbox-mark-weight | sys.icon.mark.weight | 500 |
--tanrei-comp-checkbox-motion-feedback-duration | sys.motion.role.feedback | 450ms |
--tanrei-comp-checkbox-motion-mark-enter-scale | — | 0.5 |
--tanrei-comp-checkbox-motion-mark-scale-duration | sys.motion.role.selection.mark | 250ms |
--tanrei-comp-checkbox-motion-mark-scale-easing | sys.motion.easing.spatial | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-checkbox-motion-selection-duration | sys.motion.role.selection.mark | 250ms |
--tanrei-comp-checkbox-motion-selection-easing | sys.motion.easing.state | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-checkbox-motion-state-duration | sys.motion.role.state.compact | 200ms |
--tanrei-comp-checkbox-motion-state-easing | sys.motion.easing.state | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-checkbox-outline-width | sys.border.thick | 2px |
--tanrei-comp-checkbox-pressed-container-shape | — | 9999px |
--tanrei-comp-checkbox-pressed-opacity | — | 1 |
--tanrei-comp-checkbox-selected-box-color | sys.color.primary | |
--tanrei-comp-checkbox-selected-container-color | — | |
--tanrei-comp-checkbox-selected-disabled-box-color | — | |
--tanrei-comp-checkbox-selected-disabled-container-color | — | |
--tanrei-comp-checkbox-selected-disabled-label-color | — | |
--tanrei-comp-checkbox-selected-disabled-mark-color | — | |
--tanrei-comp-checkbox-selected-disabled-outline-color | — | |
--tanrei-comp-checkbox-selected-disabled-state-layer-color | — | |
--tanrei-comp-checkbox-selected-focused-box-color | — | |
--tanrei-comp-checkbox-selected-focused-container-color | — | |
--tanrei-comp-checkbox-selected-focused-label-color | — | |
--tanrei-comp-checkbox-selected-focused-mark-color | — | |
--tanrei-comp-checkbox-selected-focused-outline-color | — | |
--tanrei-comp-checkbox-selected-focused-state-layer-color | — | |
--tanrei-comp-checkbox-selected-hovered-box-color | — | |
--tanrei-comp-checkbox-selected-hovered-container-color | — | |
--tanrei-comp-checkbox-selected-hovered-label-color | — | |
--tanrei-comp-checkbox-selected-hovered-mark-color | — | |
--tanrei-comp-checkbox-selected-hovered-outline-color | — | |
--tanrei-comp-checkbox-selected-hovered-state-layer-color | — | |
--tanrei-comp-checkbox-selected-label-color | sys.color.on-surface | |
--tanrei-comp-checkbox-selected-mark-color | sys.color.on-primary | |
--tanrei-comp-checkbox-selected-outline-color | sys.color.primary | |
--tanrei-comp-checkbox-selected-pressed-box-color | — | |
--tanrei-comp-checkbox-selected-pressed-container-color | — | |
--tanrei-comp-checkbox-selected-pressed-label-color | — | |
--tanrei-comp-checkbox-selected-pressed-mark-color | — | |
--tanrei-comp-checkbox-selected-pressed-outline-color | — | |
--tanrei-comp-checkbox-selected-pressed-state-layer-color | — | |
--tanrei-comp-checkbox-selected-state-layer-color | comp.checkbox.selected.outline.color | |
--tanrei-comp-checkbox-unselected-box-color | — | |
--tanrei-comp-checkbox-unselected-container-color | — | |
--tanrei-comp-checkbox-unselected-disabled-box-color | — | |
--tanrei-comp-checkbox-unselected-disabled-container-color | — | |
--tanrei-comp-checkbox-unselected-disabled-label-color | — | |
--tanrei-comp-checkbox-unselected-disabled-mark-color | — | |
--tanrei-comp-checkbox-unselected-disabled-outline-color | — | |
--tanrei-comp-checkbox-unselected-disabled-state-layer-color | — | |
--tanrei-comp-checkbox-unselected-focused-box-color | — | |
--tanrei-comp-checkbox-unselected-focused-container-color | — | |
--tanrei-comp-checkbox-unselected-focused-label-color | — | |
--tanrei-comp-checkbox-unselected-focused-mark-color | — | |
--tanrei-comp-checkbox-unselected-focused-outline-color | — | |
--tanrei-comp-checkbox-unselected-focused-state-layer-color | — | |
--tanrei-comp-checkbox-unselected-hovered-box-color | — | |
--tanrei-comp-checkbox-unselected-hovered-container-color | — | |
--tanrei-comp-checkbox-unselected-hovered-label-color | — | |
--tanrei-comp-checkbox-unselected-hovered-mark-color | — | |
--tanrei-comp-checkbox-unselected-hovered-outline-color | — | |
--tanrei-comp-checkbox-unselected-hovered-state-layer-color | — | |
--tanrei-comp-checkbox-unselected-label-color | sys.color.on-surface | |
--tanrei-comp-checkbox-unselected-mark-color | — | |
--tanrei-comp-checkbox-unselected-outline-color | sys.color.outline | |
--tanrei-comp-checkbox-unselected-pressed-box-color | — | |
--tanrei-comp-checkbox-unselected-pressed-container-color | — | |
--tanrei-comp-checkbox-unselected-pressed-label-color | — | |
--tanrei-comp-checkbox-unselected-pressed-mark-color | — | |
--tanrei-comp-checkbox-unselected-pressed-outline-color | — | |
--tanrei-comp-checkbox-unselected-pressed-state-layer-color | — | |
--tanrei-comp-checkbox-unselected-state-layer-color | comp.checkbox.unselected.outline.color | |
--tanrei-comp-checkbox-label-typescale | sys.typescale.body | 400 14px/1.5714 |
フィクスチャ
基準となる描画パターンです。全プラットフォームが同じ ID でスナップショットを撮り、結果を比較できるようにしています。
unselected
label: Email me updates selected
checked: true label: Email me updates indeterminate
indeterminate: true label: Select all error-unselected
error: true label: I accept the terms error-selected
checked: true error: true label: I accept the terms error-indeterminate
indeterminate: true error: true label: Select all disabled-unselected
disabled: true label: Email me updates disabled-selected
checked: true disabled: true label: Email me updates disabled-indeterminate
indeterminate: true disabled: true label: Select all label-hidden
checked: true label: Select row labelHidden: true read-only-selected
checked: true readOnly: true label: Send me a receipt 生成元 specs/checkbox.spec.json, tokens/comp/checkbox.tokens.json, design/tokens/
ほかの選択に左右されない選択に使います。いくつ選んでもよい(1 つも選ばなくてもよい)選択肢の一覧や、利用規約への同意のような「はい」か「いいえ」かの 1 つの選択です。選択が反映されるのは、フォームの送信や保存のように、利用者が確定したときです。表の行やリストの項目を選ぶのにも使います。
中間状態は、子の一部だけにチェックが入っている親のチェックボックス(リストの上の「すべて選択」など)のためのものです。利用者が選べる 3 つ目の答えではありません。
読み取り専用のチェックボックスは、読めるが変えられない答えを示します。注文を送る前の確認画面や、一部の人だけが変えられる設定などです。フォーカス順に残り、状態とともに読み取り専用であることが読み上げられ、フォームとともに送信されます。見た目は有効なチェックボックスと同じで、ホバーと押下の反応だけがありません。使えないものではなく、答えとして読めるようにするためです。選択そのものが当てはまらないときは disabled を使い、誰もたどる必要がないときは答えを文章で書きます。
| コントロール | 選択 | 反映されるとき | 用途 |
|---|---|---|---|
| チェックボックス | 独立した選択をいくつでも(0 個も可) | 利用者が確定したとき | フォームの選択肢、規約への同意、行の選択 |
| ラジオボタン | すべて見えている少数の選択肢から 1 つだけ | 多くは、利用者が確定したとき | 1 つの問いへの 1 つの答え |
| スイッチ | 1 つの設定のオンかオフ | すぐに | 切り替えた時点で反映される設定 |
- ラベルには選択の内容を肯定の形で書きます。「メールを送らない」ではなく「更新情報をメールで受け取る」です。
- チェックボックスの一覧は 1 行に 1 つずつ縦に並べ、ラベルの書き出しをそろえます。
- 中間状態は子の状態から導きます。親が操作されたら、すべての子にチェックを入れます。
- 必須のチェックボックスにチェックが入っていないときは
errorを設定し、理由をフォームのメッセージで伝えます。
- 操作した時点で反映される変更にチェックボックスを使わない。スイッチを使います。
- 互いに排他的な選択にチェックボックスを使わない。ラジオボタンを使います。
- ラベルの中にリンクやほかのコントロールを置かない。ラベルをクリックするとチェックボックスが切り替わります。
- 何を選ぶチェックボックスなのかが周りの行から分からない場合は、ラベルを隠さない。
- ロール
checkbox- ラベル付け
- label is the accessible name, visible or not (labelHidden). A click on the visible label toggles the checkbox, as a native label does. A checkbox with no label is reported in debug builds.
- 最小ターゲット
- 見た目のサイズが小さくても、ヒット領域は最小ターゲットサイズを満たします。 minimum 32px · pointer 44px · spacing 8px · touch 48px
キーボード操作
| キー | 動作 |
|---|---|
| Tab | Moves focus to the checkbox. |
| Space | Switches it (an indeterminate checkbox becomes checked); nothing while it is read-only. |
| Enter | Nothing on the web (it submits the form); switches it where the platform activates any focused control with Enter (Android, tvOS). |
備考
- The mixed state is announced as such (aria-checked="mixed" on the web, a toggleable state of Indeterminate on Android, a Semantics mixed value in Flutter, accessibilityState checked "mixed" in React Native). SwiftUI has no mixed trait on iOS: the value is announced as "mixed" through accessibilityValue.
- error is exposed as invalid (aria-invalid on the web, the error semantics on Android and Flutter). The reason is text the form shows and associates with the checkbox; the checkbox does not draw it.
- Read-only (CHK-24) is a checkbox that shows an answer in place and keeps it in the focus order, so that it is read with its form — on a review step, or where only some people may change it. HTML's readonly attribute does not apply to a checkbox, so a read-only checkbox is not a native one's: on the web it keeps the native checkbox enabled, cancels its activation and says read-only with aria-readonly, which WAI-ARIA allows on the checkbox role; React Aria's isReadOnly is the same: focusable, announced with its value, not changeable. Where the answer needs no control at all, write it as text; where the person may not reach it at all, it is disabled.
- Several checkboxes that answer one question are a checkbox group: it names the set, holds the list of the checked values under one name and says the set's error (CHK-23). A checkbox stands alone where it is one choice of its own — a consent, a setting — and in a field group where each checkbox of a set has a name of its own.
- The check and the dash are decorative glyphs of the icon set, hidden from assistive technology: where a glyph is written as a ligature (the web), its name ("check", "remove") is never announced or shown as text (CHK-12, CHK-19). Checked and indeterminate differ by the glyph alone, and both are exposed as states (CHK-14).
- The mark is drawn at its own weight (comp.checkbox.mark.weight, CHK-12), heavier than the system's icons in the default system. Its color already has the contrast of content on its fill; what a light weight loses is the stroke, which at this size is about one pixel wide and is drawn in a mix of the mark's color and the fill's. A system that sets a lighter weight should look at the dash in particular: it is one stroke, and it is all that tells indeterminate from checked.
- The selection motion is decoration too: under reduced motion the new condition is drawn whole at once, never later (CHK-17).
- The label wraps at 200% text size; the box does not grow with text, because it is a control, not text.
- How a state looks is a value decision of the active design system; components read the state's tokens and never compute the effect themselves.
生成元 specs/checkbox.spec.json, tokens/sys/measure.tokens.json
- チェックボックスのロールと、その状態(チェックあり、なし、中間状態では mixed)、無効状態、
errorが設定されている間は invalid の状態を伝えます。React Native には invalid の状態がないため、エラーは描かれますが読み上げられません。 - ラベルは、描かれていても
labelHiddenで隠されていても、アクセシブルネームになります。描かれたテキストは支援技術から隠すので、名前が読まれるのは 1 度だけです。 - ラベルをクリックまたはタップするとチェックボックスが切り替わります。ラベルもヒット領域に含まれ、ヒット領域は最小ターゲットを満たします。
- Space で切り替わります。Enter で切り替わるのは、フォーカスのあるコントロールを Enter で操作するのが慣習のプラットフォーム(Android、tvOS)だけです。Web では Enter はフォームを送信します。
readOnlyの間は、フォーカスでき、状態とともに読み取り専用であることが伝わります。押下、Space、ラベルのクリック、click()のどれでも変わらず、ホバーと押下の反応も出ません。Web では値はそのまま送信され、必須でも値がないとは報告しません。HTML のreadonlyはチェックボックスには効かないので、コンポーネントが自分でこれを行います。- フォーカスインジケーターは、キーボードフォーカスのときだけ、ボックスの周りに表示します。
- チェックと横線は支援技術から隠します。チェックありと mixed は状態として読み上げ、グリフの名前から読み上げることはありません。
- 動きを減らす設定では、新しい状態を変化の直後のフレームで完全に描き、遅らせたり途中の姿を見せたりしません。変化の途中で再び変わったときは、その時点で描かれている姿から続けます。
- アイコンフォントがまだグリフを描けない間は、グリフの場所に何も描かず、「check」という文字を出すこともありません。塗られたボックスは描き、状態も伝えます。フォントが読み込まれると、グリフが現れます。
- Web では、ネイティブのチェックボックスと同じようにフォームに参加します。
name、value、required、リセットに対応します。 - ラベルがない場合は、デバッグビルドで報告します。
プラットフォームごとの既知の制約:
- SwiftUI、Compose、Flutter、React Native は、まだチェックと横線を独自の印で描き、独自の動きで切り替えます。印専用の太さと、1 つの形として描くボックスにも、まだ対応していません。
readOnlyはいまのところ Web だけにあります。SwiftUI、Compose、Flutter、React Native にはまだありません。m3-likeでは、チェックはアイコンセットのグリフで、フェードインしながら大きくなります。Material はチェックを独自に描き、線をなぞるように描き入れ、横線へと曲げて変えます(mimicry-gaps 台帳checkbox-mark-drawn-on)。
- アイコンフォントを読み込みます。読み込まれるまでは、チェックありと中間状態のチェックボックスは、どちらもグリフのない塗られたボックスで、見た目では区別できません。状態は読み上げられます。
- デザインシステムで印の太さ(
comp.checkbox.mark.weight)を細くする場合は、横線を確かめてください。横線は 1 本の線で、中間状態とチェックありを見た目で区別する唯一の手がかりです。 - 選択の内容を表すラベルを書き、チェックの有無にかかわらず同じにします。状態はプラットフォームが読み上げます。
errorを設定したら、理由をチェックボックスの隣かフォームのまとめにテキストで示し、チェックボックスと関連付けます。チェックボックスが伝えるのは invalid であることだけで、理由は伝えません。React Native では、そのメッセージがエラーを耳で知る唯一の手段です。- 1 つの問いに答えるチェックボックスのまとまりには名前を付けます。Web では
<fieldset>と<legend>を使います。