# InputOtp

> Takes a one-time code, one digit per box, pasted or typed.

- **Level**: molecule · **Status**: stable · **Role**: input
- **Import**: `import { InputOtp } from "@rrios-forge/ui/molecules/input-otp";`
- **Source**: `packages/ui/src/molecules/input-otp`

**Purpose.** Single-purpose molecule for entering a one-time code as a row of single-character slots. Auto-advances on input, retreats on backspace, distributes paste across the row, and exposes a single concatenated value to the form layer. Mirrors the Input atom's visual contract so the two read as the same family.

**When to use.**
- Two-factor authentication and email/SMS verification flows.
- Account-recovery codes and step-up authentication.
- Any short, fixed-length code that benefits from per-character visual feedback.

**When NOT to use.**
- Variable-length codes or longer secrets — use `Input type="password"`.
- Free-text identifiers or coupons — use `Input` with `pattern`.
- Reading existing codes back to the user as plain text — render with `Code`.

**Composes with.**
- `Field` + `Field.Label` + `Field.Description` + `Field.Error` — wrap the row to inherit the molecule's full ARIA wiring and visual rhythm.
- `Button` for the resend / submit affordances that typically sit beneath the row.
- `Card.tone="elevated"` as the canonical container for a sign-in step.

**Accessibility.**
- `aria-label` is required on the row (e.g. "One-time code"). Each slot is auto-labelled `Code digit N of LENGTH` so screen-reader users always know where they are.
- The control wires `aria-invalid` and `aria-required` on every slot from the row's props; `aria-describedby` propagates so a `Field.Error` anchors correctly.
- The first slot uses `autoComplete="one-time-code"` so iOS/Android surface the SMS code as a keyboard suggestion.
- `inputMode` defaults to `numeric` (numeric soft keyboard); `pattern` defaults to `^\d$` per slot. Override both for alphanumeric codes.
- Backspace clears the focused slot in place; pressing it again retreats. Arrow keys, Home, End and paste behave per platform expectations.
- `disabled` dims the whole row as a single block; the slots remain in the tab order only when the row is enabled.

**Related patterns.**
- `Patterns/Forms · FieldAnatomy` — wrap the row in a `Field` for the canonical Label · Control · Description / Error stack.
- `Patterns/Forms · ValidationFlow` — error placement and tone.
- `Patterns/Feedback · InlineFeedback` — error lives next to its cause.
- `Patterns/Composition · AtomToMolecule` — InputOtp is a leaf molecule, not a primitive.
- `Patterns/Decision Matrix · ComponentChoice` — pick `InputOtp` over `Input` when the input is a fixed-length code.

## Use it for

- OTP / 2FA code → `InputOtp` (molecule)

## Axes

| Axis | Part | Values | Default | Meaning |
|---|---|---|---|---|
| `size` | — | `sm` `md` `lg` | `md` | Ergonomic scale, in three families (control, text, container). |
| `invalid` | — | `true` `false` | `false` | Fails validation: a danger edge, announced as invalid; pair it with an error message. |
| `filled` | — | `true` `false` | `false` | Holds a value: the label stays raised over the field. |
| `disabled` | — | `true` `false` | `false` | Not available: dimmed, skipped by the keyboard, ignores the pointer. |

## Stories

- [Playground](/?path=/story/components-molecules-inputotp--playground) · frame: `/iframe.html?id=components-molecules-inputotp--playground&viewMode=story`
- [Sizes](/?path=/story/components-molecules-inputotp--sizes) · frame: `/iframe.html?id=components-molecules-inputotp--sizes&viewMode=story`
- [States](/?path=/story/components-molecules-inputotp--states) · frame: `/iframe.html?id=components-molecules-inputotp--states&viewMode=story`
- [In Context](/?path=/story/components-molecules-inputotp--in-context) · frame: `/iframe.html?id=components-molecules-inputotp--in-context&viewMode=story`
- [Typing flow (interaction test)](/?path=/story/components-molecules-inputotp--typing-flow) — interaction test · frame: `/iframe.html?id=components-molecules-inputotp--typing-flow&viewMode=story`

## Patterns consulted

- Patterns/Forms · FieldAnatomy
- Patterns/Forms · ValidationFlow
- Patterns/Feedback · InlineFeedback
- Patterns/Composition · AtomToMolecule
- Patterns/Decision Matrix · ComponentChoice

## Always

- Tokens only (R04); variants are semantic axes, never appearance (R02).
- Typography and actions are Poesía atoms, never raw HTML with utilities.
- Vibrant panes need a ground and never nest (ADR-027).
