ワンタイムコード入力欄
サインインや確認のためにユーザーへ送った短いコードを、マス目に分けて描いた 1 つのテキストの値として受け取ります。コードの長さと、まだ足りない分が見え、プラットフォームが 1 回の操作で入力できます。
上級者向け
ほとんどのプロダクトでは、このコンポーネントを部品として含むOne-time-code fieldを配置します。
- カテゴリ
- テキスト入力
- トークン
comp.one-time-code-input- レベル
- 基礎
- Web
tanrei-one-time-code-inputschedule - SwiftUI
TanreiOneTimeCodeInputradio_button_unchecked - Jetpack Compose
TanreiOneTimeCodeInputradio_button_unchecked - Flutter
TanreiOneTimeCodeInputradio_button_unchecked - React Native
OneTimeCodeInputradio_button_unchecked
生成元 docs/status/status.json, specs/one-time-code-input.spec.json
フィールドの中のワンタイムコード入力欄と、プロダクトがコードを受け付けなかったもの
ワンタイムコード入力欄は、プロダクトがユーザーに送り、1 回だけ入力してもらう短いコードに使います。サインイン、メールアドレスや電話番号の確認、支払いの承認などです。マス目は、コードの長さと、まだ足りない分を示します。
これはコード全体のための 1 つの入力欄で、1 文字ごとの入力欄の集まりではありません。テキストの値は 1 つ、Tab で止まる位置は 1 つ、支援技術にとってのテキストボックスも 1 つで、マス目はその値を描いたものです。そのため、プラットフォームのコードの自動入力が 1 回の操作で入り、貼り付けたコードが丸ごと入り、スクリーンリーダーは名前の付いた 1 つのテキストボックスとして読みます。
これは上級者向けのコンポーネントです。自分で組み立てるプロダクトのための、コントロールだけの部品で、ラベル、補足、エラーテキストは自分では持ちません。ほとんどのプロダクトに合うのは、この入力欄をフィールドに入れてそのまま使える形にしたワンタイムコードフィールドです。
使われている場所は、ワンタイムコードフィールドです。自分で組み立てるときは、フィールドの中に入れます。フィールドが名前と説明を与え、必須であることを伝え、エラーの状態にします。このページの例はその書き方で、ワンタイムコードフィールドの 1 つ下の階層にあたります。見えるラベルがほかの場所にあるとき(ダイアログの見出しなど)は、単独で使って label を指定します。label が描かれることはありません。
Web では <tanrei-one-time-code-input> です。ほかのプラットフォームはまだ実装していません。
value は、そこまでに入力されたコードです。最大で length 文字の、数字か、alphanumeric では数字と大文字の英字で、グループをどう描いていても区切りは含みません。
<form>
<tanrei-field label="確認コード"
supporting-text="携帯電話に送った 6 桁のコードを入力してください。"
error-text="コードが正しくありません。メッセージを確かめて、もう一度入力してください。"
required required-text="必須">
<tanrei-one-time-code-input name="code" group-size="3"></tanrei-one-time-code-input>
</tanrei-field>
</form>
<script type="module">
import '@tanrei/web/components/field';
import '@tanrei/web/components/one-time-code-input';
const field = document.querySelector('tanrei-field');
const code = document.querySelector('tanrei-one-time-code-input');
// ユーザーが値を変えました。value はすでに新しい値です。
code.addEventListener('input', () => (field.error = false));
// 最後のマスが埋まったか、コード全体が貼り付けまたは自動入力されました。ほかには何も起きません。
code.addEventListener('complete', async (e) => {
code.readOnly = true;
const right = await verify(e.detail.value);
code.readOnly = false;
field.error = !right;
});
</script>// 上級者向けのコンポーネント(ほかのコンポーネントの部品)は、advanced のエントリーから読み込みます。
import { Field } from '@tanrei/react';
import { OneTimeCodeInput } from '@tanrei/react/advanced';
<Field label="確認コード" error={wrong}
supportingText="携帯電話に送った 6 桁のコードを入力してください。"
errorText="コードが正しくありません。メッセージを確かめて、もう一度入力してください。">
<OneTimeCodeInput name="code" groupSize={3} value={code}
onInput={(event) => setCode(event.detail.value)}
onComplete={(event) => verify(event.detail.value)} />
</Field>4 マス、2 グループの 8 マス、英字と数字、隠したコード、読み取り専用、無効
| パーツ | 内容 |
|---|---|
| マス | コードの 1 文字につき 1 つのボックス。空か、1 文字を持ちます。空のマスと埋まったマスは同じボックスです |
| 文字 | 埋まったマスの文字。テキストフィールドの入力のテキストスタイルで、等幅の数字で描きます。mask を付けると、パスワードの入力欄が描く印に置き換わります |
| アクティブなマス | 入力欄にフォーカスがある間、次の文字が入るマス。最初の空のマスか、すべて埋まっていれば最後のマスです。縁の内側にフォーカスの線を描きます。これが入力欄のフォーカスインジケーターで、入力位置の目印でもあります |
| キャレット | 空のアクティブなマスに描きます。埋まったアクティブなマスには描きません。次の文字は、そのマスの文字を置き換えるためです |
| グループの印 | groupSize を指定したとき、決まった数のマスごとに入る短い線。描くだけのもので、値にも、コピーされるものにも、フォームが送信するものにも含まれません |
マスの高さは medium のテキストフィールドと同じなので、1 つのフォームの中でワンタイムコード入力欄とテキストフィールドの高さがそろいます。サイズも見た目も 1 つだけです。マスの高さ、角、塗りは、デザインシステムがレイヤーで決めます。
マスの並びは先頭側の端から始まり、幅はマスに必要な分だけです。2 グループの 6 マスは、既定のシステムで幅 284 になり、幅 320 の画面に収まります。場所が足りないときは、マスが幅を分け合って細くなります。細くなるのは、1 文字とその両側の小さなパディングの幅までです。それでも足りなければ並びを折り返します。まずグループの間で折り返し(折り返した位置の印は描きません)、グループがないときはマスの間で折り返します。マスが切れることはなく、収めるためにコードを小さく描くこともありません。
| いつ | 起きること |
|---|---|
| 入力できる文字を打つ | アクティブなマスに入り、そのマスの文字を置き換えて、次のマスがアクティブになります。最後のマスではアクティブなマスは動かないので、続けて打った文字は最後の文字を置き換えます |
| それ以外の文字を打つ | 何も起きません。マスが持てるのは、コードに使える文字だけです |
| Backspace | 埋まったアクティブなマスはその文字を、空のアクティブなマスは 1 つ前の文字を失います。後ろの文字は前に詰まり、値に空きはできません |
| 左右の矢印キー、Home、End | 埋まったマスと最初の空のマスの間で、アクティブなマスを動かします。上下の矢印キーは何もしません |
| すべて選択してから文字を打つ | コード全体を置き換えます。一部のマスだけを選ぶことはできません |
| 貼り付け、ドロップ、自動入力、音声入力 | アクティブなマスがどこにあっても、テキスト全体を 1 つのコードとして読みます |
入力や貼り付けは、寛容に読みます。ほかの文字体系の数字や、全角の数字と英字は ASCII の文字として、小文字は大文字として読みます。値は常に ASCII なので、送ったコードとそのまま比べられます。
貼り付けたテキストからは、空白、ハイフン、ダッシュを取り除きます。123 456 も 123-456 も 123456 になります。数字のコードでは、長いテキストの中から、ちょうど length 桁の数字の並びが 1 つだけあるときにそれを探し出すので、「確認コードは 123456 です。」のようなメッセージを丸ごと貼り付けられます。どれがコードか決まらないときは、何も変えません。
入力メソッドがまだ確定していないテキストは、下線付きでマスに描きます。確定するまで、値は変わりません。
| イベント | いつ |
|---|---|
input |
ユーザーが値を変えるたび。新しい値を伝えます |
complete |
ユーザーによる変更で、値が length 文字になったとき。その変更の input の後に、1 回だけ |
change |
フォーカスが離れたとき、または Enter が押されたときに、値が最後に確定した値と違っている場合 |
action |
Enter。Web のフォームの中では、続けて、通常のテキスト入力と同じようにフォームが送信されます |
プロダクトが value を設定したときは、どれも発火しません。また、コードがそろっても、ほかには何も起きません。入力欄が送信することも、フォーカスを動かすことも、自身を無効にすることも、何かを読み上げることもありません。そろったコードをどう扱うかは、プロダクトが決めます。
構成要素
構成要素
empty の上に描いています。| パーツ | 説明 |
|---|---|
1 cell | One box per character of the code, empty or holding one character. The component's container: it carries the hover and the focus answer, and its tokens are the container's. |
2 character | The character a filled cell holds, or the platform's obscuring mark in its place while mask is true. |
3 caret · 任意 | Drawn in the active cell while the field has focus and that cell is empty: where the next character goes. |
4 separator · 任意 | A short line between two groups of cells. A drawing only: not part of the value and kept from assistive technology. |
プロパティ
| プロパティ | 型 | 既定値 | 説明 |
|---|---|---|---|
value | string | "" | The code entered so far: at most length characters, digits or, for alphanumeric, digits and upper-case letters, with no separator. One string, whatever the cells and groups drawn. |
length | number | 6 | How many characters the code has, and so how many cells are drawn. A whole number of 1 or more. |
type | numeric | alphanumeric | "numeric" | What a cell takes: numeric is the digits 0 to 9, with a numeric keypad; alphanumeric is digits and the letters A to Z, held in upper case, with a general keyboard. |
groupSize | number | 0 | Draws the cells in groups of this many, counted from the first, with a mark between two groups (3 for a six-character code written "123 456"). 0 draws one group. It changes the drawing only: the value has no separator. |
mask | boolean | false | Draws the platform's obscuring mark in each filled cell in place of its character, and exposes the field as protected. For a screen other people can see; a code that is used once and expires rarely needs it. |
label | string | "" | Names the field for assistive technology where no Field frames it (the visible label is a dialog headline or a step title, in the same words). Never drawn. Inside a Field leave it empty: the Field names it. |
error | boolean | false | Draws every cell in the error condition and exposes the field as invalid. A Field sets it from its own error; set it here only where no Field frames the control. What a wrong code means is the product's to say, in words, with the Field's errorText. |
disabled | boolean | false | Prevents entry and takes the field out of the focus order. Inside a Field, disable the Field, so that its label follows. |
readOnly | boolean | false | Keeps the field focusable and its value readable, and lets nothing change it: for the moment a complete code is being checked, when taking focus away would lose the place of a person who must then correct it. |
イベント
| イベント | 説明 |
|---|---|
input | The person changed the value; carries the new value. Emitted for every change, not when the product sets value. |
change | The person committed a changed value (focus left the field, or the action key was pressed); carries the value. |
complete | A change by the person left the value length characters long; carries the value. Emitted after input, once for that change. The field does nothing else: checking the code is the product's. |
action | The person pressed the keyboard's action key (Enter, Return, Done). |
状態
振る舞い
EARS 記法による要件です。各プラットフォームの実装は、この ID に対応するテストで検証されます。要件の原文は仕様ファイルのものをそのまま掲載しています。
| ID | 要件 |
|---|---|
OTC-1 | THE one-time-code input SHALL draw one row of length cells, in the order of the code's characters, each a box at least comp.one-time-code-input.container.height high and comp.one-time-code-input.container.width wide (OTC-23), with corners of comp.one-time-code-input.container.shape (never more than half its height) eased by sys.shape.corner-smoothing, comp.one-time-code-input.container.gap from the next, filled with comp.one-time-code-input.standard.container.color. The row SHALL start at the start edge of the width its layout gives it and SHALL be as wide as its cells, gaps and group marks need; the field SHALL be as tall as its rows. THE one-time-code input SHALL draw no label, no help, no error text, no placeholder and no container around the row: a Field frames it (OTC-22). |
OTC-2 | THE one-time-code input SHALL be one field to the person, the form, the keyboard and assistive technology: it SHALL hold one value, be one stop in the focus order, edit in one native text element of the platform, so that an input method, the platform's autofill, the clipboard and dictation meet one text input, and be exposed as one text box whose value is the whole code. The cells, the caret it draws and the group marks SHALL be a drawing of that value: they SHALL NOT be exposed to assistive technology, SHALL NOT take focus one by one, and SHALL NOT be separate inputs. |
OTC-3 | THE one-time-code input SHALL draw the character at each place of value in the cell of that place, centred, on one line, in comp.one-time-code-input.input.typescale with tabular figures and in comp.one-time-code-input.standard.input.color, and SHALL leave empty every cell past the end of value. An empty cell and a filled cell SHALL have the same box and the same fill. The value SHALL never have a gap: the filled cells are always the first ones. |
OTC-4 | THE one-time-code input SHALL hold in value only the characters its type permits — WHILE type is numeric the ASCII digits 0 to 9; WHILE type is alphanumeric those digits and the letters A to Z — and SHALL read what a person types, pastes, dictates or is given by autofill leniently before deciding: a decimal digit of any script and a full-width digit or letter SHALL be read as its ASCII form, and a lower-case letter as its upper-case form. A character that is still not permitted SHALL be dropped: it SHALL NOT enter a cell, move the active cell or emit an event. The value SHALL therefore be ASCII, in upper case, and comparable as it stands with the code the product sent. |
OTC-5 | WHILE the field has focus THE one-time-code input SHALL have one active cell, the cell the next character goes to: the first empty cell and, WHILE every cell is filled, the last cell — unless the person moved it to a filled cell (OTC-8, OTC-25). WHEN focus enters by the keyboard, by a press on a Field's label or from the product THE active cell SHALL be that first empty or last cell; WHEN focus leaves, the field SHALL have no active cell. The insertion point of the native text element SHALL stand at the active cell — before its character WHILE it is filled, at the end of the value WHILE it is empty — so that assistive technology that reads where the insertion point is, and the character at it, reads the active cell. |
OTC-6 | WHEN the person types a permitted character (OTC-4) THE one-time-code input SHALL put it in the active cell, in place of the character that cell holds, and SHALL move the active cell to the next one; WHILE the active cell is the last THE active cell SHALL stay there, so that a further character replaces the last one and nothing is typed past the end. Text an input method commits SHALL be read character by character in the same way. WHILE an input method holds text it has not yet committed THE one-time-code input SHALL draw that text's characters, read by OTC-4, in the cells from the active cell on, marked as the platform marks composing text, SHALL NOT change value or emit an event for it, and SHALL remove it from the cells when the input method cancels it; the cells are the only drawing of what is typed, so text that is being composed is never left unseen. THE one-time-code input SHALL NOT move focus out of itself because the code is complete (OTC-14). |
OTC-7 | WHILE hovered THE one-time-code input SHALL render every cell from the hovered component tokens, and WHILE focused SHALL render its active cell, and that cell alone, from the focused ones (their error parts WHILE error is true), with precedence focused over hovered; unlike a button, focus gained by pointer or touch SHALL select the focused state, because a field shows where typing will go however it was focused. THE one-time-code input SHALL show focus by the active cell's focused tokens and SHALL NOT draw the focus ring: the focused outline color and width are drawn as a line inside that cell's edge, following its corners and taking no layout space, so that no cell moves as the line appears, moves to another cell or goes; WHERE sys.behavior.focus-style is glow it SHALL also draw the glow around the active cell. A hovered cell SHALL show the state layer and draw no edge; a focused cell SHALL draw no state layer. WHILE the active cell is empty and readOnly is false THE one-time-code input SHALL draw a caret centred in it, comp.one-time-code-input.caret.width wide and one line of the input's text style high, in comp.one-time-code-input.standard.caret.color (comp.one-time-code-input.standard.error.caret.color WHILE error is true), blinking as the platform's own caret does and steady WHERE motion is reduced; a filled active cell SHALL draw no caret. WHEN its state, its active cell, error or disabled changes THE one-time-code input SHALL change its colors and line widths over comp.one-time-code-input.motion.state-duration with comp.one-time-code-input.motion.state-easing, and at once WHERE motion is reduced; a character SHALL appear in its cell at once, with no motion of its own. |
OTC-8 | WHEN the person presses Left Arrow or Right Arrow THE one-time-code input SHALL move the active cell to the cell drawn on that side, in every layout direction (OTC-27), no further than the first cell on one side and the first empty cell — or the last cell WHILE all are filled — on the other; Home SHALL move it to the first cell and End to that furthest one. Up Arrow, Down Arrow, Page Up and Page Down SHALL do nothing in the field and SHALL be left to the page. THE one-time-code input SHALL NOT change the value by any of these keys. |
OTC-9 | WHEN the person presses Backspace THE one-time-code input SHALL, WHILE the active cell is filled, remove its character and keep the active cell where it is, and WHILE the active cell is empty, remove the character before it and move the active cell there; WHEN the person presses Delete it SHALL remove the active cell's character. The characters after a removed one SHALL each move one cell toward the first, so that the value keeps no gap (OTC-3). On an empty field both keys SHALL do nothing. |
OTC-10 | WHEN the person selects all with the platform's own command THE one-time-code input SHALL select the whole value and draw every filled cell as the active cell is drawn (OTC-7); a permitted character typed then SHALL replace the whole value and stand in the first cell, and Backspace or Delete SHALL empty the field. Copy SHALL take the whole value, without group marks, whichever cell is active, and cut SHALL take it and empty the field; WHILE mask is true copy and cut SHALL give nothing and cut SHALL change nothing, as the platform's protected field gives nothing and keeps its text. THE one-time-code input SHALL offer no selection of some cells only: a drag and Shift with an arrow key SHALL select nothing. |
OTC-11 | WHEN text is pasted, dropped or dictated into the field, or given to it by the platform's autofill, THE one-time-code input SHALL read the whole text as one code, wherever the active cell is: it SHALL remove white space and hyphen and dash characters, read the rest by OTC-4, and, IF every remaining character is permitted and there is at least one, replace the whole value with the first length of them. IF that fails WHILE type is numeric and the text holds exactly one run of exactly length digits that no other digit adjoins, it SHALL take that run, so that a whole message pasted with its code in it is read. Otherwise it SHALL change nothing and emit nothing. After a change the active cell SHALL be the first empty cell, or the last WHILE all are filled. |
OTC-12 | THE one-time-code input SHALL ask the platform for the code it received and for the keyboard of its type: it SHALL mark its text element as a one-time code for the platform's autofill (the web's autofill field name one-time-code; each native platform's own content type for a one-time code), so that the code offered above the keyboard or by a password manager fills the field in one step (OTC-11); WHILE type is numeric it SHALL show a numeric keypad, and WHILE type is alphanumeric a general keyboard that capitalizes every character, each without autocorrection, suggestions or spelling marks. THE one-time-code input SHALL NOT read the person's messages itself and SHALL NOT keep or offer codes entered before. |
OTC-13 | WHEN the person changes the value — by typing, removing, cutting, pasting or autofill — THE one-time-code input SHALL emit input carrying the new value, once for each change; WHEN focus leaves the field or the action key is pressed and the value differs from the value at the last commit it SHALL emit change carrying the value; WHEN the person presses the keyboard's action key (Enter, Return, Done) it SHALL emit action and, WHERE the platform has forms, leave the key to the form, which submits as it does from any text input: through its default button (BTN-30) — WHILE the form has a submit button, the platform's own or a Button of type submit, the first of them in document order is pressed, so that its click is emitted and its name and value are sent, and WHILE that button is disabled nothing is submitted; only a form with no submit button is asked directly. A key that commits or cancels an input method's composing text SHALL NOT emit action and SHALL NOT reach the form. THE one-time-code input SHALL emit none of these when the product sets value. |
OTC-14 | WHEN a change by the person leaves the value length characters long — the last empty cell was typed into, a whole code was pasted or filled, or a character of a complete code was replaced — THE one-time-code input SHALL emit complete carrying the value, after the input event of that change and once for it. It SHALL NOT emit complete when the product sets value, and SHALL do nothing else because the code is complete: it SHALL NOT submit a form, move or drop focus, disable itself, or announce anything. What follows a complete code — checking it, saying that it is wrong, moving on — is the product's. |
OTC-15 | WHILE groupSize is a whole number from 1 to length minus 1 THE one-time-code input SHALL draw, after every groupSize cells counted from the first and before the next cell, a group mark: a horizontal line comp.one-time-code-input.separator.width long and comp.one-time-code-input.separator.thickness thick, with round ends, centred on the height of the cells, comp.one-time-code-input.container.gap from the cell on each side, in comp.one-time-code-input.standard.separator.color; the last group holds the cells that remain. The mark SHALL be a drawing only: it SHALL NOT be part of value, of what is copied or of what a form submits, SHALL take no focus and no press of its own, and SHALL be kept from assistive technology. WHILE groupSize is 0 THE one-time-code input SHALL draw no mark and one even row. |
OTC-16 | WHILE mask is true THE one-time-code input SHALL draw, in each filled cell and in place of its character, the mark the platform's own protected text field draws for a character, in the character's color and text style, at once and without first showing what was typed; it SHALL expose the field as a protected text entry, so that assistive technology does not read the characters back, and SHALL keep its type's keyboard and the platform's code autofill (OTC-12). The value, the events and what a form submits SHALL be the same as without mask. |
OTC-17 | WHILE error is true — set by the product, or by the Field that frames it (FLD-8) — THE one-time-code input SHALL render every cell from the error parts of its tokens: at rest a line comp.one-time-code-input.outline.width wide inside each cell's edge in comp.one-time-code-input.standard.error.outline.color, drawn as the focused line is (OTC-7), so that the field itself is marked and not only a text below it; and it SHALL expose the field as invalid to assistive technology. THE one-time-code input SHALL never set error itself and SHALL NOT empty, select or change the value because of it: whether a wrong code is cleared is the product's to decide. The words that say what is wrong are the Field's errorText (FLD-7, FLD-9); the error color is never the only sign. |
OTC-18 | WHEN the product sets value THE one-time-code input SHALL show it, reading it by OTC-4 and keeping its first length permitted characters; IF anything was dropped it SHALL in debug builds report it. It SHALL emit no event for a value the product sets, and setting value to what it already is SHALL change nothing, the active cell included. WHEN the value is set while the field has focus THE active cell SHALL become the first empty cell, or the last WHILE all are filled. |
OTC-19 | IF length is not a whole number of 1 or more THE one-time-code input SHALL draw 6 cells, and IF groupSize is not a whole number from 0 to length minus 1 it SHALL draw one group, and in debug builds SHALL report each. WHEN length becomes smaller than the value is long THE one-time-code input SHALL keep the first length characters, without emitting an event. WHEN type names a value it does not know it SHALL behave as numeric and in debug builds report the unknown value. |
OTC-20 | WHILE disabled is true — set by the product, or by the Field that frames it (FLD-14) — THE one-time-code input SHALL NOT be focusable or editable, SHALL have no active cell and no caret, SHALL NOT emit input, change, complete or action, SHALL expose the disabled state to assistive technology, SHALL be left out of form submission on the web, and SHALL render every cell, character and group mark from the disabled component tokens (of its error parts WHILE error is true). |
OTC-21 | WHILE readOnly is true and disabled is false THE one-time-code input SHALL stay focusable, with its active cell and its focused line, and copyable (OTC-10); SHALL NOT let the person change the value by typing, removing, cutting, pasting or autofill; SHALL draw no caret; SHALL NOT emit input, change or complete; SHALL expose the read-only state to assistive technology; SHALL be submitted with its form on the web; and SHALL render as an enabled field, including its hovered and focused states. |
OTC-22 | THE one-time-code input SHALL take its name, its description and its required state from the Field that frames it, as every control a Field frames does (FLD-10, FLD-11): the Field's label is its accessible name, the Field's supporting text with, in error, the error text after it its description. WHILE label is not empty THE one-time-code input SHALL use it as the accessible name instead, drawn nowhere, for a field no Field frames or one whose visible label is elsewhere. WHILE it has either THE one-time-code input SHALL expose that one alone, over a name the product gives it on the element (aria-label or aria-labelledby); WHILE it has neither and the product gives it a name of its own on the element — aria-label, or aria-labelledby naming an element — THE one-time-code input SHALL expose that name as its accessible name; IF it has none of the three THE one-time-code input SHALL still render and work, and in debug builds SHALL report that it has no accessible name. It SHALL expose how many characters the code has only through its value and the product's own words: it SHALL say no word of its own (OTC-30). |
OTC-23 | THE one-time-code input SHALL never be wider than its layout gives it. WHEN the row needs more width than there is, the cells SHALL share the width equally and become narrower than comp.one-time-code-input.container.width, never narrower than a character of the input's text style with comp.one-time-code-input.container.padding-inline on each side; IF the row still does not fit, it SHALL wrap onto further rows comp.one-time-code-input.container.gap below, each from the start edge: between two groups first, where the group mark at the break SHALL NOT be drawn, and between any two cells where there are no groups or one group alone does not fit. A cell SHALL never be cut, drawn over another or scrolled sideways, and the code SHALL never be drawn at a smaller text size to make it fit. |
OTC-24 | WHILE the text size is enlarged THE one-time-code input SHALL grow with its characters: each cell grows in height with the character's line, keeping comp.one-time-code-input.container.height as a minimum, becomes as wide as the character and its paddings need where that is more than comp.one-time-code-input.container.width, and all cells keep one size; the row then narrows and wraps by OTC-23. At 200% in a layout 288 wide no character SHALL be lost, cut or laid over another part, and nothing SHALL need scrolling in two directions. |
OTC-25 | WHEN the person presses a cell, a group mark or the space between cells THE one-time-code input SHALL take focus and make the pressed cell the active cell WHILE it is filled, and otherwise the first empty cell; it SHALL change nothing else and SHALL draw no press answer, because a press on a field is not an action. WHERE a cell is shorter than the minimum target THE one-time-code input SHALL extend the row's hit area vertically 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. |
OTC-26 | WHERE the platform draws with a person's own forced colors (the web's forced-colors mode, and a platform's equivalent where it has one) THE one-time-code input SHALL draw an edge comp.one-time-code-input.outline.width wide in the platform's control text color around every cell, that edge in the platform's highlight color at the focused width around the active cell, its characters, masks and group marks in the platform's text color and its caret in that color, and a disabled field in the platform's disabled text color; it SHALL rely on no color of its own to show an error, which is carried by the Field's words and the invalid state (OTC-17). |
OTC-27 | WHERE the layout direction is right-to-left THE one-time-code input SHALL keep the cells a left-to-right run: the first character of the code in the leftmost cell of its row, the group marks between the same cells, Right Arrow moving to the cell on the right and Left Arrow to the cell on the left, because a code is a sequence of digits and Latin letters that is written, sent and read aloud left to right in every script and digits are never reversed. Only the row's place SHALL follow the layout: the row, and every row of a wrapped code, SHALL start at the right edge of the width its layout gives it, where the Field's label and help start. A wrapped code SHALL read from the top row down in both directions. |
OTC-28 | THE one-time-code input 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 field is shown THE one-time-code input SHALL draw itself for the new direction at once, without a motion of its own, keeping its value, its active cell and its focus. |
OTC-29 | WHERE the platform has forms (the web) THE one-time-code input SHALL take part in them as a native text input does: it takes name, submits its value — the code alone, without group marks — or an empty string WHILE it holds none, restores it on navigation, resets to the value it was first given, and reports to the form's constraint validation a missing value WHILE its Field says it is required and it is empty. It SHALL report nothing for a code that is shorter than length: an unfinished code is the product's to refuse. |
OTC-30 | THE one-time-code input SHALL have no words of its own: it SHALL draw no word in any language and expose none. Its name is the Field's label or its own label, each the product's (OTC-22); what a required, a wrong or an expired code is called is the Field's requiredText, supportingText and errorText; the group mark and the mask are marks, not words. It SHALL read no key of the product's words. |
OTC-31 | 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 one-time-code input 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 one-time-code input is invalid — except those the one-time-code input owns (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 one-time-code input SHALL take it off that element. WHEN the product sets an aria- attribute the one-time-code input owns THE one-time-code input SHALL report it in debug builds. |
プラットフォーム別の名前対応
パリティは API が同一であることを意味しません。同じ契約を、各プラットフォームの流儀で表現します。
| 仕様 | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| コンポーネント | tanrei-one-time-code-input | TanreiOneTimeCodeInput | TanreiOneTimeCodeInput | TanreiOneTimeCodeInput | OneTimeCodeInput |
value · プロパティ | value | code | value | controller | value |
length · プロパティ | length | length | length | length | length |
type · プロパティ | type | type | type | type | type |
groupSize · プロパティ | groupSize | groupSize | groupSize | groupSize | groupSize |
mask · プロパティ | mask | isMasked | masked | obscureText | secureTextEntry |
label · プロパティ | label | label | label | semanticLabel | accessibilityLabel |
error · プロパティ | error | error | isError | isError | error |
disabled · プロパティ | disabled | disabled | enabled | enabled | disabled |
readOnly · プロパティ | readOnly | readOnly | readOnly | readOnly | readOnly |
input · イベント | input | code | onValueChange | onChanged | onChangeText |
change · イベント | change | onCommit | onCommit | onCommit | onEndEditing |
complete · イベント | complete | onComplete | onComplete | onCompleted | onComplete |
action · イベント | action | onSubmit | keyboardActions | onSubmitted | onSubmitEditing |
| 備考 | A control, so a custom element with a shadow root, form-associated (static formAssociated = true) as the text field is: it takes name, submits the code, restores and resets it, follows <fieldset disabled> and reports valueMissing (OTC-29). <tanrei-field label="Verification code" supporting-text="…" error-text="…"><tanrei-one-time-code-input name="code" group-size="3"></tanrei-one-time-code-input></tanrei-field>: the field is the one element in the Field's default slot and asks it for its name, description, invalid, required and disabled states with the tanrei-field-connect event, as every Tanrei control does. In the shadow root there is exactly one <input type="text"> (type="password" while mask is set), laid over the whole row, with transparent text and no caret of its own, carrying autocomplete="one-time-code", inputmode="numeric" ("text" with autocapitalize="characters" for alphanumeric), autocorrect="off", spellcheck="false", enterkeyhint="done", and aria-label, aria-description, aria-invalid, aria-required and aria-readonly set on that element — not through ElementInternals, which axe cannot see. It has no maxlength and no pattern: the browser would cut or refuse a code pasted or filled with a space in it before the element could read it (OTC-11); the element reads and cuts in beforeinput and input. The cells, the caret and the group marks are aria-hidden elements under the input, drawn from the value; the caret is the element's own, blinking with a CSS animation that prefers-reduced-motion: reduce stops. input is a composed, bubbling CustomEvent whose detail.value is the code; the native input's own input event is stopped at the shadow root. change, complete and action are composed, bubbling events (the host's value is set before each fires). Enter is left to the native input, so a form submits implicitly as from any text input. Attributes are kebab-case (group-size) except readonly, which keeps HTML's name. The host is display: block; the row is a wrapping flex row with direction: ltr whatever the page's, placed at the inline start of the host by the page's direction. Tabular figures are font-variant-numeric: tabular-nums. Under forced-colors: active each cell has a ButtonText border, the active one Highlight. Before the element is defined it has no size and shows nothing: a page that must not jump gives the tag a block size of the cell height in its own stylesheet, and a page that must work without script uses a plain <input autocomplete="one-time-code" inputmode="numeric">, which this element is a drawing of. The product may fill value itself from the browser's own retrieval of a code from a message (the WebOTP API); the element does not call it, because the message's form and the permission are the product's. Words: the element has no words of its own and reads no key of setWords(). | TanreiField("Verification code") { TanreiOneTimeCodeInput(code: $code, length: 6, groupSize: 3, onComplete: verify) }. code is a Binding<String>, written on every change, which is the input event. Built on one TextField (SecureField while masked) laid over the drawn cells, with .textContentType(.oneTimeCode), so that the code from a message is offered above the keyboard, .keyboardType(.numberPad) (.asciiCapable with .textInputAutocapitalization(.characters) for alphanumeric) and .autocorrectionDisabled(). disabled follows .disabled(_:), action is .onSubmit, label is .accessibilityLabel where no TanreiField gives one (it reads \.tanreiField). The cells are hidden from accessibility; the row is laid out with .environment(\.layoutDirection, .leftToRight) and placed by the surrounding direction. | TanreiField(label = "Verification code") { TanreiOneTimeCodeInput(value = code, onValueChange = { code = it }, onComplete = ::verify) }. One BasicTextField whose decorationBox draws the cells from the value; KeyboardOptions(keyboardType = KeyboardType.NumberPassword, autoCorrectEnabled = false) (KeyboardType.Ascii with KeyboardCapitalization.Characters for alphanumeric), semantics { contentType = ContentType.SmsOtpCode } for the platform's autofill, and VisualTransformation for the mask. enabled is the inverse flag; the name, the description and isError come from LocalTanreiFieldState where a TanreiField frames it. The row is drawn under CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) and placed by the surrounding direction. | TanreiField(labelText: 'Verification code', child: TanreiOneTimeCodeInput(controller: code, groupSize: 3, onCompleted: verify)). One EditableText under the drawn cells with autofillHints: [AutofillHints.oneTimeCode], keyboardType: TextInputType.number (TextInputType.visiblePassword with TextCapitalization.characters for alphanumeric), autocorrect: false, enableSuggestions: false and an input formatter that reads by OTC-4. enabled is the inverse flag; the name and the states come from TanreiFieldScope where a TanreiField frames it. The row is wrapped in Directionality(textDirection: TextDirection.ltr) and aligned by the surrounding Directionality. | <Field label="Verification code"><OneTimeCodeInput value={code} onChangeText={setCode} groupSize={3} onComplete={verify} /></Field>. One transparent TextInput over the drawn cells with textContentType="oneTimeCode" (iOS) and autoComplete="sms-otp" (Android; "one-time-code" on iOS), keyboardType="number-pad" ("default" with autoCapitalize="characters" for alphanumeric), autoCorrect={false} and caretHidden. The cells are importantForAccessibility="no" and accessibilityElementsHidden. The name and the states come from FieldContext where a Field frames it. The row sets direction: "ltr" and is aligned by the app's direction. |
トークン
| トークン | 参照先 | 解決値(ライト) |
|---|---|---|
--tanrei-comp-one-time-code-input-caret-width | sys.border.hairline | 1px |
--tanrei-comp-one-time-code-input-container-gap | sys.space.space75 | 6px |
--tanrei-comp-one-time-code-input-container-height | — | 48px |
--tanrei-comp-one-time-code-input-container-padding-inline | sys.space.space50 | 4px |
--tanrei-comp-one-time-code-input-container-shape | sys.shape.corner.small | 6px |
--tanrei-comp-one-time-code-input-container-width | sys.space.space500 | 40px |
--tanrei-comp-one-time-code-input-disabled-outline-width | — | 1px |
--tanrei-comp-one-time-code-input-focused-outline-width | — | 2px |
--tanrei-comp-one-time-code-input-hovered-outline-width | — | 1px |
--tanrei-comp-one-time-code-input-motion-state-duration | sys.motion.role.state.default | 250ms |
--tanrei-comp-one-time-code-input-motion-state-easing | sys.motion.easing.state | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-one-time-code-input-outline-width | sys.border.hairline | 1px |
--tanrei-comp-one-time-code-input-separator-thickness | sys.border.hairline | 1px |
--tanrei-comp-one-time-code-input-separator-width | sys.space.space100 | 8px |
--tanrei-comp-one-time-code-input-standard-caret-color | sys.color.primary | |
--tanrei-comp-one-time-code-input-standard-container-color | sys.color.surface-container-highest | |
--tanrei-comp-one-time-code-input-standard-disabled-caret-color | — | |
--tanrei-comp-one-time-code-input-standard-disabled-container-color | — | |
--tanrei-comp-one-time-code-input-standard-disabled-error-caret-color | — | |
--tanrei-comp-one-time-code-input-standard-disabled-error-container-color | — | |
--tanrei-comp-one-time-code-input-standard-disabled-error-input-color | — | |
--tanrei-comp-one-time-code-input-standard-disabled-error-outline-color | — | |
--tanrei-comp-one-time-code-input-standard-disabled-error-separator-color | — | |
--tanrei-comp-one-time-code-input-standard-disabled-error-state-layer-color | — | |
--tanrei-comp-one-time-code-input-standard-disabled-input-color | — | |
--tanrei-comp-one-time-code-input-standard-disabled-outline-color | — | |
--tanrei-comp-one-time-code-input-standard-disabled-separator-color | — | |
--tanrei-comp-one-time-code-input-standard-disabled-state-layer-color | — | |
--tanrei-comp-one-time-code-input-standard-error-caret-color | sys.color.error | |
--tanrei-comp-one-time-code-input-standard-error-container-color | sys.color.surface-container-highest | |
--tanrei-comp-one-time-code-input-standard-error-input-color | sys.color.on-surface | |
--tanrei-comp-one-time-code-input-standard-error-outline-color | sys.color.error | |
--tanrei-comp-one-time-code-input-standard-error-separator-color | sys.color.on-surface-variant | |
--tanrei-comp-one-time-code-input-standard-error-state-layer-color | comp.one-time-code-input.standard.error.input.color | |
--tanrei-comp-one-time-code-input-standard-focused-caret-color | — | |
--tanrei-comp-one-time-code-input-standard-focused-container-color | — | |
--tanrei-comp-one-time-code-input-standard-focused-error-caret-color | — | |
--tanrei-comp-one-time-code-input-standard-focused-error-container-color | — | |
--tanrei-comp-one-time-code-input-standard-focused-error-input-color | — | |
--tanrei-comp-one-time-code-input-standard-focused-error-outline-color | — | |
--tanrei-comp-one-time-code-input-standard-focused-error-separator-color | — | |
--tanrei-comp-one-time-code-input-standard-focused-error-state-layer-color | — | |
--tanrei-comp-one-time-code-input-standard-focused-input-color | — | |
--tanrei-comp-one-time-code-input-standard-focused-outline-color | — | |
--tanrei-comp-one-time-code-input-standard-focused-separator-color | — | |
--tanrei-comp-one-time-code-input-standard-focused-state-layer-color | — | |
--tanrei-comp-one-time-code-input-standard-hovered-caret-color | — | |
--tanrei-comp-one-time-code-input-standard-hovered-container-color | — | |
--tanrei-comp-one-time-code-input-standard-hovered-error-caret-color | — | |
--tanrei-comp-one-time-code-input-standard-hovered-error-container-color | — | |
--tanrei-comp-one-time-code-input-standard-hovered-error-input-color | — | |
--tanrei-comp-one-time-code-input-standard-hovered-error-outline-color | — | |
--tanrei-comp-one-time-code-input-standard-hovered-error-separator-color | — | |
--tanrei-comp-one-time-code-input-standard-hovered-error-state-layer-color | — | |
--tanrei-comp-one-time-code-input-standard-hovered-input-color | — | |
--tanrei-comp-one-time-code-input-standard-hovered-outline-color | — | |
--tanrei-comp-one-time-code-input-standard-hovered-separator-color | — | |
--tanrei-comp-one-time-code-input-standard-hovered-state-layer-color | — | |
--tanrei-comp-one-time-code-input-standard-input-color | sys.color.on-surface | |
--tanrei-comp-one-time-code-input-standard-outline-color | — | |
--tanrei-comp-one-time-code-input-standard-separator-color | sys.color.on-surface-variant | |
--tanrei-comp-one-time-code-input-standard-state-layer-color | comp.one-time-code-input.standard.input.color | |
--tanrei-comp-one-time-code-input-input-typescale | sys.typescale.body-large | 400 16px/1.625 |
フィクスチャ
基準となる描画パターンです。全プラットフォームが同じ ID でスナップショットを撮り、結果を比較できるようにしています。
empty
label: Verification code partial
value: 123 label: Verification code complete
value: 123456 label: Verification code grouped-empty
groupSize: 3 label: Verification code grouped-partial
value: 1234 groupSize: 3 label: Verification code grouped-complete
value: 123456 groupSize: 3 label: Verification code length-4
value: 4821 length: 4 label: Verification code length-8-grouped
value: 12345678 length: 8 groupSize: 4 label: Verification code alphanumeric-grouped
value: A7K93Q type: alphanumeric groupSize: 3 label: Verification code masked
value: 1234 mask: true label: Verification code error
value: 123456 label: Verification code error: true error-grouped-empty
groupSize: 3 label: Verification code error: true disabled
label: Verification code disabled: true disabled-value
value: 123456 groupSize: 3 label: Verification code disabled: true disabled-error
value: 123456 label: Verification code error: true disabled: true read-only
value: 123456 label: Verification code readOnly: true grouped-partial-rtl
value: 123 groupSize: 3 label: Verification code direction: rtl error-rtl
value: 123456 label: Verification code error: true direction: rtl grouped-ja
value: 123456 groupSize: 3 label: 確認コード 生成元 specs/one-time-code-input.spec.json, tokens/comp/one-time-code-input.tokens.json, design/tokens/
- 要素はフォームに関連付けられます。
nameを受け取り、コードだけを、またはコードがなければ空文字列を送信します。リセットするとvalue属性の値に戻り、フィールドが必須としていて値が空の間は、値がないことを報告します。lengthより短いコードについては何も報告しません。入力途中のコードを受け付けないかどうかは、利用者側で決めます。 - シャドウルートにある
<input>は 1 つだけです。autocomplete="one-time-code"とinputmode="numeric"(alphanumericでは、大文字にするtext)を持ち、maskを付けるとパスワードの入力欄になります。maxlengthとpatternはありません。あると、空白を含めて貼り付けたコードを、読む前にブラウザーが切ってしまうためです。 input、change、complete、actionは、detail.valueを持つ CustomEvent です。actionをキャンセルすると、フォームは送信されません。readOnlyの属性はreadonly、groupSizeの属性はgroup-sizeです。- キャレットは、要素が自分で描いたものです。入力メソッドが変換候補のウィンドウを出すとき、ブラウザーはそれを、アクティブなマスではなく、ネイティブの入力欄のテキストの位置(並びの先頭)に置きます。
- 要素がユーザーのメッセージを読むことはありません。プロダクトが、メッセージのコードをブラウザーに求め、
valueに設定することはできます。 - 要素が定義されるまでは、大きさがありません。マスの高さを確保してください。スクリプトなしで動く必要があるページでは、素の
<input autocomplete="one-time-code" inputmode="numeric">を使います。この要素は、それを描いたものです。
| 観点 | ワンタイムコード入力欄 | テキストフィールド |
|---|---|---|
| 持つもの | ユーザーに送り、1 回だけ入力してもらう、長さの決まった短いコード | 任意のテキスト |
| 見せるもの | 1 文字ごとのマス。コードの長さと、足りない分 | テキスト |
| 受け取るもの | 数字、または数字と大文字の英字 | すべて |
autocomplete="one-time-code" を付けたテキストフィールドでも、コードは正しく入力できます。マス目が要らない場所では、そちらが適しています。パスワード、ユーザーが自分で決めた暗証番号、リカバリーキーやライセンスキー、カード番号、郵便番号はテキストフィールドです。描くほど短い決まった長さがないか、マス目で見せるべきではないためです。プロダクトが数として読む値は数値フィールドです。
- ラベル、マス目、補足、エラーがあれば足りるときは、ワンタイムコードフィールドを使います。フィールドにこの入力欄を入れて自分で書くのは、ワンタイムコードフィールドにない並べ方が必要なときだけです。
- フィールドの中に入れ、何文字のコードか、どこに送ったかを
supportingTextに書きます。 - グループは、メッセージの書き方に合わせて描きます。「123 456」と送るコードには
groupSize="3"を指定します。 - コードが違うことは、フィールドの
errorとerrorTextを使って言葉で伝えます。違っていたコードを消すかどうかは、利用者側で決めます。1 桁だけ違うことがよくあります。 - そろったコードを確かめている間は、
disabledではなくreadOnlyを使います。無効にするとフォーカスが外れ、コードを直すことになったユーザーが位置を見失います。 - 新しいコードを求める手段と、時間の制限があればその説明を、入力欄の近くに置きます。これらはプロダクト側のボタンとテキストです。
completeで確認や送信をする場合は、入力欄の前でそれを伝えます。
- 1 文字ごとの入力欄を並べてコードの入力を作らない。スクリーンリーダーには名前のないテキストボックスが並び、自動入力も貼り付けもできません。
- 貼り付けを禁じない。
maskを付けていても同じです。目で写すしかないコードは、記憶力の試験になります。 - ユーザーに先に伝えずに、フォーカスを動かしたり、フォームを送信したりしない。
- 習慣で
maskを付けない。1 回しか使えず期限のあるコードを隠す必要はほとんどなく、隠すと間違いに気づきにくくなります。 - フィールドの中で
labelを使わない。コントロールの名前はフィールドが与えます。
- ロール
textbox- ラベル付け
- One text box. Its accessible name is the label of the Field that frames it, or its own label where no Field does; its description is the Field's supporting text with, in error, the error text after it. Its value is the whole code as one string. It is exposed as invalid while error is true, required while its Field says so, read-only while readOnly is true, and as a protected text entry while mask is true. The cells, the caret and the group marks are not exposed.
- 最小ターゲット
- 見た目のサイズが小さくても、ヒット領域は最小ターゲットサイズを満たします。 minimum 32px · pointer 44px · spacing 8px · touch 48px
キーボード操作
| キー | 動作 |
|---|---|
| Tab / Shift+Tab | Moves focus to the field, which is one stop however many cells it draws, and on from it. |
| A permitted character | Fills the active cell, replacing what it holds, and moves to the next cell (OTC-6). Other characters do nothing (OTC-4). |
| Left Arrow / Right Arrow | Move the active cell to the cell on that side, in every layout direction, among the filled cells and the first empty one (OTC-8). |
| Home / End | Move the active cell to the first cell, or to the first empty cell (the last cell while all are filled). |
| Backspace / Delete | Remove a character; the ones after it move up, so the value keeps no gap (OTC-9). |
| The platform's select all, copy, cut and paste | Act on the whole code: paste replaces it from the first cell, read leniently (OTC-10, OTC-11). |
| Enter | Emits action, commits a changed value, and submits the enclosing form on the web. |
備考
- One field, not one input per character. A row of separate inputs is a group of unnamed text boxes to a screen reader, breaks the platform's code autofill and paste, turns Backspace and the arrow keys into focus management, and gives a form several values for one answer. Here the cells are a drawing of one native text element.
- For a short code sent to the person and typed back once. A password, a PIN the person chose, a recovery or licence key and a card number are text fields with the matching type and autofill name; a number the product reads as a number is a number field.
- It has no label, help or error text of its own: a Field frames it (FLD-1 to FLD-24) and is where a product says how many characters to expect ("Enter the 6-digit code we sent to …"), that the code was wrong, and that it is required. Errors are words (WCAG 3.3.1, 1.4.1).
- Never moves focus or submits by itself when the code is complete (OTC-14): a change of context on input (WCAG 3.2.2) is the product's decision, taken with the complete event, and a product that submits on complete should say so before the field.
- Codes expire. Where a product limits the time to enter one, the limit, its extension and the way to ask for a new code are the product's, beside the field (WCAG 2.2.1); the field has no timer and no resend control.
- A code that must be copied from another place is a cognitive test unless it can be pasted or filled: paste and the platform's autofill always work and are never blocked, masked or not (WCAG 3.3.8).
- The active cell's focused line is the focus indicator. A design system must keep it visible: without it nothing shows where a replaced character will go.
- The cells are a left-to-right run in a right-to-left layout (OTC-27); the row stands at the start edge with the Field's label.
- Web: a touch browser zooms the page into an input whose text is smaller than 16 px. The character style is 16 px in the default system; a layer that sets a smaller style brings the zoom back.
- Heights are minimums: at 200% text size the cells grow and the row narrows or wraps (OTC-23, OTC-24); nothing is cut (WCAG 1.4.4, 1.4.10).
- Not pressable: a press focuses the field and is not an action (OTC-25), so BTN-8, BTN-9 and BTN-10 are not copied.
- 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/one-time-code-input.spec.json, tokens/sys/measure.tokens.json
- 1 つのテキストボックスです。名前は、囲んでいるフィールドのラベルか、フィールドがないときは自身の
labelです。説明は、フィールドが表示している補足テキストまたはエラーテキストです。値は、コード全体を 1 つの文字列にしたものです。 - エラーの間は invalid として、フィールドが必須としている間は必須として、
readOnlyが true の間は読み取り専用として、maskが true の間はパスワードの入力欄として伝えます。 - マス、キャレット、グループの印は支援技術から隠し、フォーカスも受け取りません。
- ネイティブの挿入位置は、アクティブなマスにあります。マスが埋まっていれば、その文字の前です。挿入位置の文字を読むスクリーンリーダーは、アクティブとして描かれているマスを読みます。
- マスがいくつあっても、Tab で止まる位置は 1 つです。
- 入力欄自身は何も読み上げません。値の変更も、コードがそろったことも読み上げません。現れたエラーは、囲んでいるフィールドが読み上げます。
- 入力メソッドのテキストを確定または取り消すキーは、アクションのキーとして扱わず、フォームも送信しません。
- 押せる範囲は最小ターゲットを満たします。押すと入力欄にフォーカスが移り、押したマスが埋まっていれば、そのマスがアクティブになります。
- テキストを 200% にすると、マスは文字に合わせて大きくなり、細くなり、折り返します。何も切れず、横にスクロールすることもありません。
- 強制カラーモードでは、すべてのマスに縁が付き、アクティブなマスの縁はハイライトの色になります。エラーを、入力欄自身の色で示すことはありません。
- 右から左のレイアウトでも、マスは左から右に並びます。数字の並びが逆になることはありません。マスの並びは右端に、フィールドのラベルの下に置かれます。
- どの言語でも、自身の言葉は持ちません。
Web での既知の不足:
- コードを入力し、置き換え、貼り付ける間にスクリーンリーダーが何を伝えるかは、ブラウザーのアクセシビリティツリーで確かめたもので、スクリーンリーダーで聞いて確かめてはいません。
- 入力メソッドは、Chromium では実際に動かし、Firefox と Safari ではそのイベントだけで確かめています。
- 要素が定義されるまでは、何も描かれません。
- コントロールに名前を付けます。囲んでいるフィールドのラベルか、見えるラベルがほかの場所にあるときは、それと同じ言葉の
labelです。 - 何を入力するのかを言葉で伝えます。何文字か、どこに送ったかです。マス目で長さが分かるのは、マス目が見えるユーザーだけです。
- コードが違う、期限が切れている、必須である、といったことは、フィールドの
errorText、supportingText、requiredで伝えます。色だけで示してはいけません。 - コードを入力できる時間に制限がある場合は、それを伝え、時間の延長か新しいコードを求められるようにします。