Pin Input
A row of single-character cells for one-time codes and PINs on Ark UI's PinInput machine — autofocus advance, paste-to-fill, masking, OTP autofill, and native form submission.
PinInput is a row of single-character cells for one-time codes, PINs, and confirmation tokens, built on Ark UI's PinInput machine. Each cell is a real <input>; the machine handles autofocus advance, paste-to-fill across cells, backspace navigation, masking, and otp autofill, and a hidden input backs form submission.
import { PinInput } from '@42/ui-react/pin-input';
<PinInput length={6} otp />The value is a single string — the machine speaks string[] (one char per cell), but value / defaultValue take a string and onChange / onComplete hand one back. Like the rest of the family it carries its own label, description, error, and required — no external wrapper needed — and passing error flips the cells to the invalid (red) state. Omit them and it still composes cleanly inside a Field.
Playground
Component
Dir
Presets
Props
Code
<Component label="Verification code" length={4} size="md" type="numeric"/>One-time code
otp opts the cells into autocomplete="one-time-code", so iOS / Android surface the SMS code above the keyboard and fill every cell with one tap.
Masked
mask hides the entered characters like a password field — for PINs that shouldn't be shoulder-surfed.
Value type
type constrains what each cell accepts: numeric (default), alphanumeric, or alphabetic. Numeric cells also hint the numeric keyboard on mobile.
Sizes
Five sizes — xs through xl — matching the rest of the family. Each cell is a square that scales with the text.
Code
<PinInput size="xs" length={4} /><PinInput size="sm" length={4} /><PinInput size="md" length={4} /><PinInput size="lg" length={4} /><PinInput size="xl" length={4} />Colors
Like the rest of the form family, the cells are palette-independent at rest — only the focus ring references --c-solid, so each palette tints the focused cell for free. See Colors.
Code
<PinInput color="brand" length={4} /><PinInput color="green" length={4} /><PinInput color="purple" length={4} />Invalid & disabled
invalid swaps every cell's border and ring to red regardless of color (and sets aria-invalid). disabled dims and blocks the cells; readOnly keeps full contrast but rejects edits.
Code
<PinInput invalid defaultValue="12" length={4} /><PinInput disabled defaultValue="1234" length={4} /><PinInput readOnly defaultValue="1234" length={4} />With label, description & error
label, description (helper text), and error are built in via Field — no external wrapper needed. Passing error flips the cells to the invalid (red) state; required adds the semantic flag and a red asterisk on the label.
Code
<PinInput length={6} otp label="Verification code" description="Enter the 6-digit code from your authenticator app." /><PinInput length={6} required label="Verification code" /><PinInput length={6} label="Verification code" error="That code is incorrect" defaultValue="12" />If you omit these props, the cells still compose inside an outer Field, inheriting its invalid, disabled, and readOnly from context — so an error on the field flips them red automatically.
Controlled
Drive the value from state. onChange fires on every keystroke with the joined string; onComplete fires once every cell is filled.
'use client';
import { useState } from 'react';
import { PinInput } from '@42/ui-react/pin-input';
export function CodeInput() {
const [value, setValue] = useState('');
return (
<PinInput
length={6}
value={value}
onChange={setValue}
onComplete={(code) => verify(code)}
/>
);
}Forms
A name wires the hidden input into native <form> submission and FormData — the value submits as the joined string.
<form action={verify}>
<PinInput name="code" length={6} />
</form>API
Prop
Type
Accessibility
- Full PinInput keyboard model from Ark: typing advances to the next cell,
Backspaceclears and steps back,←/→move between cells, and pasting a code fills every cell at once. - Each cell is labelled (
Pin input 1 of N, …) and the cells are grouped, so assistive tech announces position and length. invalidsetsaria-invalidon the cells. Passlabel/description/errorfor an accessible name and error text via the built-inField, or compose inside an outerFieldinstead.- A hidden input backs form submission; pass
nameto include the joined value, andotpto enable OS-level one-time-code autofill.
Number Input
A numeric input with increment / decrement steppers on Ark UI's NumberInput machine — clamping, locale-aware formatting, mouse-wheel, and the full keyboard model on the shared input shell.
File Upload
A drag-and-drop file picker on Ark UI's FileUpload machine — a dashed dropzone with a browse button, a list of accepted files with thumbnails / sizes / remove, built-in label / description / error, and native form submission.