Input
A text input with optional leading and trailing icons.
Usage
<script setup lang="ts">
const value = ref('')
</script>
<template>
<SInput v-model="value" placeholder="Type something..." />
</template>
Input is full-width by default, rather than needing an opt-in flag to make
it so - constrain it with a class on the component itself (as the examples
on this page do with max-w-xs), not a wrapping element.
Icons
icon and trailingIcon add an icon before or after the text - the same
props Button uses for its own.
<SInput v-model="search" icon="hugeicons:search-01" placeholder="Search..." />
<SInput v-model="amount" trailing-icon="hugeicons:dollar-01" placeholder="0.00" />
Custom leading and trailing content
Use #leading and #trailing for text, icons, or buttons inside the field frame.
The slots receive { disabled, size, buttonSize }; buttonSize fits a Button
inside the current field size. Give interactive controls an accessible label,
use type="button", and pass disabled through to match the field state.
Custom content stays visible alongside the built-in clear button. It replaces the corresponding decorative icon or trailingIcon.
The field reserves space for the rendered content, including suffixes whose
width changes. Use ui.leading and ui.trailing to customize its wrappers.
<script setup lang="ts">
const password = ref('')
const visible = ref(false)
</script>
<template>
<SInput v-model="password" :type="visible ? 'text' : 'password'" clearable aria-label="Password">
<template #trailing="{ disabled, buttonSize }">
<SButton
type="button" :disabled="disabled" :size="buttonSize" variant="text" color="neutral" square
:icon="visible ? 'hugeicons:view-off-slash' : 'hugeicons:view'"
:aria-label="visible ? 'Hide password' : 'Show password'" :aria-pressed="visible"
@click="visible = !visible"
/>
</template>
</SInput>
</template>
Text prefixes and suffixes use the same slots:
Clear
clearable adds a button that empties the value, once there's something to
clear - it takes over the trailing position from trailingIcon while active,
the same way Select's does.
<SInput v-model="value" clearable placeholder="Type something..." />
Sizes and states
size takes sm / md / lg, disabled prevents interaction and dims the
input, and invalid switches the ring to the danger role's focus color:
<SInput v-model="email" invalid placeholder="[email protected]" />
See the Props table below.
Colors
color sets the focus-ring color - the resting (unfocused) ring stays
--selaras-resolved-border-default regardless, and invalid always wins over a custom color:
<SInput v-model="primary" color="primary" placeholder="Primary" />
<SInput v-model="success" color="success" placeholder="Success" />
<SInput v-model="danger" color="danger" placeholder="Danger" />
Masking
Use the v-mask directive to format the text as
it's typed. v-model keeps the raw value, while the field shows the
formatted one - typing 5551234567 below shows (555) 123-4567, and
phone is 5551234567:
Value: —
<SInput v-model="phone" v-mask="'(###) ###-####'" inputmode="tel" />
Forms integration
Wrap it in FormField to get id/name/invalid
and aria-describedby wired up automatically, plus a hint/error message
underneath - FormField is also where size and invalid fall back to when
not set directly on the input.
Accessibility
Input renders a plain native <input>, so browser and screen-reader support
for typing, selection, and autofill all come for free. aria-invalid and
aria-describedby are set automatically once invalid is true or the input
is wrapped in FormField - nothing to
configure by hand for the common case.
Custom :ui
To see exactly what you'd be overriding - the current default classes for
every slot and variant - here's Input's own theme file:
Props
| Prop | Type | Default |
|---|---|---|
id | string | - |
name | string | - |
modelValue | string | number | - |
type | string | text |
placeholder | string | - |
size | 'sm' | 'md' | 'lg' | md |
disabled | boolean | false |
invalid | boolean | false |
color | 'primary' | 'neutral' | 'secondary' | 'success' | 'danger' | 'info' | 'warning' | primary |
clearable | boolean | false |
icon | string | - |
trailingIcon | string | - |
ui | Partial<Record<'root' | 'base' | 'leadingIcon' | 'trailingIcon' | 'leading' | 'trailing' | 'clear', string | object>> | - |
Slots
| Slot | Props | Description |
|---|---|---|
leading | { disabled, size, buttonSize } | Custom content before the text; replaces icon |
trailing | { disabled, size, buttonSize } | Custom content after the text, alongside the clear button; replaces trailingIcon |
clear-icon | - | Replaces the clear button's icon (default: hugeicons:cancel-01) |