# OTP

> Source: https://design.nanatec.co.ke/components/otp/
> A one-time-code field: a row of single-character boxes that behave as one input, with typing, pasting and deletion handled across them.

A one-time-code field. The boxes look separate but behave as one input: typing
advances, Backspace retreats, and a pasted code fills from the box it landed on.
It is form-associated, so it submits under its `name` like any native control.

:::note
This one ships as a web component only. There is no React or Svelte
implementation yet, so the CLI has nothing to copy for those targets.
:::

## Preview

```html
<nana-otp length="6"></nana-otp>
```

## Installation

```bash
npm install @nana-tec/ui-components
```

```js
import "@nana-tec/ui-components/otp";
```

## Usage

Give it a `length` and a `name`. The value is the characters entered so far, so
a partially typed code reads back as a short string.

```html
<nana-otp length="4" name="code"></nana-otp>
```

### Letters as well as digits

`alphanumeric` widens what the boxes accept and switches the on-screen keyboard
away from the numeric one. Anything outside the accepted set is dropped rather
than rejected, so pasting `"12 34-56"` still fills six digit boxes.

```html
<nana-otp length="5" alphanumeric></nana-otp>
```

### Grouping

A long run of boxes is hard to carry from a message, so six splits as 3-3 and
eight as 4-4 on its own. `group-size` sets the split yourself, and `separator`
changes the mark. The mark is hidden from assistive tech, so the code is still
announced as characters rather than punctuation.

```html
<nana-otp length="6"></nana-otp>
```

```html
<nana-otp length="6" group-size="2" separator="·"></nana-otp>
```

### Masked

`masked` renders the characters as dots, for a code that should not be read over
a shoulder.

```html
<nana-otp length="4" masked></nana-otp>
```

### Required

`required` fails constraint validation until every box is filled, so a native
form will not submit a half-entered code.

```html
<form><nana-otp length="4" name="code" required></nana-otp></form>
```

## Keyboard

| Key | Result |
|---|---|
| A character | Fills the box and moves to the next |
| <kbd>Backspace</kbd> | Clears the box, or clears the previous one and moves back if already empty |
| <kbd>←</kbd> / <kbd>→</kbd> | Moves between boxes |
| <kbd>Home</kbd> / <kbd>End</kbd> | Jumps to the first or last box |
| Paste | Fills from the current box onward, ignoring separators |

## API

## Events

| Event | Type | Description |
|---|---|---|
| `nana-input` | `CustomEvent` | The code changed; `detail.value` is the code so far. |
| `nana-complete` | `CustomEvent` | Every box is filled; `detail.value` is the whole code. |

## Accessibility

The host is a `group` labelled by `label`, and each box names its own position
("One-time code, character 3 of 6") so a screen reader announces where focus
landed. The first box carries `autocomplete="one-time-code"`, which lets a
platform offer a code it received by SMS.

## Related components

- [Input](/components/input) — a single free-text field
- [Checkbox](/components/checkbox) — another form-associated control
