Masked Input React component
A formatted text field for phone numbers, dates, times, card numbers, ZIP codes or any pattern you define: separators fill themselves in, the rest of the template waits in faint ghost text, a thin bar tracks how much is filled, and a tick appears when it's complete.
When to use the Masked Input component
Use Masked Input for values with a fixed shape: phone numbers, dates, times, card numbers, postcodes, booking or licence codes. People see exactly what's expected and can't type characters that don't fit.
Store the raw value (digits and letters only) and format it again when you display it.
Installation
Add the Masked Input component to your project with the shadcn CLI. It lands in components/masked-input.tsx as plain React + Tailwind CSS source you own and can edit.
npx shadcn@latest add https://reactframe.com/r/masked-input.jsonOr copy the source by hand and install its dependencies:
npm install motion clsx tailwind-mergeProps
<MaskedInput /> accepts 13 props, all optional.
| Prop | Type | Default |
|---|---|---|
| preset | "phone" | "date" | "time" | "card" | "zip" | "phone" |
| mask Your own mask: 9 = digit, A = letter, * = either; anything else is inserted as-is. | string | — |
| placeholder Ghost text for the empty slots, same length as the mask. | string | — |
| label | string | — |
| value Raw characters (without the mask's separators). | string | — |
| defaultValue | string | "" |
| onValueChange | (raw: string, formatted: string) => void | — |
| onComplete | (raw: string, formatted: string) => void | — |
| helperText | string | — |
| error | string | — |
| size | "sm" | "md" | "lg" | "md" |
| theme | "dark" | "light" | "dark" |
- preset"phone" | "date" | "time" | "card" | "zip"Default: "phone"
- mask
Your own mask: 9 = digit, A = letter, * = either; anything else is inserted as-is.
string - placeholder
Ghost text for the empty slots, same length as the mask.
string - labelstring
- value
Raw characters (without the mask's separators).
string - defaultValuestringDefault: ""
- onValueChange(raw: string, formatted: string) => void
- onComplete(raw: string, formatted: string) => void
- helperTextstring
- errorstring
- size"sm" | "md" | "lg"Default: "md"
- theme"dark" | "light"Default: "dark"
Show all 13 propsShow fewer
| className | string | — |
- classNamestring
FAQ
- What does onValueChange return?
- Both the raw characters (for example 5551234567) and the formatted text ((555) 123-4567), so you can store one and show the other.
- Can I paste a whole number?
- Yes. Pasted text is filtered to the characters that fit the mask and formatted in one go; extra characters are dropped.
- How do I define my own pattern?
- Use 9 for a digit, A for a letter and * for either; everything else (spaces, dashes, brackets) is inserted automatically.