Pricing

OTPInput handbook

v1.1.0<br> · @snowui-design-system/components

License: Read the complete LICENSE before first reading component documentation, source, or npm usage instructions. Reuse this review within the same task and version.

Overview

A 4–8 digit one-time-code input supporting full-code paste, SMS autofill, and native form submission and reset.

When to use it

Enter a numeric one-time code already sent by an application or identity provider. This component handles entry; the application sends and verifies codes and owns any countdown.

  • Defaults to 6 digits; supports 4, 5, 6, 7, or 8. Ordinary entry filters non-digits and limits length. Paste is validated strictly as described below.

  • oncomplete runs only when user entry produces a new complete value. Initialization, external assignment, and repeated synchronization of the same complete value do not trigger it.

  • name, form, required, disabled, readonly, and autocomplete="one-time-code" are applied to the real input.

Quick start

<script lang="ts">    import { OTPInput } from "@snowui-design-system/components";    let code = $state("");</script> <OTPInput bind:value={code} aria-label="Verification code" oncomplete={(value) => console.log(value)} />

API

Keyword Type Default Description
value string "" Normalized numeric value supporting bind:value; external changes update the displayed digits.
defaultValue string — Initial value when value is omitted, and the native form reset baseline. When both are supplied, value controls the current display and defaultValue controls reset.
length OTPLength 6 Number of code digits. Changing it immediately truncates the value to the new length and rebuilds the visual slots.
oncomplete (value: string) => void — Called when user entry produces a new complete value; initialization, external assignment, and unchanged repeated values do not trigger it.
name string — Native field name. FormData collects the normalized complete or partial value when enabled.
form string — Associate the input with an external form by its id.
disabled boolean false Prevent focus and editing, and exclude the field from FormData.
readonly boolean false Allow focus, selection, and submission while preventing editing.
required boolean false Enable native required-field validation.
autocomplete HTMLInputAttributes["autocomplete"] "one-time-code" Use the SMS one-time-code autofill semantic by default.
autofocus boolean — Request initial focus. Avoid competing with other autofocus controls.
tabindex number — Native keyboard focus order.
id string — The real input id, usable by an associated label's for attribute.
title string — Native tooltip text; does not replace an accessible name.
invalid boolean false Persistent caller-controlled error state, with aria-invalid and Input's border, focus ring, error text, and shake. The internal two-second timer does not clear this Prop.
error string | Snippet Locale message Error text or content. An explicit value takes precedence over the default locale message.
oninput (event: Event) => void — Called after user entry is normalized or an accepted paste is written. Rejected paste does not trigger it.
onchange (event: Event) => void — Forward the real input's native change event.
onfocus (event: FocusEvent) => void — Called after the real input gains focus and the active slot is synchronized.
onblur (event: FocusEvent) => void — Called after the real input loses focus and the active indicator is hidden.
onkeydown (event: KeyboardEvent) => void — Called before native key handling; preventDefault can cancel the browser default action.
onpaste (event: ClipboardEvent) => void — Called before paste validation; preventDefault cancels the component's entire paste handling.
class / style / Frame Props FrameProps — Applicable capabilities are applied to the public root Frame. tag, children, and F-03B enableScaleObserver are excluded; shared host filtering forwards valid native attributes only to the input.

Public style overrides: --snowui-otp-input-gap-override, --snowui-otp-input-size-override, --snowui-otp-input-radius-override, --snowui-otp-input-font-size-override, and --snowui-otp-input-line-height-override.

Usage boundaries and details

  • One real <input type="text" inputmode="numeric"> owns keyboard entry, selection, deletion, replacement, autofill, forms, and assistive technology. The root group and input share an explicit accessible name; slots are aria-hidden visuals. aria-describedby associates errors, announced through a polite status region.

  • Click a filled slot to select its character for replacement. The active slot follows the real input selection. Native arrows, Home, End, Backspace, Delete, selection replacement, and undo remain available.

  • Ordinary entry keeps only ASCII digits 0–9 and activates the next slot. Pointer and keyboard navigation cannot skip beyond the first empty slot. Filled slots remain selectable for replacement.

  • Paste validates the entire text first. Whitespace, separators, letters, and full-width digits are rejected rather than silently filtered.

  • A pasted value exactly equal to length always replaces the entire code from the first slot, regardless of the current active position.

  • At a later slot (index > 0), a paste can fill the current suffix if a continuous prefix exists and the text fits the remaining slots. Partial filling is allowed: with a 4-digit code containing 12, pasting 34 at slot three produces 1234; pasting 3 produces 123.

  • At the first slot, too few or too many pasted digits clear the entire value and show an error. At a later slot, overflow is rejected atomically. Any non-numeric paste is also rejected without changing the current value.

  • Built-in paste errors use Input's border, focus ring, shake, and error typography for two seconds. Another invalid paste restarts the timer. Reset and unmount clean up timers; errors do not lock entry. External invalid remains caller-controlled.

  • The active indicator moves with TAB_INDICATOR_MOTION; digits appear or replace with NUMBER_POP_APPEAR_MOTION. Reduced motion preserves value, semantics, and focus and presents final positions directly.

  • Provide aria-label, aria-labelledby, or an associated label. Disabled values are excluded from submission; readonly values are included.

  • Form reset restores defaultValue, or the first value when no defaultValue was supplied. A canceled reset preserves the current value. The listener checks the current input.form, so changing form reassociates the field. Repeated resets and unmount clean up the deferred reset timer.

OTPInput style overrides

Read the full LICENSE first; reuse that review for the same task, version, and scope.

First use public component Props to match the desired appearance, preserving the existing look where possible. If changes are necessary, follow the style selection and override order: use your own class (including Tailwind already in the project) or an instance style. The names below are public overrides actually consumed by source; check their scope and do not modify private DOM. Choose the correct SnowUI token family. External apps need not install SnowUI website utilities.

Variable Purpose and default reference
--snowui-otp-input-font-size-override default: var(--text-16)
--snowui-otp-input-gap-override default: var(--gap-2)
--snowui-otp-input-line-height-override default: var(--leading-14)
--snowui-otp-input-radius-override default: var(--radius-3)
--snowui-otp-input-size-override default: var(--size-10)

Design guide · Tokens · Composition boundaries

OTPInput types and states

Required Props: no named required Props.

Two-way binding: bind:value.

Inherited declaration: Omit<FrameProps, "tag" | "children" | "enableScaleObserver" | "oninput" | "onchange" | "onfocus" | "onblur" | "onkeydown" | "onpaste">. Consult the public base component documentation for inherited capabilities; excluded fields are unavailable as inherited Props.

Shared Frame API · Back to API

The following type declarations are actually referenced by public Props and come from source. A Svelte Snippet denotes a content fragment; ComponentProps denotes the Props of the corresponding component.

OTPLength

Source: components/src/components/OTPInput.svelte

export type OTPLength = 4 | 5 | 6 | 7 | 8;

External type source:

  • HTMLInputAttributes — svelte/elements