Component reference
PinInput
A one-time verification code split into coordinated cells.
Preview
Live previewOptional six-digit hex. Clear to restore the preset. Check contrast with your brand color.
Changes apply to this preview only.
Two-factor verification
Enter the six-digit code from your authenticator app. The code is grouped as 3 + 3 for easier reading.
The verification action stays disabled until every cell is filled.
Width adapts to the available space
"use client";
import { useState } from "react";
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
PinInput,
Badge,
Button
} from "@pimolu/react";
function VerificationCard() {
const [code, setCode] = useState<string[]>([
"",
"",
"",
"",
"",
"",
]);
const [completed, setCompleted] = useState<string | null>(null);
const complete = code.every(Boolean);
return (
<Card>
<CardHeader>
<CardTitle>Two-factor verification</CardTitle>
<CardDescription>
Enter the six-digit code from your authenticator app. The code
is grouped as 3 + 3 for easier reading.
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid gap-5 min-w-0">
<PinInput
label="Authentication code"
length={6}
groups={[3, 3]}
value={code}
onValueChange={(next: string[]) => {
setCode(next);
setCompleted(null);
}}
onComplete={setCompleted}
/>
<div className="flex flex-wrap items-center gap-3 min-w-0">
<Badge variant={complete ? "success" : "neutral"}>
{complete ? "Complete" : "Waiting"}
</Badge>
<Button size="sm" disabled={!complete}>Verify</Button>
<Button
size="sm"
appearance="ghost"
onClick={() => {
setCode(["", "", "", "", "", ""]);
setCompleted(null);
}}
>
Reset
</Button>
</div>
<p className="text-sm text-muted leading-relaxed">
{
completed
? `onComplete received "${completed}".`
: "The verification action stays disabled until every cell is filled."
}
</p>
</div>
</CardContent>
</Card>
);
}
export function DemoExample() {
return (<VerificationCard />);
}More examples
Different configurations and compositions using the real Pimolu API. Each preview runs independently and follows the site appearance.
Default
Six numeric cells, one-time-code autocomplete on the first cell and a labelled group.
Grouped and alphanumeric
groups splits the cells visually without changing the single group label. type=alphanumeric accepts letters and digits.
States
mask renders password cells; error marks every cell invalid and links the message; disabled and read-only lock the group.
Usage
Keep verification and server errors outside the input; completion only reports local input.
API reference
Generated from the public TypeScript declarations. Native HTML attributes are inherited where the component extends them; this reference includes Pimolu props and selected common native attributes.
PimoluPinInputProps
Type source| Name | Type | Default | Description |
|---|---|---|---|
value | string[] | undefined | — | Controlled cells. Each entry is one cell; missing entries are empty. This positional API keeps a hole in the middle of the code from shifting the remaining digits. |
defaultValue | string[] | undefined | — | Initial cells when uncontrolled. |
onValueChange | ((value: string[]) => void) | undefined | — | Called with the next cell array after every edit. |
onComplete | ((value: string) => void) | undefined | — | Called once when the last empty cell is filled. |
length | number | undefined | 6 | Number of cells. Defaults to 6. |
type | PimoluPinInputType | undefined | "numeric" | Accepted characters. Defaults to "numeric". |
mask | boolean | undefined | false | Render the cells as password fields. |
disabled | boolean | undefined | false | Public Pimolu prop; see the source declaration for details. |
readOnly | boolean | undefined | false | Public Pimolu prop; see the source declaration for details. |
error | boolean | undefined | false | Invalid state, announced on every cell. |
helperText | ReactNode | — | Supporting text below the cells. |
errorMessage | ReactNode | — | Error text below the cells. |
label | ReactNode | — | Visible label, also used as the accessible name of the group. |
autoFocus | boolean | undefined | false | Focus the first empty cell on mount. |
groups | number[] | undefined | — | Split the cells into visual groups, e.g. `[3, 3]`. Ignored unless the sizes are positive integers that add up to `length`. |
className | string | undefined | — | Class applied to the outer group. |
style | CSSProperties | undefined | — | Standard React/HTML attribute. |
aria-label | string | undefined | — | Defines a string value that labels the current element. |
children | ReactNode | — | Standard React/HTML attribute. |
onClick | MouseEventHandler<HTMLDivElement> | undefined | — | Standard React/HTML attribute. |
valuestring[] | undefinedNo default extracted.
Controlled cells. Each entry is one cell; missing entries are empty. This positional API keeps a hole in the middle of the code from shifting the remaining digits.
defaultValuestring[] | undefinedNo default extracted.
Initial cells when uncontrolled.
onValueChange((value: string[]) => void) | undefinedNo default extracted.
Called with the next cell array after every edit.
onComplete((value: string) => void) | undefinedNo default extracted.
Called once when the last empty cell is filled.
lengthnumber | undefinedDefault: 6
Number of cells. Defaults to 6.
typePimoluPinInputType | undefinedDefault: "numeric"
Accepted characters. Defaults to "numeric".
maskboolean | undefinedDefault: false
Render the cells as password fields.
disabledboolean | undefinedDefault: false
Public Pimolu prop; see the source declaration for details.
readOnlyboolean | undefinedDefault: false
Public Pimolu prop; see the source declaration for details.
errorboolean | undefinedDefault: false
Invalid state, announced on every cell.
helperTextReactNodeNo default extracted.
Supporting text below the cells.
errorMessageReactNodeNo default extracted.
Error text below the cells.
labelReactNodeNo default extracted.
Visible label, also used as the accessible name of the group.
autoFocusboolean | undefinedDefault: false
Focus the first empty cell on mount.
groupsnumber[] | undefinedNo default extracted.
Split the cells into visual groups, e.g. `[3, 3]`. Ignored unless the sizes are positive integers that add up to `length`.
classNamestring | undefinedNo default extracted.
Class applied to the outer group.
styleCSSProperties | undefinedNo default extracted.
Standard React/HTML attribute.
aria-labelstring | undefinedNo default extracted.
Defines a string value that labels the current element.
childrenReactNodeNo default extracted.
Standard React/HTML attribute.
onClickMouseEventHandler<HTMLDivElement> | undefinedNo default extracted.
Standard React/HTML attribute.
Accessibility
- Label the code entry, test paste/backspace and do not prevent password-manager or OTP autofill.