Input
Core text field for freeform user input. Specialized variants extend this base for specific semantics, validation, or UX affordances (search, email, contact number, etc.).
When To Use
Use the base spr-input when you need a generic editable field. Prefer a variant when:
- Semantic validation or UX guidance is baked-in (e.g. email, password, URL)
- Additional UI (country selector, currency selector) is required
- Formatting / masking logic is specialized (contact number, currency)
Base Usage
<template>
<spr-input v-model="model" label="Text Input" placeholder="Enter your username" />
</template>Common Patterns
State & decoration features shared by variants:
- Active, error, disabled states
- Prefix / suffix (trailing) slots
- Helper text & helperMessage slot
- Character counting via
show-char-count,min-length,max-length
Variants
| Variant | Description | Link |
|---|---|---|
| Search | Optimized for quick filtering & search affordance | /documentation/components/input/input-search |
| Username | Username field (future: uniqueness rules) | /documentation/components/input/input-username |
| Email-specific semantic input | /documentation/components/input/input-email | |
| Password | Masked entry with optional reveal | /documentation/components/input/input-password |
| URL | Enforces URL semantics | /documentation/components/input/input-url |
| Contact Number | Country-aware number input + validation | /documentation/components/input/input-contact-number |
| Dropdown Input | Display-only styled input used as dropdown trigger | /documentation/components/input/input-dropdown |
| Currency | Currency selection + formatting (code/symbol, decimals) | /documentation/components/input/input-currency |
Advanced Slots
| Slot | Use Case |
|---|---|
prefix | Icon or contextual identifier (e.g. search icon) |
trailing | Units, inline labels, compact actions |
icon | Internal adornment (status / action) |
helperMessage | Rich helper/error content (icons + text) |
Accessibility Notes
- Always pair
labelprop (or external<label for>association) for clarity. - Avoid placeholder-only labeling; placeholder should hint format, not supply meaning.
- Use helper text to clarify constraints (length, allowed characters) instead of relying solely on validation errors.
See Also
- Select Component (structured choices)
- Textarea (multi-line content)
- File Upload (non-text input)
Active State
<template>
<spr-input v-model="inputValue" label="Text Input" placeholder="Enter your username" active />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValue = ref('');
</script>Error State
<template>
<spr-input v-model="inputValue" label="Text Input" placeholder="Enter your username" :error="true">
<template #icon>
<Icon icon="ph:warning-circle-fill" />
</template>
</spr-input>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValue = ref('');
</script>Disabled State
<template>
<spr-input v-model="inputValue" label="Text Input" placeholder="Enter your username" :disabled="true" />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValue = ref('');
</script>Min Max Length & Character Count
You can set minimum or maximum length limits by passing props min-length or max-length with the corresponding number value. Additionally, you can enable a character counter display in the bottom right of the input field with the show-char-count prop.
Character Length: 0
<template>
<!-- Text input with character count -->
<spr-input
v-model="inputValue"
label="Text Input"
placeholder="Enter your username"
:min-length="0"
:max-length="50"
show-char-count
/>
<!-- Numeric input with character count and helper -->
<spr-input
v-model="numericValue"
type="number"
label="Numeric Input"
placeholder="Enter a number"
:max-length="3"
helper-text="Max 3 digits allowed"
display-helper
show-char-count
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValue = ref('');
const numericValue = ref(0);
</script>Prefix
<template>
<spr-input v-model="inputValue" label="Text Input" placeholder="Enter your username">
<template #prefix>
<Icon icon="ph:warning-circle-fill" />
</template>
</spr-input>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValue = ref('');
</script>Trailing Label
<template>
<!-- xs -->
<spr-input v-model="inputValueXS" label="Offset xs" placeholder="00" offset-size="xs" type="number">
<template #trailing> minutes </template>
</spr-input>
<!-- sm -->
<spr-input v-model="inputValueSM" label="offset sm" placeholder="00" offset-size="sm" type="number">
<template #trailing> minutes </template>
</spr-input>
<!-- md -->
<spr-input v-model="inputValueMD" label="offset md" placeholder="Enter your name" offset-size="md">
<template #trailing> Name of the user </template>
</spr-input>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValueXS = ref('');
const inputValueSM = ref('');
const inputValueMD = ref('');
</script>Character Count Display
You can display a character counter in the bottom right of the input field by setting the show-char-count prop to true. When used with max-length, the character count will display in the format "current/max" and will change color to indicate when the maximum length is reached.
<template>
<spr-input
v-model="inputValue"
label="Text with Character Count"
placeholder="Type to see the counter"
:max-length="20"
show-char-count
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValue = ref('');
</script>Helper Message
A helper message is a text label below the input field that provides additional information about instructions, formatting hints, validation feedback, etc.
To display the helper message, set the display-helper prop to true and add the helper-text prop with the helper message text. You can also insert an icon with the helper-icon prop. This uses the Iconify icon library.
<template>
<spr-input
v-model="inputValue"
label="Text Input"
placeholder="Enter your text"
helper-text="This is a helper message"
display-helper
/>
<spr-input
v-model="inputValue"
label="Text Input"
placeholder="Enter your text"
helper-text="This is an error message"
helper-icon="ph:warning-circle-fill"
display-helper
error
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValue = ref('');
</script>Alternatively, you can use the helperMessage slot to display a custom helper message.
<template>
<spr-input v-model="inputValue" label="Text Input" placeholder="Enter your text">
<template #helperMessage> This is a helper message </template>
</spr-input>
<spr-input v-model="inputValue" label="Text Input" placeholder="Enter your text" :error="true">
<template #helperMessage>
<icon icon="ph:warning-circle-fill" width="20px" height="20px" />
<span>This is an error message</span>
</template>
</spr-input>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValue = ref('');
</script>Input Types
Search Input
<template>
<spr-input-search v-model="inputValueSearch" label="Search" placeholder="Search ..." />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValueSearch = ref('');
</script>Username Input
<template>
<spr-input-username v-model="inputValueUsername" label="Username" placeholder="Enter username" />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValueUsername = ref('');
</script>Email Input
<template>
<spr-input-email v-model="inputValueEmail" label="Username" placeholder="Enter email" />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValueEmail = ref('');
</script>Password Input
<template>
<spr-input-password v-model="inputValuePassword" label="Password" placeholder="Enter password" />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValuePassword = ref('');
</script>URL Input
<template>
<spr-input-url v-model="inputValueURL" label="URL" placeholder="Enter url" />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputValueURL = ref('');
</script>Contact Number Input
This component utilizes libphonenumber-js to parse and format the input on blur. Masking of contact number on change will be implemented in the future.
Model Output:
Selected Country Code:
Selected Country Calling Code:
Error Handling: []
Parsed International Number:
Importannt to note:
Since the v-model output is not in an international format (e.g., +63XXXXXXXXXXX), you will need to create a separate function that parses the model output along with the selected country code.
<template>
<div>
<div class="spr-grid spr-gap-4">
<spr-input-contact-number
v-model="inputValueContactNumber"
label="Contact Number"
@get-selected-country-calling-code="handleSelectedCountryCallingCode"
@get-contact-number-errors="handleContactNumberErrors"
/>
<spr-input-contact-number
v-model="inputValueContactNumber"
label="Disabled Calling Country Code"
@get-selected-country-calling-code="handleSelectedCountryCallingCode"
@get-contact-number-errors="handleContactNumberErrors"
disabledCountryCallingCode
/>
</div>
<p>Model Output: {{ inputValueContactNumber }}</p>
<p>Selected Country Code: {{ selectedCountryCode }}</p>
<p>Selected Country Calling Code: {{ selectedCountryCallingCode }}</p>
<p>Error Handling: {{ contactNumberErrors }}</p>
<p>Parsed International Number: {{ parseInternationalNumber }}</p>
</div>
<script lang="ts" setup>
import { ref, computed } from 'vue';
const inputValueContactNumber = ref('');
const selectedCountryCode = ref('');
const selectedCountryCallingCode = ref('');
const contactNumberErrors = ref([]);
const handleSelectedCountryCallingCode = (value: string) => {
selectedCountryCode.value = value.countryCode;
selectedCountryCallingCode.value = value.countryCallingCode;
};
const handleContactNumberErrors = (errors: { title: string; message: string }[]) => {
contactNumberErrors.value = errors;
};
const handleContactNumberErrors = (errors: { title: string; message: string }[]) => {
contactNumberErrors.value = errors;
};
const parseInternationalNumber = computed(() => {
if (inputValueContactNumber.value) {
const formattedNumber = `+${selectedCountryCallingCode.value}${inputValueContactNumber.value.replace(/[^0-9]/g, '')}`;
return formattedNumber;
}
return '';
});
</script>
</template>Set Pre Selected Country Code
<div class="spr-mt-3">
<spr-input-contact-number
v-model="inputValue"
label="Contact Number"
pre-selected-country-code="US"
/>
</div>Dropdown Input
This is the one used in the dropdown component. If you want to implement a dropdown, you can refer to the Dropdown Component.
<template>
<spr-input-dropdown v-model="dropdownInput" label="Dropdown Input" placeholder="Select an item ..." readonly />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const dropdownInput = ref('');
</script>API Reference
Props
| Name | Description | Type | Default |
|---|---|---|---|
| modelValue | The current value of the input field. This prop is used for v-model binding to enable two-way data binding between the component and parent. | string | number | '' |
| type | Specifies the type of input field, which determines its behavior and validation. Supports all standard HTML input types including:
| string | 'text' |
| id | Unique identifier for the input element. Used for associating the input with a label for accessibility. | string | 'spr-input' |
| label | Text label displayed above the input field to describe its purpose. | string | '' |
| supporting-label | Text beside label that has a supporting style | string | '' |
| placeholder | Hint text displayed inside the input when it's empty, providing guidance on what to enter. | string | '' |
| active | When set to true, the input will appear in its active/focused state even when not actually focused. | boolean | false |
| error | When set to true, displays the input in an error state with error styling. Typically used for validation feedback. | boolean | false |
| disabled | When set to true, makes the input non-interactive and visually indicates its disabled state. | boolean | false |
| readonly | When set to true, makes the input read-only, preventing users from modifying its value, but still allowing focus and selection. | boolean | false |
| minLength | Sets the minimum number of characters allowed in the input. Used for validation. | number | undefined |
| maxLength | Sets the maximum number of characters allowed in the input. Used for validation and with showCharCount to display limits. | number | undefined |
| showCharCount | When set to true, displays a character counter in the bottom right of the input field. When used with maxLength, shows current/max format. | boolean | false |
| offsetSize | Controls the spacing/offset size when using trailing content, affecting the positioning and padding:
| 'xs' | 'sm' | 'md' | 'sm' |
| displayHelper | When set to true, shows the helper text area below the input field. | boolean | false |
| helperText | Text content for the helper message displayed below the input field when displayHelper is true. | string | '' |
| helperIcon | Icon name from Iconify to display alongside the helper text. Particularly useful for warning or error messages. | string | null |
Events
| Name | Description | Parameters |
|---|---|---|
| update:modelValue | Emitted when the input value changes. This event enables v-model binding to work correctly. | (value: string | number): The new value of the input field. |
Slots
| Name | Description |
|---|---|
| prefix | Content to display at the beginning of the input field, typically used for icons or additional decorations. |
| trailing | Content to display at the end of the input field, used for units, additional text, or action buttons. |
| icon | Custom icon content to display inside the input field, particularly useful for custom input types. |
| helperMessage | Custom content for the helper message area, allowing more complex UI than just text and a single icon. |