## Feature Examples

### Size
- description: Control the size of the slots with the `size` prop. The default heights and text sizes match `<Input/>` in every theme. - `medium` (default) - `large` for prominent screens, such as a full-page login step. - `small` and `tiny` for compact layouts. Use these sparingly.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column" gap="24px">
  <FormField label="Large">
    <OTPInput size="large" defaultValue="123" />
  </FormField>
  <FormField label="Medium (default)">
    <OTPInput size="medium" defaultValue="123" />
  </FormField>
  <FormField label="Small">
    <OTPInput size="small" defaultValue="123" />
  </FormField>
  <FormField label="Tiny">
    <OTPInput size="tiny" defaultValue="123" />
  </FormField>
</StorybookComponents.Stack>;
```

### Length
- description: Set the number of characters with the `length` prop. It's 6 by default. `onComplete` fires once the code reaches that length. On a narrow screen the row fits its container: the gaps between the slots get smaller first, then the slots get narrower, down to 60% of their width. Their height never changes, so they stay easy to tap.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column" gap="24px">
  <FormField label="Four digits">
    <OTPInput length={4} />
  </FormField>
  <FormField label="Six digits (default)">
    <OTPInput />
  </FormField>
  <FormField label="Eight digits">
    <OTPInput length={8} />
  </FormField>
</StorybookComponents.Stack>;
```

### Groups
- description: Split the slots into groups with `<OTPInput.Group/>` and `<OTPInput.Slot/>`, for codes read in parts such as 123 456. - Groups next to each other are set apart by a wider gap. - Add `<OTPInput.Separator/>` between groups to draw a dash.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column" gap="24px">
  <FormField label="Groups">
    <OTPInput size="large">
      <OTPInput.Group>
        <OTPInput.Slot index={0} />
        <OTPInput.Slot index={1} />
        <OTPInput.Slot index={2} />
      </OTPInput.Group>
      <OTPInput.Group>
        <OTPInput.Slot index={3} />
        <OTPInput.Slot index={4} />
        <OTPInput.Slot index={5} />
      </OTPInput.Group>
    </OTPInput>
  </FormField>
  <FormField label="Groups with a separator">
    <OTPInput size="large">
      <OTPInput.Group>
        <OTPInput.Slot index={0} />
        <OTPInput.Slot index={1} />
        <OTPInput.Slot index={2} />
      </OTPInput.Group>
      <OTPInput.Separator />
      <OTPInput.Group>
        <OTPInput.Slot index={3} />
        <OTPInput.Slot index={4} />
        <OTPInput.Slot index={5} />
      </OTPInput.Group>
    </OTPInput>
  </FormField>
</StorybookComponents.Stack>;
```

### Status
- description: Set the status on the `<FormField/>` that wraps the field. The slots take on the status color and the `<FormField/>` shows the message below. The status only changes how the field looks; the entered code stays. - `error` marks a wrong code. Call `clear()` on the ref to empty it. - `warning` marks the field without an error. - `loading` marks the field as busy while a code is verified, and adds `readOnly` to stop edits meanwhile. It doesn't change the slots, so the field keeps its width. Show the progress in the `<FormField/>` message, with a tiny `<Loader/>` before the text.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column" gap="24px">
  <FormField label="Error" status="error" statusMessage="This is an error message.">
    <OTPInput defaultValue="123456" />
  </FormField>
  <FormField label="Warning" status="warning" statusMessage="This code expires soon.">
    <OTPInput defaultValue="123456" />
  </FormField>
  <FormField
    label="Loading"
    status="loading"
    statusMessage={
      <Box gap="6px" verticalAlign="middle">
        <Loader size="tiny" />
        Verifying
      </Box>
    }
  >
    <OTPInput defaultValue="123456" readOnly />
  </FormField>
</StorybookComponents.Stack>;
```

