Input
Text input with shadcn/ui styling. Supports mask, debounce, formatter, textarea, number stepper, search, and more.
<template>
<VxInput v-model="value" placeholder="Type something..." />
</template>Sizes
<template>
<VxInput size="sm" />
<VxInput />
<VxInput size="lg" />
</template>Clearable
<template>
<VxInput v-model="value" clearable />
</template>Password
<template>
<VxInput type="password" placeholder="Enter password..." />
</template>Prefix & Suffix
<template>
<VxInput placeholder="Search...">
<template #prefix><SearchIcon /></template>
</VxInput>
</template>Mask
# = digit, A = letter, * = any character. Separators auto-insert.
<template>
<VxInput mask="###-###-####" placeholder="Phone" />
<VxInput mask="#### #### #### ####" placeholder="Card" />
</template>Mask with Unmasked Value
v-model returns the masked value (e.g. +1 (234) 567-89-01). Use v-model:unmasked-value to get the raw digits only.
<script setup>
const phone = ref('')
const phoneRaw = ref('')
// phone will be "+1 (234) 567-89-01" (masked)
// phoneRaw will be "12345678901" (unmasked)
</script>
<template>
<VxInput v-model="phone" v-model:unmasked-value="phoneRaw" mask="+# (###) ###-##-##" />
</template>Debounce
Delays v-model update. @input still fires immediately.
<template>
<VxInput v-model="value" :debounce="500" />
</template>Trim
Auto-trims whitespace on blur.
<template>
<VxInput v-model="value" trim />
</template>Lazy
Updates v-model on blur, not on every keystroke.
<template>
<VxInput v-model="value" lazy />
</template>Autofocus
<template>
<VxInput autofocus />
</template>Loading
<template>
<VxInput v-model="value" loading />
</template>Formatter / Parser
Display formatted value, store raw value. Formatter runs on blur, parser on input.
<script setup>
function formatter(v) { return Number(v).toLocaleString('en-US') }
function parser(v) { return v.replace(/,/g, '') }
</script>
<template>
<VxInput v-model="value" :formatter="formatter" :parser="parser" />
</template>Textarea
<template>
<VxInput v-model="value" type="textarea" :rows="4" />
</template>Autosize Textarea
<template>
<VxInput type="textarea" :autosize="{ minRows: 2, maxRows: 6 }" />
</template>Number
With stepper buttons and arrow key support.
<template>
<VxInput v-model="value" type="number" />
<VxInput v-model="value" type="number" :min="0" :max="10" :step="2" />
<VxInput v-model="value" type="number" :step="0.25" :precision="2" />
</template>Regex
Restrict input to characters matching a regex pattern. Non-matching characters are stripped in real-time.
<template>
<!-- Numbers only -->
<VxInput v-model="value" :regex="/[0-9]/" />
<!-- Letters only -->
<VxInput v-model="value" :regex="/[a-zA-Z]/" />
<!-- Alphanumeric -->
<VxInput v-model="value" :regex="/[a-zA-Z0-9]/" />
</template>Search
Built-in search icon. Emits @search on Enter.
<template>
<VxInput type="search" placeholder="Search..." @search="onSearch" clearable />
</template>Word Limit
<template>
<VxInput :maxlength="50" show-word-limit />
</template>Floating Label
When floating-label is enabled, the placeholder animates to the top border on focus or when the input has a value.
<template>
<VxInput v-model="val" placeholder="Username" floating-label />
<VxInput v-model="email" placeholder="Email" floating-label type="email" />
<VxInput v-model="pass" placeholder="Password" floating-label type="password" />
</template>Disabled & Readonly
<template>
<VxInput disabled />
<VxInput readonly />
</template>Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | number | '' | Value (v-model) |
placeholder | string | '' | Placeholder |
type | 'text' | 'password' | 'email' | 'number' | 'search' | 'tel' | 'url' | 'textarea' | 'text' | Input type |
size | 'sm' | 'default' | 'lg' | 'default' | Size |
disabled | boolean | false | Disable |
readonly | boolean | false | Read only |
clearable | boolean | false | Clear button |
debounce | number | 0 | Debounce v-model update (ms) |
mask | string | '' | Input mask (#=digit, A=letter, *=any) |
unmaskedValue | string | — | Raw value without mask chars (v-model:unmasked-value) |
trim | boolean | false | Trim whitespace on blur |
lazy | boolean | false | Update v-model on blur only |
autofocus | boolean | false | Focus on mount |
loading | boolean | false | Show loading spinner |
formatter | (v: string) => string | — | Format display value (on blur) |
parser | (v: string) => string | — | Parse value before emit |
maxlength | number | — | Max characters |
showWordLimit | boolean | false | Show character count |
rows | number | 3 | Textarea rows |
autosize | boolean | { minRows, maxRows } | false | Auto-grow textarea |
min | number | — | Min value (number type) |
max | number | — | Max value (number type) |
step | number | 1 | Step increment (number type) |
precision | number | — | Decimal places (number type) |
regex | RegExp | — | Allow only characters matching the regex |
inputClass | string | string[] | Record | '' | Custom wrapper class |
inputStyle | Record<string, string> | — | Custom wrapper style |
floatingLabel | boolean | false | Animate placeholder to top border on focus |
Events
| Event | Type | Description |
|---|---|---|
update:modelValue | (v: string | number) | Value changed |
input | (v: string | number) | On every keystroke |
change | (v: string | number) | On blur/enter |
focus | (e: FocusEvent) | Focused |
blur | (e: FocusEvent) | Blurred |
clear | () | Cleared |
search | (v: string) | Enter pressed (search type) |
Slots
| Slot | Description |
|---|---|
prefix | Before input (auto search icon for type="search") |
suffix | After input |