Entrada de código de un solo uso
Recibe un código corto enviado a la persona (un código de inicio de sesión o de verificación) como un único valor de texto dibujado en celdas separadas, de modo que se ven su longitud y lo que aún falta, y la plataforma puede rellenarlo en un solo paso.
Avanzado
La mayoría de los productos usan One-time-code field, del que este componente forma parte.
- Categoría
- Entradas de texto
- Tokens
comp.one-time-code-input- Nivel
- Base
- Se usa en
- One-time-code field
- Web
tanrei-one-time-code-inputschedule - SwiftUI
TanreiOneTimeCodeInputradio_button_unchecked - Jetpack Compose
TanreiOneTimeCodeInputradio_button_unchecked - Flutter
TanreiOneTimeCodeInputradio_button_unchecked - React Native
OneTimeCodeInputradio_button_unchecked
Generado a partir de docs/status/status.json, specs/one-time-code-input.spec.json
Una entrada de código de un solo uso dentro de un campo, y otra cuyo código rechazó el producto
Usa una entrada de código de un solo uso para un código corto que un producto envió a la persona y que le pide de vuelta una sola vez: para iniciar sesión, para confirmar una dirección de correo electrónico o un número de teléfono, para aprobar un pago. Las celdas muestran la longitud del código y cuánto falta todavía.
Es una sola entrada para todo el código, no una entrada por carácter. Hay un único valor de texto, una única parada para la tecla Tab y un único cuadro de texto para la tecnología de apoyo; las celdas son un dibujo de ese valor. Por eso el autorrelleno de códigos de la plataforma lo rellena en un solo paso, un texto pegado llega entero y un lector de pantalla lee un único cuadro de texto con nombre.
Es un componente avanzado: el control sin nada más, para un producto que compone el suyo. No tiene etiqueta, ayuda ni texto de error propios. La mayoría de los productos quieren el campo de código de un solo uso, que es esta entrada dentro de un campo, listo para usarse.
Se usa en el campo de código de un solo uso. Para componer el tuyo, ponla dentro de un campo, que le da nombre, la describe, la marca como obligatoria y la pone en su estado de error; los ejemplos de esta página están escritos así, un nivel por debajo del campo de código de un solo uso. Donde la etiqueta visible está en otro lugar (el título de un diálogo), úsala sola y da label, que nunca se dibuja.
En la web es <tanrei-one-time-code-input>. Las demás plataformas todavía no la han implementado.
value es el código introducido hasta el momento: como máximo length caracteres, que son dígitos o, con alphanumeric, dígitos y letras mayúsculas, sin separador, sean cuales sean los grupos dibujados.
<form>
<tanrei-field label="Código de verificación"
supporting-text="Introduce el código de 6 dígitos que enviamos a tu teléfono."
error-text="El código no es correcto. Revisa el mensaje e inténtalo de nuevo."
required required-text="Obligatorio">
<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');
// La persona cambió el valor. Ya es el nuevo.
code.addEventListener('input', () => (field.error = false));
// Se rellenó la última celda, o se pegó o se rellenó un código entero. Nada más ocurre por sí solo.
code.addEventListener('complete', async (e) => {
code.readOnly = true;
const right = await verify(e.detail.value);
code.readOnly = false;
field.error = !right;
});
</script>// Un componente avanzado —una pieza de la que se construyen otros— se importa desde la entrada advanced.
import { Field } from '@tanrei/react';
import { OneTimeCodeInput } from '@tanrei/react/advanced';
<Field label="Código de verificación" error={wrong}
supportingText="Introduce el código de 6 dígitos que enviamos a tu teléfono."
errorText="El código no es correcto. Revisa el mensaje e inténtalo de nuevo.">
<OneTimeCodeInput name="code" groupSize={3} value={code}
onInput={(event) => setCode(event.detail.value)}
onComplete={(event) => verify(event.detail.value)} />
</Field>Cuatro celdas, ocho celdas en dos grupos, letras y dígitos, un código oculto, uno de solo lectura y uno deshabilitado
| Parte | Qué es |
|---|---|
| Celda | Una caja por cada carácter del código, vacía o con un carácter. Una celda vacía y una rellena son la misma caja |
| Carácter | El carácter de una celda rellena, en el estilo de entrada del campo de texto y con cifras tabulares. Con mask, ocupa su lugar la marca que dibuja un campo de contraseña |
| Celda activa | Mientras la entrada tiene el foco, la celda a la que va el siguiente carácter: la primera celda vacía, o la última cuando todas están rellenas. Dibuja la línea de foco por dentro de su borde, que es a la vez el indicador de foco de la entrada y la marca de su posición |
| Cursor de texto | En una celda activa vacía. Una celda activa rellena no dibuja ninguno: el siguiente carácter sustituye al que contiene |
| Marca de grupo | Con groupSize, una línea corta cada tantas celdas. Es solo un dibujo: no forma parte del valor, ni de lo que se copia, ni de lo que envía un formulario |
Una celda es tan alta como un campo de texto mediano, de modo que, en un mismo formulario, una entrada de código de un solo uso y un campo de texto tienen la misma altura. Hay un solo tamaño y un solo aspecto; un sistema de diseño define en su capa la altura, las esquinas y el relleno de la celda.
La fila empieza en el borde de inicio y es tan ancha como necesitan sus celdas: seis celdas en dos grupos miden 284 de ancho en el sistema predeterminado, lo que cabe en una pantalla de 320. Donde hay menos sitio, las celdas se reparten el ancho y se estrechan, hasta quedar en un carácter con un pequeño margen interior a cada lado; después la fila salta de línea: primero entre dos grupos, sin la marca en el salto, y entre celdas donde no hay grupos. Una celda nunca se corta, y el código nunca se dibuja más pequeño para que quepa.
| Cuándo | Qué ocurre |
|---|---|
| Se escribe un carácter permitido | Rellena la celda activa, sustituyendo lo que contiene, y la celda siguiente pasa a ser la activa. En la última celda, la celda activa no cambia, de modo que otro carácter sustituye al último |
| Se escribe cualquier otro carácter | Nada. Una celda solo contiene lo que puede contener un código |
| Retroceso | Una celda activa rellena pierde su carácter; una vacía pierde el carácter anterior. Lo que sigue se desplaza hacia el inicio: el valor no tiene huecos |
| Flecha izquierda y Flecha derecha, Inicio, Fin | Mueven la celda activa entre las celdas rellenas y la primera vacía. Flecha arriba y Flecha abajo no hacen nada |
| Seleccionar todo y, después, un carácter | Sustituye el código entero. No se puede seleccionar solo algunas celdas |
| Pegar, soltar, autorrelleno, dictado | Todo el texto se lee como un solo código, esté donde esté la celda activa |
Lo que se escribe o se pega se lee con tolerancia. Los dígitos de otras escrituras y los dígitos y letras de ancho completo se leen como sus formas ASCII, y las letras minúsculas como mayúsculas; el valor siempre es ASCII y se puede comparar tal cual con el código que se envió.
Un texto pegado pierde sus espacios, guiones y rayas: 123 456 y 123-456 son 123456. Con dígitos, en un texto más largo se busca exactamente una serie de exactamente length dígitos, de modo que se puede pegar un mensaje entero («Tu código es 123456.»). Lo que sea ambiguo no cambia nada.
El texto que un método de entrada todavía no ha confirmado se dibuja en las celdas, subrayado, y no cambia ningún valor hasta que se confirma.
| Evento | Cuándo |
|---|---|
input |
Cada cambio que hace la persona. Lleva el valor nuevo |
complete |
Un cambio hecho por la persona dejó el valor con length caracteres. Después del input de ese cambio, una vez |
change |
El foco salió de la entrada, o se pulsó Enter, y el valor es distinto del último confirmado |
action |
Enter. En un formulario en la web, el formulario se envía entonces como desde cualquier campo de entrada de texto |
Ninguno se emite cuando el producto define value. Y no ocurre nada más cuando el código está completo: la entrada no envía el formulario, no mueve el foco, no se deshabilita ni anuncia nada. Lo que sigue a un código completo es cosa del producto.
Anatomía
Anatomía
empty, tal como lo dibuja el paquete web.| Parte | Descripción |
|---|---|
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 · opcional | Drawn in the active cell while the field has focus and that cell is empty: where the next character goes. |
4 separator · opcional | A short line between two groups of cells. A drawing only: not part of the value and kept from assistive technology. |
Propiedades
| Propiedad | Tipo | Valor predeterminado | Descripción |
|---|---|---|---|
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. |
Eventos
| Evento | Descripción |
|---|---|
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). |
Estados
Comportamiento
Requisitos en formato EARS. Cada implementación de plataforma se prueba contra estos identificadores. El texto de los requisitos se muestra tal como está en la especificación, en inglés.
| ID | Requisito |
|---|---|
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. |
Correspondencia de nombres por plataforma
Paridad no significa API idénticas. Cada plataforma expresa el mismo contrato con su propio estilo.
| Especificación | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| Componente | tanrei-one-time-code-input | TanreiOneTimeCodeInput | TanreiOneTimeCodeInput | TanreiOneTimeCodeInput | OneTimeCodeInput |
value · Propiedad | value | code | value | controller | value |
length · Propiedad | length | length | length | length | length |
type · Propiedad | type | type | type | type | type |
groupSize · Propiedad | groupSize | groupSize | groupSize | groupSize | groupSize |
mask · Propiedad | mask | isMasked | masked | obscureText | secureTextEntry |
label · Propiedad | label | label | label | semanticLabel | accessibilityLabel |
error · Propiedad | error | error | isError | isError | error |
disabled · Propiedad | disabled | disabled | enabled | enabled | disabled |
readOnly · Propiedad | readOnly | readOnly | readOnly | readOnly | readOnly |
input · Evento | input | code | onValueChange | onChanged | onChangeText |
change · Evento | change | onCommit | onCommit | onCommit | onEndEditing |
complete · Evento | complete | onComplete | onComplete | onCompleted | onComplete |
action · Evento | action | onSubmit | keyboardActions | onSubmitted | onSubmitEditing |
| Notas | 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. |
Tokens
| Token | Alias de | Valor resuelto (claro) |
|---|---|---|
--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 |
Fixtures
Representaciones canónicas. Todas las plataformas capturan cada fixture con el mismo identificador para poder comparar los resultados.
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: 確認コード Generado a partir de specs/one-time-code-input.spec.json, tokens/comp/one-time-code-input.tokens.json, design/tokens/
- Es un elemento asociado a formularios. Recibe
namey envía solo el código, o una cadena vacía. Se restablece al valor del atributovalue, y notifica al formulario que falta un valor mientras su campo dice que es obligatorio y está vacío. Un código más corto quelengthno se notifica de ningún modo: rechazar un código sin terminar te corresponde a ti. - En el shadow root hay exactamente un
<input>, conautocomplete="one-time-code"einputmode="numeric"(text, con mayúsculas automáticas, paraalphanumeric); conmaskes un campo de entrada de contraseña. No tienemaxlengthnipattern: el navegador cortaría un código pegado con un espacio dentro antes de que se pudiera leer. input,change,completeyactionson CustomEvents condetail.value. Cancelaactionpara impedir que el formulario se envíe.- El atributo de
readOnlyesreadonly, y el degroupSizeesgroup-size. - El cursor de texto es un dibujo propio del elemento. Donde un método de entrada muestra una ventana de candidatos, el navegador la coloca según el texto del campo de entrada nativo, al inicio de la fila, y no según la celda activa.
- El elemento no lee los mensajes de la persona. Un producto puede pedir él mismo al navegador el código de un mensaje y definir
value. - Antes de que el elemento esté definido no tiene tamaño. Reserva la altura de una celda. Una página que deba funcionar sin script usa un
<input autocomplete="one-time-code" inputmode="numeric">sencillo, del que este elemento es un dibujo.
| Aspecto | Entrada de código de un solo uso | Campo de texto |
|---|---|---|
| Contiene | Un código corto de longitud conocida, enviado a la persona y que esta escribe de vuelta una vez | Cualquier texto |
| Muestra | Una celda por cada carácter: la longitud del código y cuánto falta | El texto |
| Acepta | Dígitos, o dígitos y letras mayúsculas | Cualquier cosa |
Un campo de texto con autocomplete="one-time-code" también recibe un código correctamente, y es la elección adecuada donde no se quieren celdas. Una contraseña, un PIN que eligió la persona, una clave de recuperación o de licencia, un número de tarjeta y un código postal son campos de texto: no tienen una longitud corta y fija que merezca dibujarse, o no deben mostrarse en celdas. Un número que el producto lee como número es un campo numérico.
- Usa el campo de código de un solo uso donde una etiqueta, las celdas, una ayuda y un error sean todo lo que necesitas. Escribe a mano un campo con esta entrada dentro solo para una organización que el campo de código de un solo uso no ofrezca.
- Pon la entrada en un campo y di en su
supportingTextcuántos caracteres se esperan y adónde se envió el código. - Dibuja los grupos como los escribe el mensaje:
groupSize="3"para un código enviado como «123 456». - Di con palabras que un código es incorrecto, con
erroryerrorTextdel campo. Decide tú si un código incorrecto se borra: a menudo solo un dígito está mal. - Usa
readOnly, nodisabled, mientras se comprueba un código completo. Una entrada deshabilitada pierde el foco, y una persona que después deba corregir el código pierde su posición. - Pon junto a la entrada la forma de pedir un código nuevo y, si lo hay, el límite de tiempo. Son un botón y un texto tuyos.
- Si compruebas o envías en
complete, dilo antes de la entrada.
- No construyas la entrada de un código con un campo de entrada por carácter. Un lector de pantalla se encuentra con varios cuadros de texto sin nombre, y el autorrelleno y el pegado no pueden rellenarlos.
- No impidas pegar, esté el código oculto o no. Un código que hay que copiar a ojo es una prueba de memoria.
- No muevas el foco a otro lugar ni envíes el formulario sin avisar antes a la persona.
- No uses
maskpor costumbre. Un código que se usa una vez y caduca rara vez necesita ocultarse, y ocultarlo hace que un error sea más difícil de ver. - No uses
labeldentro de un campo. El campo da nombre al control.
- Rol
textbox- Etiquetado
- 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.
- Objetivo mínimo
- El área de pulsación cumple el tamaño mínimo de objetivo aunque el tamaño visual sea menor. minimum 32px · pointer 44px · spacing 8px · touch 48px
Teclado
| Teclas | Acción |
|---|---|
| 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. |
Notas
- 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.
Generado a partir de specs/one-time-code-input.spec.json, tokens/sys/measure.tokens.json
- Es un solo cuadro de texto. Su nombre es la etiqueta del campo, o su propio
labeldonde ningún campo lo enmarca; su descripción es el texto de apoyo o de error que muestra el campo; su valor es el código entero como una sola cadena. - Se expone como no válido mientras está en error, como obligatorio mientras su campo lo dice, como de solo lectura mientras
readOnlyes true y como un campo de contraseña mientrasmaskes true. - Las celdas, el cursor de texto y las marcas de grupo quedan ocultos para la tecnología de apoyo y no reciben el foco.
- El punto de inserción nativo está en la celda activa (antes de su carácter mientras la celda está rellena), de modo que un lector de pantalla que lee el carácter del punto de inserción lee la celda que se dibuja como activa.
- Es una sola parada para la tecla Tab, dibuje las celdas que dibuje.
- La entrada no anuncia nada por sí misma: ni un cambio ni un código completo. Un error que aparece lo anuncia el campo que la rodea.
- La tecla que confirma o cancela el texto de un método de entrada no es la tecla de acción y no envía el formulario.
- El área de pulsación cumple el objetivo mínimo. Una pulsación da el foco a la entrada y hace activa la celda pulsada mientras esa celda esté rellena.
- Con el texto al 200%, las celdas crecen con sus caracteres, se estrechan y saltan de línea; nada se corta y nada se desplaza hacia los lados.
- En colores forzados, cada celda gana un borde, y el borde de la celda activa es del color de resaltado. Ningún color propio de la entrada muestra un error.
- En un diseño de derecha a izquierda, las celdas siguen siendo una serie de izquierda a derecha (los dígitos nunca se invierten) y la fila se sitúa en el borde derecho, bajo la etiqueta del campo.
- No incluye textos propios, en ningún idioma.
Carencias conocidas en la web:
- Lo que dicen los lectores de pantalla mientras un código se escribe, se sustituye y se pega se ha leído en los árboles de accesibilidad de los navegadores, no se ha oído con un lector de pantalla.
- Los métodos de entrada se han accionado de verdad en Chromium; en Firefox y Safari, solo a través de sus eventos.
- Antes de que el elemento esté definido, no se dibuja nada.
- Da un nombre al control: la etiqueta del campo que lo rodea, o su propio
labeldonde la etiqueta visible está en otro lugar, con las mismas palabras. - Di con palabras qué se espera: cuántos caracteres, y adónde se envió el código. Las celdas muestran la longitud solo a quienes las ven.
- Di que un código es incorrecto, que ha caducado o que es obligatorio con
errorText,supportingTextyrequireddel campo. El color nunca es la única señal. - Donde el tiempo para introducir un código sea limitado, dilo, y deja que la persona pida más tiempo o un código nuevo.