### Status message
- description: Add text that explains the status or what to do next with the `statusMessage` prop of the `<FormField/>`. It is linked to the input, so a screen reader reads it.
- example:
```jsx
<FormField
  label="Verification code"
  status="error"
  statusMessage="That code is wrong or expired. Try again."
>
  <OTPInput />
</FormField>;
```

### Read only
- description: Stop edits with the `readOnly` prop, for example while a code is being verified. The code stays visible and can still be focused.
- example:
```jsx
<FormField label="Verification code">
  <OTPInput readOnly defaultValue="123456" />
</FormField>;
```

### Disabled
- description: Disable the field with the `disabled` prop. It can't be focused or edited, and it doesn't show a status.
- example:
```jsx
<FormField label="Verification code">
  <OTPInput disabled defaultValue="123456" />
</FormField>;
```

### Auto focus
- description: Focus the field as soon as it appears with `autoFocus`, for example when a code step opens after the user asked for a code. Use it only when entering the code is the main task on the screen. Press _Show the code step_ to see the field appear focused.
- example:
```jsx
() => {
  const [open, setOpen] = React.useState(false);

  if (!open) {
    return (
      <Button priority="secondary" onClick={() => setOpen(true)}>
        Show the code step
      </Button>
    );
  }

  return (
    <StorybookComponents.Stack flexDirection="column" gap="12px">
      <FormField label="Verification code">
        <OTPInput autoFocus />
      </FormField>
      <Box>
        <TextButton size="small" onClick={() => setOpen(false)}>
          Hide
        </TextButton>
      </Box>
    </StorybookComponents.Stack>
  );
};
```

### Typing and pasting
- description: The field behaves the way people expect from a code field. - Digits fill the slots from the left. Other characters are ignored. - Pasting a code fills the slots in order. Only digits are kept, and anything beyond the length is dropped. - Backspace deletes the last digit. - Clicking a filled slot selects its digit, so typing replaces it. - Arrow keys move between the slots.
- example:
```jsx
<FormField label="Try typing, or pasting: 12-34 & 56">
  <OTPInput />
</FormField>;
```

## Developer Examples

### Controlled and uncontrolled
- description: The field works in either mode, depending on whether you pass `value`. - **Uncontrolled:** leave out `value`. The field keeps the code itself, starting from `defaultValue`. Read it from `onChange` or `onComplete`, and empty it with `clear()` on the ref. - **Controlled:** pass `value` and update it in `onChange`. The field shows only what `value` holds, so you can set, change or empty the code from outside. `onChange` receives the code as a string of digits.
- example:
```jsx
() => {
  const uncontrolled = React.useRef(null);
  const [lastChange, setLastChange] = React.useState('12');
  const [value, setValue] = React.useState('12');

  return (
    <StorybookComponents.Stack flexDirection="column" gap="30px">
      <StorybookComponents.Stack flexDirection="column" gap="12px">
        <FormField label="Uncontrolled, with defaultValue">
          <OTPInput
            ref={uncontrolled}
            defaultValue="12"
            onChange={setLastChange}
          />
        </FormField>
        <Box gap="12px" verticalAlign="middle">
          <TextButton size="small" onClick={() => uncontrolled.current.clear()}>
            Clear
          </TextButton>
          <Text size="small" secondary>
            Last onChange: {lastChange || '(empty)'}
          </Text>
        </Box>
      </StorybookComponents.Stack>
      <StorybookComponents.Stack flexDirection="column" gap="12px">
        <FormField label="Controlled, with value and onChange">
          <OTPInput value={value} onChange={setValue} />
        </FormField>
        <Box gap="12px" verticalAlign="middle">
          <TextButton size="small" onClick={() => setValue('123456')}>
            Fill 123456
          </TextButton>
          <TextButton size="small" onClick={() => setValue('')}>
            Clear
          </TextButton>
          <Text size="small" secondary>
            value: {value || '(empty)'}
          </Text>
        </Box>
      </StorybookComponents.Stack>
    </StorybookComponents.Stack>
  );
};
```

