āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā š shadcn/directory/sadmann7/diceui/components/mask-input ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
npx shadcn@latest add "https://diceui.com/r/mask-input"
```package-install
@radix-ui/react-slot
```
</Step>
<Step>
Copy the refs composition utilities into your `lib/compose-refs.ts` file.
<ComponentSource name="compose-refs" />
</Step>
<Step>
Copy and paste the following code into your project.
<ComponentSource name="mask-input" />
</Step>
</Steps>
Import and use the component directly.
import { MaskInput } from "@/components/ui/mask-input";
<MaskInput
mask="phone"
placeholder="Enter phone number"
maskPlaceholder="(___) ___-____"
onValueChange={(masked, unmasked) => {
console.log('Masked:', masked); // "(555) 123-4567"
console.log('Unmasked:', unmasked); // "5551234567"
}}
/>
maskPlaceholderasChild prop to render as a different component using Radix SlotCreate custom mask patterns for specific formatting needs.
<ComponentTabs name="mask-input-custom-pattern-demo" />Control when validation occurs with different validation modes, similar to react-hook-form.
<ComponentTabs name="mask-input-validation-modes-demo" />Card information with credit card number, expiry date, and CVC fields.
<ComponentTabs name="mask-input-card-information-demo" />Integrate masked inputs with form validation using react-hook-form.
<ComponentTabs name="mask-input-form-demo" />The component includes several predefined mask patterns:
| Pattern | Format | Example | Description |
|---------|--------|---------|-------------|
| phone | (###) ###-#### | (555) 123-4567 | US phone number |
| ssn | ###-##-#### | 123-45-6789 | Social Security Number |
| date | ##/##/#### | 12/25/2023 | Date (MM/DD/YYYY) |
| time | ##:## | 14:30 | Time (HH:MM) |
| creditCard | #### #### #### #### | 1234 5678 9012 3456 | Credit card number |
| creditCardExpiry | ##/## | 12/25 | Credit card expiry date (MM/YY) |
| zipCode | ##### | 12345 | US ZIP code |
| zipCodeExtended | #####-#### | 12345-6789 | US ZIP+4 code |
| currency | Dynamic | $1,234.56 | Currency formatting using Intl.NumberFormat |
| percentage | ##.##% | 12.34% | Percentage with decimals |
| licensePlate | ###-### | ABC-123 | License plate format |
| ipv4 | ###.###.###.### | 192.168.1.1 | IPv4 address |
| macAddress | ##:##:##:##:##:## | 00:1B:44:11:3A:B7 | MAC address |
| isbn | ###-#-###-#####-# | 978-0-123-45678-9 | ISBN-13 book identifier |
| ein | ##-####### | 12-3456789 | Employer Identification Number |
Create custom patterns using the MaskPattern interface:
const customPattern: MaskPattern = {
pattern: "###-###-####",
transform: (value, opts) => value.replace(/[^A-Z0-9]/gi, "").toUpperCase(),
validate: (value, opts) => value.length === 10,
};
<MaskInput
mask={customPattern}
placeholder="Enter license plate"
maskPlaceholder="ABC-1234"
/>
The currency mask uses the Intl.NumberFormat API for localization and currency formatting.
// Default USD formatting
<MaskInput mask="currency" />
// Euro formatting with German locale
<MaskInput
mask="currency"
currency="EUR"
locale="de-DE"
/>
// Japanese Yen formatting
<MaskInput
mask="currency"
currency="JPY"
locale="ja-JP"
/>
// British Pound formatting
<MaskInput
mask="currency"
currency="GBP"
locale="en-GB"
/>
Use the maskPlaceholder prop to control when mask format hints are shown. The mask placeholder only appears when the input is focused and the prop is provided.
// Shows mask placeholder when focused
<MaskInput
mask="phone"
placeholder="Enter phone number"
maskPlaceholder="(___) ___-____"
/>
// No mask placeholder - just regular placeholder behavior
<MaskInput
mask="phone"
placeholder="Enter phone number"
/>
The main masked input component that handles formatting and user input.
<AutoTypeTable path="./types/docs/mask-input.ts" name="MaskInputProps" />
Interface for creating custom mask patterns.
<AutoTypeTable path="./types/docs/mask-input.ts" name="MaskPattern" />
Predefined mask pattern keys for common input formats.
| Pattern | Description |
|---------|-------------|
| phone | US phone number |
| ssn | Social Security Number |
| date | Date (MM/DD/YYYY) |
| time | Time (HH:MM) |
| creditCard | Credit card number |
| creditCardExpiry | Credit card expiry date (MM/YY) |
| zipCode | US ZIP code |
| zipCodeExtended | US ZIP+4 code |
| currency | Currency formatting using Intl.NumberFormat |
| percentage | Percentage with decimals |
| licensePlate | License plate format |
| ipv4 | IPv4 address |
| macAddress | MAC address |
| isbn | ISBN-13 book identifier |
| ein | Employer Identification Number |
Options passed to the transform function for advanced formatting.
<AutoTypeTable path="./types/docs/mask-input.ts" name="TransformOptions" />
Options passed to the validate function for enhanced validation.
<AutoTypeTable path="./types/docs/mask-input.ts" name="ValidateOptions" />
<DataAttributesTable attributes={[ { title: "[data-disabled]", value: "Present when the input is disabled.", }, { title: "[data-invalid]", value: "Present when the input has validation errors.", }, { title: "[data-readonly]", value: "Present when the input is read-only.", }, { title: "[data-required]", value: "Present when the input is required.", }, ]} />
<KeyboardShortcutsTable shortcuts={[ { keys: ["Tab"], description: "Moves focus to or away from the input.", }, { keys: ["Shift + Tab"], description: "Moves focus to the previous focusable element.", }, { keys: ["Backspace"], description: "Removes the previous character, intelligently handling mask characters.", }, { keys: ["Delete"], description: "Removes the next character.", }, { keys: ["Ctrl + V", "Cmd + V"], description: "Pastes content with intelligent mask formatting.", }, { keys: ["Ctrl + A", "Cmd + A"], description: "Selects all input content.", }, ]} />
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā