OTP Field
Forms & choicesBrick 0.1.2

OTP Field

OTP Field is segmented one-time-code entry backed by Atom OTP Field. Atom owns accepted characters, focus movement, paste, masking, completion, validation, reset, and one-value form participation; Brick owns cell recipes and the static Group layout part.

Live example

Built from the published package

Interactive
Choose with confidence

Know when OTP Field is the right part

Use it when

Use it for short verification, recovery, or pairing codes delivered through another channel.

Choose another path when

Do not use it for passwords, permanent PIN storage, arbitrary serial numbers, or unrelated fields. It does not send codes, manage expiry, or submit automatically unless autoSubmit is explicitly enabled.

Installation and imports

tsx
import { Field, OTPField } from "@flowstack-ui/brick";
// or import { OTPField } from "@flowstack-ui/brick/otp-field";
import "@flowstack-ui/brick/styles.css";

The complete stylesheet above is the recommended default. For a measured route-aware build, replace it with the shared foundation and this component's stylesheet:

tsx
import "@flowstack-ui/brick/styles/core.css"; // once at the application root
import "@flowstack-ui/brick/styles/otp-field.css";

Add the modular stylesheet for every other Brick component the route renders. Do not combine modular styles with styles.css or tokens.css.

Quick start

tsx
<Field.Root id="verification" required>
  <Field.Label>Verification code</Field.Label>
  <OTPField.Root length={6} name="code">
    <OTPField.Group>{Array.from({ length: 6 }, (_, index) => <OTPField.Input index={index} key={index} />)}</OTPField.Group>
  </OTPField.Root>
  <Field.Error>Enter all six digits.</Field.Error>
</Field.Root>

Visual recipes and states

Outline, soft, and underline follow the form-family paint. Size changes every cell. Shape changes cell geometry. Attached removes gaps and joins adjacent cells; separated retains individual boundaries. State paint derives from Atom data attributes.

Examples

Use mask for shoulder-surfing resistance, type="alphanumeric" for mixed codes, and getInputLabel={(index, length) => ...} for localization.

Public contract

API

Start with the public parts and root options below. Components with multiple parts separate each area into its own named subsection.

Public exports are OTPField, OTPFieldRoot, OTPFieldGroup, OTPFieldInput, OTPFieldSeparator, OTPFieldRootProps, OTPFieldGroupProps, OTPFieldInputProps, OTPFieldSeparatorProps, OTPFieldVariant, OTPFieldSize, OTPFieldShape, and OTPFieldLayout.

Root propValuesDefault
variantoutline, soft, underlineoutline
sizesm, md, lgmd
shapesharp, roundedrounded
layoutseparated, attachedseparated

underline rejects shape. Root preserves Atom's controlled/uncontrolled value, completion, length (default 6), type (default numeric), pattern, mask (default false), state, autoFocus/autoSubmit (both false), name, form, inputId, localized getInputLabel, and validation props. Input accepts an optional explicit index. Separator defaults visually to an en dash; Group has static div props.

Shared responsibility

Accessibility

Use Field for the visible group label. Each cell receives a position-aware accessible name; localize it with getInputLabel. Only the first cell owns native required validity so the segmented control contributes one validation target and one named form value. Masking is visual privacy, not secure storage.

Responsive behavior

Groups use logical flex layout and may wrap only at group boundaries. Keep code length appropriate for the available width. RTL preserves authored cell order while logical groups and separators remain contained.

Stable visual contract

Styling and tokens

Customization

Prefer recipe props and semantic tokens, then the two component variables. Compose Groups and Separators to express readable code grouping; do not alter cell order visually.

Tokens and CSS hooks

Public variables are --brick-otp-size and --brick-otp-radius. Root exposes data-variant, data-size, data-shape, data-layout, and data-slot. Stable classes and slots are listed above.

Advanced reference

Open these details only when you need to inspect DOM ownership, native forwarding, or lower-level composition.

Maintainer resources

Tests, playground evidence, source notes, and release history remain available without crowding the plug-and-play guide.