### Verify the code
- description: Verify the code either when the last digit is typed, with `onComplete`, or when the user presses a button, with the code you keep from `onChange`. Show the result with the status of the `<FormField/>` and make the field `readOnly` while verifying. Without a button, show the progress in the `<FormField/>` message, with a tiny `<Loader/>` and the `loading` status. With a button, show it on the button and leave the status of the field empty. To let the user fix a wrong or incomplete code, keep it and call `focus()` on the ref: the cursor goes to the first empty slot, or the first slot of a complete code is selected so the user can retype it. Without a button, `onComplete` fires again when the last digit is retyped, or right away when the user clicks one digit and changes it.
- example:
```jsx
() => {
  const useVerify = () => {
    const code = React.useRef(null);
    const [verifying, setVerifying] = React.useState(false);
    const [status, setStatus] = React.useState(null);
    const [message, setMessage] = React.useState(null);

    const verify = value => {
      if (value.length < 6) {
        setStatus('error');
        setMessage('Enter all 6 digits.');
        code.current.focus();
        return;
      }
      setStatus(undefined);
      setMessage(undefined);
      setVerifying(true);
      setTimeout(() => {
        setVerifying(false);
        if (value === '123456') {
          setMessage('Verified.');
        } else {
          setStatus('error');
          setMessage('That code is wrong. Fix it and try again.');
          code.current.focus();
        }
      }, 1200);
    };

    const reset = () => {
      setStatus(undefined);
      setMessage(undefined);
    };

    return { code, verifying, status, message, verify, reset };
  };

  const auto = useVerify();
  const manual = useVerify();
  const [value, setValue] = React.useState('');

  return (
    <StorybookComponents.Stack flexDirection="column" gap="30px">
      <FormField
        label="Without a button: verifies when the last digit is typed"
        status={auto.verifying ? 'loading' : auto.status}
        statusMessage={
          auto.verifying ? (
            <Box gap="6px" verticalAlign="middle">
              <Loader size="tiny" />
              Verifying
            </Box>
          ) : (
            auto.message
          )
        }
      >
        <OTPInput
          ref={auto.code}
          readOnly={auto.verifying}
          onChange={auto.reset}
          onComplete={auto.verify}
        />
      </FormField>
      <StorybookComponents.Stack flexDirection="column" gap="12px">
        <FormField
          label="With a button: verifies when you press Confirm"
          status={manual.status}
          statusMessage={manual.message}
        >
          <OTPInput
            ref={manual.code}
            readOnly={manual.verifying}
            onChange={next => {
              setValue(next);
              manual.reset();
            }}
          />
        </FormField>
        <Box>
          <Button
            disabled={manual.verifying}
            onClick={() => manual.verify(value)}
          >
            {manual.verifying ? <Loader size="tiny" /> : 'Confirm'}
          </Button>
        </Box>
      </StorybookComponents.Stack>
      <Text size="small" secondary>
        The right code is 123456. Enter another code to see the error, then fix it: retype it from the first slot, or click one digit and change it.
      </Text>
    </StorybookComponents.Stack>
  );
};
```

### In a form
- description: Give the field a `name` and the code is submitted with a native `<form>`, like any input. Give the `<FormField/>` and the field the same `id` and clicking the label focuses the field.
- example:
```jsx
() => {
  const [submitted, setSubmitted] = React.useState(null);

  return (
    <form
      onSubmit={event => {
        event.preventDefault();
        setSubmitted(new FormData(event.currentTarget).get('code'));
      }}
    >
      <StorybookComponents.Stack flexDirection="column" gap="12px">
        <FormField id="signin-code" label="Verification code (click to focus)">
          <OTPInput id="signin-code" name="code" />
        </FormField>
        <Box gap="12px" verticalAlign="middle">
          <Button type="submit">Submit</Button>
          <Text size="small" secondary>
            {submitted === null ? '' : 'Form data: code=' + submitted}
          </Text>
        </Box>
      </StorybookComponents.Stack>
    </form>
  );
};
```

