# Code Field

> One field for a code typed or pasted: a code sent by email or text, or a workspace's invite code. It drops anything else, and calls onComplete once the code is whole.

- Name: `code-field`
- Status: beta
- Categories: forms
- File: the install writes `code-field.tsx` to your `ui` alias, `@/components/ui` by default.
- Other registry items: `@arbokui/field-frame`, `@arbokui/input`. The install adds them.
- Gallery: https://arbokui.com/components/code-field
- Registry item: https://arbokui.com/r/code-field.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/code-field
   ```

## Use it for

- A one-time code sent by email or text: characters="digits", six long by default.
- A join code of letters and digits: characters="text". It shows in capitals.
- Check the code in onComplete. It runs once the code is whole, so there is no Continue button to press.
- Say where the code went and how long it works in hint, like "We sent it to riley@example.com. It works for 15 minutes."
- Put a wrong or expired code in error, like "That code doesn't match".
- Pass onResend to add a quiet "Send a new code" button after the hint or error. It reads "Sent" for 10 seconds after a press.

## Avoid it for

- A row of one box per digit. One field takes a paste, autofill, and the phone's suggested code in one go.
- A password or a PIN people choose. Use an input with type="password".
- Long codes people copy from a page, like a licence key. Use an input.

## Props

- `length`: `number`. Default `6`. How many characters make the code whole.
- `characters`: `"digits" | "text"`. Default `"digits"`. Digits only, or letters and digits in capitals. Anything else is dropped, so a pasted "123 456" reads 123456.
- `value`: `string`. The code. Use it with onValueChange.
- `defaultValue`: `string`. The code at first render, when you do not control it.
- `onValueChange`: `(code: string) => void`. Called with the cleaned code each time it changes.
- `onComplete`: `(code: string) => void`. Called once the code reaches its length. Check it here.
- `label`: `ReactNode`. Names the field, above it.
- `hint`: `ReactNode`. Where the code went and how long it works.
- `error`: `ReactNode`. A wrong or expired code. Replaces the hint, in red, and is announced.
- `onResend`: `() => void`. Adds a "Send a new code" button after the hint or error.
- `resendLabel`: `string`. Default `"Send a new code"`. The resend button's words.
- `size`: `"sm" | "md" | "lg"`. Default `"md"`. Height, padding, and text size. The same heights as Input.
- `disabled`: `boolean`. Default `false`. Blocks typing and the resend button.
- `placeholder`: `string`. A sample code, like "TEAM26X".
- `id`: `string`. The input's id. Defaults to a generated one.
- `className`: `string`. Classes for the frame. Other props, like name and aria-\*, land on the input.

## Accessibility

- A native input named by its label, so typing, pasting, and autofill work as usual.
- autocomplete="one-time-code" lets phones offer the code from the message they got.
- Digits open the number keypad on phones. Text codes turn on capitals.
- The hint or error describes the input. An error sets aria-invalid and is announced once when it appears.
- The resend button keeps its width when it reads "Sent", and a polite live region says "Sent a new code".
- On touch screens the text is 16px, so iOS Safari does not zoom in when the field gets focus.

## Examples

### A code sent by email

```tsx
<CodeField
  label="Code"
  hint="We sent it to riley@example.com. It works for 15 minutes."
  onComplete={(code) => console.log("check", code)}
  onResend={() => console.log("resend")}
/>
```

### Letters and digits, seven long

```tsx
<CodeField
  label="Invite code"
  characters="text"
  length={7}
  placeholder="TEAM26X"
  hint="Your admin gives you this. It joins you to the right team."
/>
```

### A wrong code

```tsx
<CodeField label="Code" defaultValue="123456" error="That code doesn't match." />
```
