OTP / PIN Input
Free4, 5 and 6-digit OTP/PIN inputs with auto-advance, paste support, arrow-key navigation, mask mode and status variants.
</>sv-otp-input otppinsecurity
import { SvOtpInputComponent } from '@styloviz/forms';Demo & usage
Basic usage
Usage example — open the gallery for the full interactive demo.
An interactive demo for this component lives in the gallery.
Open live demoMore examples
Masked PIN with error state
example.htmlAngular
1 lines
<sv-otp-input [length]="4" [mask]="true" status="error" hint="Incorrect code" (complete)="check($event)" />
Reactive forms
Implements ControlValueAccessor; the bound value hydrates the cells, so initial values and resets render.
example.htmlAngular
1 lines
<sv-otp-input formControlName="code" label="Verification code" [length]="6" (complete)="verify($event)" />
When to use
- Entering a short verification code or PIN (2FA, email confirmation, transactions).
- You want auto-advance, paste-the-whole-code and per-cell navigation.
- For longer secrets use a password Text Field instead.
Async states
None — this component has nothing to load, so it has no loading, empty or error state to drive.
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| length | 4 | 5 | 6 | 6 | Number of code cells. |
| value | string (two-way) | '' | Current code value (two-way). |
| variant | OtpInputVariant | 'default' | Visual variant of the cells. |
| size | OtpInputSize | 'md' | Cell size: sm, md or lg. |
| status | OtpInputStatus | 'idle' | Validation status: idle, error, success or loading. |
| mask | boolean | false | Mask entered digits (password-style). |
| disabled | boolean | false | Disable all cells. |
| label | string | '' | Accessible label for the code group. |
| hint | string | '' | Helper/error text shown below the cells. |
| autoFocus | boolean | false | Focus the first cell on render. |
| mode | OtpInputMode | 'cells' | How the code is actually taken from the user. |
| webOtp | boolean | false | Ask the browser to read the code out of an incoming SMS. |
| clearOnError | boolean | true | Wipe the code when it is rejected, so the user is not editing a code that has already been refused. |
| errorMessage | string | '' | Client-side validation message. |
| serverError | SvServerError | null | A rejection reported by the server about this value. Self-expiring. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| complete | string | Emitted with the full code once every cell is filled. |
| changed | string | Emitted on every change to the partial code. |
| codeCleared | void | Emitted when a rejected code was wiped — see `clearOnError`. |
| valueChange | string | Emits the new `value` whenever it changes — the output half of `[(value)]`. |
Customization & theming
- Configure `length` (4–6), `variant` (default · filled · underline · ghost), `size` and optional `mask` mode.
- Error / success / loading `status` with a `hint` message; `label`, `disabled`, `autoFocus`.
- Two-way bind `[(value)]` or a reactive control (CVA); listen to `(complete)` and `(changed)`.
Best practices
- Do: Handle the `complete` event to verify as soon as the final digit lands.
- Do: Support pasting the full code — users copy it from email/SMS.
- Tip: Use `mask` only for sensitive PINs; verification codes are usually fine visible.
Accessibility
- Each cell is a labelled numeric input (`inputmode="numeric"`, `autocomplete="one-time-code"`) with arrow-key, Backspace/Delete navigation and full-code paste.
- The group is labelled and `aria-describedby`-linked to its hint; status/error/success messages are announced through an `aria-live` region (assertive on error).
- Cells set `aria-invalid` when `status="error"`; the bound value hydrates the cells so controlled/reset states render correctly.
Feedback on OTP / PIN Input
Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.