# Pin input (goodtabs UI)

A one-time code field with one slot per digit that fills on paste.

## Install

```bash
npx shadcn@latest add https://ui.goodtabs.co/r/pin-input.json
```

Or, with the @goodtabs namespace configured in components.json: `npx shadcn@latest add @goodtabs/pin-input`

## Usage

```tsx
import { PinInput } from "@/components/ui/pin-input"

<PinInput label="Verification code" onComplete={(code) => verify(code)} />
<PinInput length={4} label="Card PIN" showLabel />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| length | `number` | `6` | Number of digits. Even lengths of six or more split into two groups. |
| onComplete | `(code: string) => void` |  | Called with the full code once every slot is filled. |
| label | `string` | `"One-time code"` | Accessible name. Screen reader only unless showLabel is set. |
| showLabel | `boolean` | `false` | Show the label above the field. |
| value, defaultValue, onChange | `input-otp props` |  | Controlled or uncontrolled. onChange receives the string, not an event. |
| disabled | `boolean` | `false` | Disables the field and dims the slots. |

## When to use

- Email or SMS verification codes and two factor prompts
- Short numeric PINs where each digit should read on its own
- Anywhere people paste a code from another app

## When not to use

- Passwords or long secrets: use the password input
- Codes with letters: digits only, by design, so the numeric keyboard appears on phones
- More than eight characters, where separate slots stop helping

## Notes for agents

- Client component that takes functions: a demo or page passing onComplete or onChange must be a client component too
- Digits only, inputMode numeric and autoComplete one-time-code, so iOS offers the code from Messages
- onChange fires with the string on every keystroke; onComplete once when the last slot fills. Clear the value yourself after a failed check
- Slots are 32px squares from the shadcn input-otp primitive; the separator only appears for even lengths of six or more

Docs: https://ui.goodtabs.co/components/pin-input