SwInput

SwInput is a text input: a thin wrapper over the native <input> whose value is the unified baseline box, not extra features — it shares the box model of the SwSelect trigger (--control-height / --control-font-size / --input border / --radius), so SwInput / SwSelect / SwSegmented align to the same height and font size by default when mixed in one row, and appliers no longer hand-roll input box styles.

Undeclared native attributes (placeholder / maxlength / autocomplete / name / readonly …) and native event listeners automatically land on the inner <input> (inheritAttrs: false + v-bind="$attrs") — the root is a .sw-input wrapper (carrying the box styles and trailing icon buttons); passthrough behavior is unchanged for callers.

iOS focus-zoom counter-measure: iOS Safari auto-zooms the page when a text input with font-size < 16px gets focused. On touch devices (hover: none + pointer: coarse) SwInput bumps its default font size back to 1rem while the height stays 32px; an explicit --sw-input-font-size override applies on both ends.

Basic usage

v-model + native attribute fallthrough

加载中...
<script setup lang="ts">
const keyword = ref('')
</script>

<template>
  <SwInput v-model="keyword" placeholder="Search keyword" maxlength="50" />
</template>

With SwFormField (error state)

Error copy is not SwInput's job — pair with SwFormField for inline messages; SwInput's error only handles the destructive border + aria-invalid:

SwFormField simple mode + error border / disabled

加载中...
<SwFormField label="Email" required :error="emailError">
  <SwInput v-model="email" type="email" :error="!!emailError" />
</SwFormField>

vee-validate mode injects via v-bind="field":

<SwFormField name="email" label="Email" v-slot="{ field, error }">
  <SwInput v-bind="field" type="email" :error="!!error" />
</SwFormField>

Clear button & password visibility

clearable shows a trailing clear button when the value is non-empty (clears + refocuses the input + emits clear); revealable only takes effect with type="password" and toggles plain/cipher text (silently ignored for other types). Enabling either reserves trailing padding permanently (no text jumping), with built-in touch hit area (sw-hit-area) and localized aria-labels:

clearable + revealable password toggle

加载中...
<SwInput v-model="keyword" clearable placeholder="Search" @clear="onCleared" />
<SwInput v-model="password" type="password" clearable revealable />

Aligned form-control row

SwInput + SwSelect + SwSegmented aligned by default

加载中...

Props

NameTypeRequiredDefaultNotes
modelValue (v-model)string | number''Controlled value; emits string on input (type="number" also emits string — convert in app code)
type'text' | 'password' | 'search' | 'email' | 'tel' | 'url' | 'number''text'Native type
disabledbooleanfalseDisabled state
errorbooleanfalseError state (destructive border + aria-invalid), a boolean (matching Vuetify); pair error copy with SwFormField — whose error is an error-message string, so wire them as :error="!!field.error"
clearablebooleanfalseTrailing clear button: shown when non-empty and not disabled; click = clear + emit update:modelValue('') + emit clear + refocus
revealablebooleanfalsePassword visibility toggle, only with type="password" (silently ignored otherwise + dev warn); toggles internal display only, type prop unchanged

All other native attributes fall through — no component declaration needed.

Events

NamePayloadNotes
update:modelValuevalue: stringFired on input
clear—Emitted when the clear button is clicked (after update:modelValue(''))

Native events (focus / blur / change …) can be listened to directly via fallthrough.

Styling Tokens

TokenDefaultApplies to
--sw-input-min-heightvar(--control-height)min-height
--sw-input-padding0.25rem 0.75rempadding
--sw-input-bordervar(--input)border color
--sw-input-radiusvar(--radius)border radius
--sw-input-bgvar(--background)background
--sw-input-colorvar(--foreground)text color
--sw-input-font-sizevar(--control-font-size) (touch devices: 1rem)font size
--sw-input-error-bordervar(--destructive)error border color
--sw-input-placeholder-colorvar(--muted-foreground)Placeholder text color

Default height / font size come from the form-control semantic tokens --control-height (32px) / --control-font-size (14px) — override these two tokens to scale every control site-wide (component-level tokens still take precedence).

Caveats

  • Native DOM / imperative focus: the root is a wrapper ($el is no longer the <input>) — use the exposed focus() / blur() / select(): inputRef.value?.focus().
  • Error copy is external: error only styles the border; render the message via SwFormField's error prop / vee-validate.
  • Not for multi-line text: this wraps a single-line <input> only; use a native <textarea> for now (SwTextarea is shape-reserved, pending a real consumer).
  • Aligning submit buttons in a form: SwButton stays unstyled (does not consume --control-height); give form buttons height: var(--control-height) in app code.

See Also