### Resend code
- description: Attach a ref to get `focus()` and `clear()`. `clear()` empties the code, calls `onChange` with an empty string and focuses the field.
- example:
```jsx
() => {
  const code = React.useRef(null);

  return (
    <StorybookComponents.Stack flexDirection="column" gap="8px">
      <FormField label="Verification code">
        <OTPInput ref={code} defaultValue="1234" />
      </FormField>
      <Box>
        <TextButton size="small" onClick={() => code.current.clear()}>
          Resend code
        </TextButton>
      </Box>
    </StorybookComponents.Stack>
  );
};
```

## Common Use Case Examples

### Two-step login
- description: A login step that asks for the code and lets the user ask for a new one.
- example:
```jsx
() => {
  const code = React.useRef(null);
  const [status, setStatus] = React.useState(null);

  return (
    <Box width="360px" direction="vertical" gap="18px">
      <Box direction="vertical" gap="6px" align="center" style={{ textAlign: 'center' }}>
        <Heading size="extraLarge">Check your email</Heading>
        <Text secondary>Enter the code sent to:</Text>
        <Text weight="bold">name@example.com</Text>
      </Box>
      <Box align="center">
        <Box direction="vertical" gap="6px" width="296px">
          <FormField
            label="6-digit code"
            status={status}
            statusMessage={status ? 'That code is wrong or expired. Try again.' : undefined}
          >
            <OTPInput
              ref={code}
              size="large"
              onChange={() => setStatus(undefined)}
              onComplete={() => {
                setStatus('error');
                code.current.focus();
              }}
            />
          </FormField>
          <Box>
            <TextButton
              size="small"
              onClick={() => {
                setStatus(undefined);
                code.current.clear();
              }}
            >
              Send a new code
            </TextButton>
          </Box>
        </Box>
      </Box>
    </Box>
  );
};
```

### Confirm a phone number in a modal
- description: A modal that asks for the code sent to a new recovery phone number. Confirm checks that all six digits are entered. If not, it shows an error and keeps what was typed. A text button under the field sends a new code and clears it.
- example:
```jsx
() => {
  const code = React.useRef(null);
  const [value, setValue] = React.useState('');
  const [status, setStatus] = React.useState(null);

  const confirm = () => {
    if (value.length < 6) {
      setStatus('error');
      code.current.focus();
    }
  };

  return (
    <CustomModalLayout
      width="520px"
      title="Add a recovery phone number"
      subtitle="We’ll use this number in case you need to recover your account."
      primaryButtonText="Confirm"
      primaryButtonOnClick={confirm}
      secondaryButtonText="Cancel"
      onCloseButtonClick={() => {}}
      footnote={<Text size="small">Note: Your code will expire after 10 mins.</Text>}
      content={
        <Box direction="vertical" gap="6px">
          <FormField
            label="Enter the 6-digit code sent to your mobile phone."
            status={status}
            statusMessage={status ? 'Enter all 6 digits.' : undefined}
          >
            <OTPInput
              ref={code}
              size="large"
              onChange={next => {
                setValue(next);
                setStatus(undefined);
              }}
            />
          </FormField>
          <Box paddingBottom="4px">
            <TextButton size="small" onClick={() => code.current.clear()}>
              Resend code
            </TextButton>
          </Box>
        </Box>
      }
    />
  );
};
```

## Accessibility Examples

### Labels
- description: Label the field with the `label` of a `<FormField/>`. Screen readers meet one input with that name and the status message; the slots are only visual. - Without a `<FormField/>`, pass `ariaLabel`, or `ariaLabelledBy` with the `id` of an element that names the field, such as a heading.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column" gap="24px">
  <FormField label="With a FormField label">
    <OTPInput />
  </FormField>
  <OTPInput ariaLabel="Code from your authenticator app" />
  <Box direction="vertical" gap="6px">
    <Heading id="recovery-code-heading" size="small">
      Recovery code
    </Heading>
    <OTPInput ariaLabelledBy="recovery-code-heading" />
  </Box>
</StorybookComponents.Stack>;
```
