Last update:
June 24, 2025
VcInput Component¶
The VcInput
component is a versatile form control for various types of input fields including text, numbers, passwords, dates, and more. It provides a consistent UI with numerous customization options and styling variants.
Storybook¶
Basic Usage¶
<template>
<VcInput v-model="inputValue" label="Full Name" placeholder="Enter your full name" />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const inputValue = ref('');
</script>
Props¶
Prop | Type | Default | Description |
---|---|---|---|
modelValue |
string \| number \| Date \| null \| undefined |
- | Value of the input, can be bound using v-model |
label |
string |
- | Label text shown above the input |
placeholder |
string |
- | Placeholder text shown when input is empty |
type |
string |
'text' |
Type of input ('text' , 'password' , 'email' , 'tel' , 'number' , 'integer' , 'url' , 'time' , 'date' , 'datetime-local' ) |
step |
string |
'1' |
Step value for number inputs |
hint |
string |
- | Help text shown below the input |
clearable |
boolean |
false |
Whether to show a clear button when input has a value |
prefix |
string |
- | Text to display before the input value |
suffix |
string |
- | Text to display after the input value |
name |
string |
'Field' |
Name attribute for the input element |
loading |
boolean |
false |
Shows a loading spinner inside the input |
debounce |
string \| number |
- | Debounce time in milliseconds for the input event |
disabled |
boolean |
false |
Disables the input |
autofocus |
boolean |
false |
Automatically focuses the input on render |
error |
boolean |
false |
Indicates an error state for the input |
errorMessage |
string |
- | Error message shown when error is true |
maxlength |
string \| number |
'1024' |
Maximum character length for the input |
tooltip |
string |
- | Tooltip text shown next to the label |
required |
boolean |
false |
Adds a required indicator to the label |
multilanguage |
boolean |
false |
Indicates if the field supports multiple languages |
currentLanguage |
string |
- | Current selected language for multilanguage inputs |
datePickerOptions |
VueDatePickerProps |
- | Options for date picker when type is date or datetime |
size |
'default' \| 'small' |
'default' |
Size of the input |
Events¶
Event | Parameters | Description |
---|---|---|
update:modelValue |
(value: string \| number \| Date \| null \| undefined) => void |
Emitted when input value changes |
blur |
(event: Event) => void |
Emitted when input loses focus |
focus |
() => void |
Emitted when input receives focus |
Slots¶
Slot | Props | Description |
---|---|---|
control |
{ editable, focused, modelValue, emitValue, placeholder } |
Custom input control |
prepend |
{ focus: () => void } |
Content to prepend outside the input |
prepend-inner |
{ focus: () => void } |
Content to prepend inside the input |
append-inner |
{ focus: () => void } |
Content to append inside the input |
append |
{ focus: () => void } |
Content to append outside the input |
error |
- | Custom error message content |
hint |
- | Custom hint content |
CSS Variables¶
The input component uses CSS variables for theming, which can be customized:
:root {
--input-height: 36px; /* Default height of input field */
--input-height-small: 30px; /* Height of input field when size="small" */
--input-border-radius: 4px; /* Border radius of the input field */
--input-border-color: var(--neutrals-300); /* Border color in normal state */
--input-padding: 10px; /* Horizontal padding inside the input field */
--input-background-color: var(--additional-50); /* Background color of the input field */
--input-placeholder-color: var(--neutrals-400); /* Color of placeholder text */
--input-clear-color: var(--primary-500); /* Color of the clear button */
--input-clear-color-hover: var(--primary-600); /* Color of the clear button on hover */
--input-text-color: var(--neutrals-800); /* Color of input text */
/* Disabled state */
--input-disabled-text-color: var(--neutrals-500); /* Text color when input is disabled */
--input-disabled-bg-color: var(--neutrals-200); /* Background color when input is disabled */
/* Error state */
--input-text-color-error: var(--danger-500); /* Text color when in error state */
--input-border-color-error: var(--danger-500); /* Border color when in error state */
/* Focus state */
--input-border-color-focus: var(--primary-100); /* Outline color when input is focused */
}
Examples¶
Basic Text Input¶
<template>
<VcInput
v-model="username"
label="Username"
placeholder="Enter username"
hint="Choose a unique username"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const username = ref('');
</script>
Password Input with Visibility Toggle¶
<template>
<VcInput
v-model="password"
type="password"
label="Password"
placeholder="Enter password"
:required="true"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const password = ref('');
</script>
Number Input¶
<template>
<VcInput
v-model="quantity"
type="number"
label="Quantity"
placeholder="Enter quantity"
min="1"
step="1"
hint="Minimum order is 1 unit"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const quantity = ref(1);
</script>
Input with Prefix and Suffix¶
<template>
<VcInput
v-model="price"
type="number"
label="Price"
placeholder="0.00"
prefix="$"
suffix="USD"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const price = ref(null);
</script>
Input with Error State¶
<template>
<VcInput
v-model="email"
type="email"
label="Email"
placeholder="Enter your email"
:error="!!emailError"
:errorMessage="emailError"
@blur="validateEmail"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const email = ref('');
const emailError = ref('');
function validateEmail() {
const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
if (!email.value) {
emailError.value = 'Email is required';
} else if (!emailRegex.test(email.value)) {
emailError.value = 'Please enter a valid email address';
} else {
emailError.value = '';
}
}
</script>
Date Input¶
<template>
<VcInput
v-model="birthdate"
type="date"
label="Birth Date"
placeholder="Select date"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const birthdate = ref(null);
</script>
Datetime Input¶
<template>
<VcInput
v-model="appointmentTime"
type="datetime-local"
label="Appointment Time"
placeholder="Select date and time"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const appointmentTime = ref(null);
</script>
Input with Clearable Option¶
<template>
<VcInput
v-model="search"
label="Search"
placeholder="Enter search term"
clearable
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const search = ref('');
</script>
Input with Prepend and Append Slots¶
<template>
<VcInput
v-model="searchTerm"
label="Search"
placeholder="Enter search term"
>
<template #prepend>
<div class="tw-bg-[var(--neutrals-300)] tw-px-3 tw-flex tw-items-center tw-rounded-l-[var(--input-border-radius)]">
<VcIcon icon="search" />
</div>
</template>
<template #append>
<VcButton>Search</VcButton>
</template>
</VcInput>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput, VcIcon, VcButton } from '@vc-shell/framework';
const searchTerm = ref('');
</script>
Small Size Input¶
<template>
<VcInput
v-model="tag"
label="Tag"
placeholder="Enter tag name"
size="small"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const tag = ref('');
</script>
Input with Debounce¶
<template>
<VcInput
v-model="searchQuery"
label="Search"
placeholder="Start typing to search..."
:debounce="500"
@update:modelValue="performSearch"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const searchQuery = ref('');
const searchResults = ref([]);
function performSearch(query) {
console.log(`Searching for: ${query}`);
// API call or search logic here after debounce
}
</script>
Input with Character Counter¶
<template>
<VcInput
v-model="message"
label="Message"
placeholder="Type your message..."
:maxlength="50"
>
<template #append-inner>
<div class="tw-text-xs tw-text-gray-500">
{{ message.length }}/50
</div>
</template>
</VcInput>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const message = ref('');
</script>
Custom Control Slot¶
<template>
<VcInput
v-model="customValue"
label="Custom Input"
>
<template #control="{ modelValue, emitValue, placeholder }">
<div class="tw-w-full tw-h-full tw-flex tw-items-center">
<input
:value="modelValue"
@input="(e) => emitValue(e.target.value)"
:placeholder="placeholder"
class="tw-w-full tw-h-full tw-outline-none tw-border-none tw-px-2 tw-bg-gray-100 tw-rounded"
/>
</div>
</template>
</VcInput>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { VcInput } from '@vc-shell/framework';
const customValue = ref('');
</script>
Special Type Features¶
Integer Type¶
The integer
type is a special input type that only allows whole numbers:
<template>
<VcInput
v-model="quantity"
type="integer"
label="Quantity"
placeholder="Enter a whole number"
/>
</template>
Date and Datetime Types¶
The date
and datetime-local
types use the Vue Datepicker component with integrated formatting based on the user's locale:
<template>
<VcInput
v-model="eventDate"
type="datetime-local"
label="Event Date & Time"
:datePickerOptions="{
disabledDates: [new Date(2023, 0, 1)],
yearRange: [2023, 2025]
}"
/>
</template>
The datePickerOptions
prop accepts all options from the @vuepic/vue-datepicker component.