# Phone input

Phone input is a neobrutalist React component from Cruise UI. A Nigerian mobile number with a +234 block: shows 0801 234 5678, gives back +2348012345678.

Install (with the @cruiseui registry in components.json, see Installation):

```bash
npx shadcn@latest add @cruiseui/phone-input
```

Import: `import { CruisePhoneInput } from "@/components/cruise/phone-input";`

## When to use

Asking for a Nigerian mobile number (SMS, delivery, WhatsApp).

## When not to

International numbers from any country (use an Input with type="tel").

## Example (React)

```tsx
"use client";

import { useState } from "react";
import { CruisePhoneInput } from "@/components/cruise/phone-input";

export default function PhoneInputExample() {
  const [e164, setE164] = useState<string | null>(null);
  return (
    <div className="flex max-w-md flex-col gap-2">
      <CruisePhoneInput
        label="Phone number"
        required
        hint="We'll text your order updates here."
        onValueChange={setE164}
      />
      <p className="text-small text-ink-muted">Value: {e164 ?? "not a valid number yet"}</p>
    </div>
  );
}
```

## HTML

Needs theme.css (https://cruiseui.dev/theme.css).

```html
<div class="field">
  <label class="field-label" for="phone">Phone number</label>
  <div class="input-group">
    <span class="input-prefix" aria-hidden="true">
      <svg viewBox="0 0 24 16"><rect width="8" height="16" fill="var(--success)"/><rect x="8" width="8" height="16" fill="var(--on-success)"/><rect x="16" width="8" height="16" fill="var(--success)"/><rect x=".75" y=".75" width="22.5" height="14.5" fill="none" stroke="var(--ink)" stroke-width="1.5"/></svg>
      +234
    </span>
    <input class="input-bare" id="phone" type="tel" inputmode="tel" autocomplete="tel" placeholder="0801 234 5678" data-ng-phone>
  </div>
  <input type="hidden" name="phone">
</div>
```

## Props: CruisePhoneInput

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label?` | `string` | — | Visible label. Leave out inside a CruiseFormField (it brings the label). |
| `hint?` | `string` | — | — |
| `error?` | `string` | — | Your own error; "not a valid number" is added for you. |
| `defaultValue?` | `string` | `""` | Any form ("0801…", "+234…"); shown as "0801 234 5678". |
| `onValueChange?` | `((e164: string \| null) => void)` | — | The number in E.164 (+2348012345678), or null while it isn't valid. |
| `onValidate?` | `((message: string \| undefined) => void)` | — | Called with the validation message (or undefined) after the field is left. |

Also takes every native `<input>` attribute.

## Accessibility

- inputMode="tel" and autocomplete="tel" so phones offer the saved number.
- The +234 block is decorative; the label names the field.
- Invalid numbers get a message in words after leaving the field.
