Phone Input
A country-code Select joined to a national-number Input (via Join), with a lightweight generic digit-grouping formatter.
Colors
Sizes
Controlled
E.164: (empty)
Using Phone Input
Silica ships one design system through three paths. They share a class vocabulary but are not interchangeable — pick the one that matches what you are building.
Plain HTML — CSS classes
The Tailwind v4 plugin. Works in any framework or none — Rails, Django, PHP, Go, a static file. This path ships no JavaScript, so Phone Input is styled but inert: its behavior comes from phone-input. For that behavior with no framework, use the node-tree path below.
/* in your CSS */
@import "tailwindcss";
@plugin "@wizeworks/silicaui";Root class phone-input-country, with 0 modifiers:
.phone-input-country
React
Typed components over those same classes, with behavior and accessibility from Base UI.
npm i @wizeworks/silicaui-reactimport { PhoneInput } from "@wizeworks/silicaui-react";Props
| Prop | Type | Required | Description |
|---|---|---|---|
| value | string | no | Controlled national number (digits, or digits with formatting — either is fine). |
| defaultValue | string | no | Uncontrolled initial national number. |
| onValueChange | (national: string, e164: string) => void | no | Fires on every keystroke with the raw national digits and the full E.164 string. |
| country | string | no | Controlled selected country (ISO 3166-1 alpha-2). |
| defaultCountry | string | no | Uncontrolled initial country. Default "US". |
| onCountryChange | (iso2: string) => void | no | Fires when the country picker selection changes. |
| countries | Country[] | no | Override/extend the built-in country list. |
| color | PhoneInputColor | no | Accent color; maps to input-<color>/select-<color> (border + focus ring). |
| size | PhoneInputSize | no | Default md. Matches same-size Input/Select heights. |
| disabled | boolean | no | — |
| placeholder | string | no | — |
| name | string | no | Field name for form submission (submits the national digits). |
| id | string | no | — |
| className | string | no | — |
| "aria-label" | string | no | — |
Source of the demo above
The exact file that renders the examples above, so it can never drift from them. It imports a few of this site’s own layout helpers (../lib/…), so read it for the component calls rather than copying it whole.
Show source
import { useState } from "react";
import { PhoneInput } from "@wizeworks/silicaui-react";
import { Section, Stack } from "../lib/Section";
import { SIZES } from "../lib/data";
export function PhoneInputDemo() {
const [national, setNational] = useState("");
const [e164, setE164] = useState("");
return (
<>
<Section title="Colors">
<Stack className="max-w-sm">
<PhoneInput />
<PhoneInput color="primary" defaultCountry="GB" defaultValue="7911123456" />
<PhoneInput disabled defaultCountry="DE" defaultValue="15123456789" />
</Stack>
</Section>
<Section title="Sizes">
<Stack className="max-w-sm">
{SIZES.map((size) => (
<PhoneInput key={size} size={size} />
))}
</Stack>
</Section>
<Section title="Controlled">
<Stack className="max-w-sm">
<PhoneInput
value={national}
onValueChange={(nat, e164) => {
setNational(nat);
setE164(e164);
}}
/>
<p className="text-xs opacity-60">E.164: {e164 || "(empty)"}</p>
</Stack>
</Section>
</>
);
}Vanilla — node tree to HTML
phone-input — a country <select> (options carry data-dial) joined with a digits input; the country list is plain static data, ported verbatim (no React-only mechanism was involved in the original). Build a node tree, project it with toHtml(), and let the zero-dependency runtime hydrate it. This is the path for generated or user-authored documents — a site builder, CMS output, a static export.
npm i @wizeworks/silicaui-html @wizeworks/silicaui-behaviorsimport { atom, toHtml } from "@wizeworks/silicaui-html";
const node = atom("PhoneInput", "phone-input-country", { /* props */ });
const markup = toHtml(node);Styling on this path is the class string in the second argument — the same classes as the Plain HTML section above. There is no color prop here; write "phone-input-country phone-input-country-primary" rather than passing a colour as a prop.
- Takes children
- no
- Hydrated by
phone-input
Load @wizeworks/silicaui-behaviors on the page or this markup renders correctly and does nothing.
The full API for Phone Input, on every path, is available through the Silica MCP server.