Field

A component that provides labeling and validation for form controls. Pair it with Form when you need submit-time errors. color tints the control wash. inline makes that wash transparent. Labels are Regular, descriptions and errors are Light.

Visible on your profile

Focus the name field and leave it empty to see the valueMissing error. The description stays visible underneath.

Usage guidelines

  • Accessible name: Use UiFieldLabel. It is associated with the control automatically.
  • When to validate: Standalone fields default to onBlur. Inside Form they default to onSubmit, then re-validate on change after submit.
  • Other controls: Omit UiFieldControl and use Input, Checkbox, or Select. Field still wires the label, description, and error.
  • External validity: Set invalid and show UiFieldError with match true when another library owns the error.

Anatomy

<UiFieldRoot>
  <UiFieldLabel />
  <UiFieldControl />
  <UiFieldDescription />
  <UiFieldItem />
  <UiFieldError />
  <UiFieldValidity />
</UiFieldRoot>

You can omit UiFieldControl and use Input, Checkbox, or Select instead. They work with Field out of the box.

Examples

Disabled

disabled on Root ignores interaction and sets data-disabled on every part. It takes precedence over disabled on Control.

Visible on your profile

Invalid

Set invalid when an external library owns validity. UiFieldError with match true always shows, so the library can control visibility.

We’ll never share this

Custom validation

Pass validate to return a string (or array of strings) when the value is invalid. Returning nothing, null, an empty string, or an empty array means the value is valid. Pair UiFieldError match="customError" with native matches such as valueMissing.

Used to sign in

<UiFieldRoot :validate="(value) => String(value).length < 3 ? 'Use at least 3 characters' : undefined">
  <UiFieldLabel>Username</UiFieldLabel>
  <UiFieldControl required />
  <UiFieldError match="valueMissing">Please choose a username</UiFieldError>
  <UiFieldError match="customError" />
</UiFieldRoot>

Validation mode

Standalone fields default to onBlur. Inside Form they default to onSubmit, then re-validate on change after submit. Set validationMode on Root to override:

  • onSubmit — validate when the form is submitted, then re-validate on change
  • onBlur — validate when the control loses focus
  • onChange — validate on every change

validationDebounceTime delays onChange validate callbacks, in milliseconds.

Validates on every change

Pattern

Native pattern sets patternMismatch after blur (or according to validationMode).

Four letters, A–Z

Field items

UiFieldItem groups a checkbox or radio with its own label and description. Item disabled ignores that row; Root disabled still wins. Prefer native-button on the checkbox when the label is a sibling (for / id).

Apples

Crisp and extra sweet

Mild and aromatic

Tart, good for baking

<UiFieldRoot name="apple">
  <UiFieldLabel :native-label="false">Apples</UiFieldLabel>
  <UiCheckboxGroup>
    <UiFieldItem>
      <UiCheckboxRoot native-button value="fuji">
        <UiCheckboxIndicator />
      </UiCheckboxRoot>
      <UiFieldLabel>Fuji</UiFieldLabel>
      <UiFieldDescription>Crisp and extra sweet</UiFieldDescription>
    </UiFieldItem>
  </UiCheckboxGroup>
</UiFieldRoot>

Validity

UiFieldValidity takes a scoped slot with { validity, error, errors, value, initialValue } so you can render a custom message from ValidityState.

filled: no · valid: —

<UiFieldValidity v-slot="{ validity, error }">
  <p v-if="validity.valid === false">{{ error }}</p>
</UiFieldValidity>

Other controls

Omit Control and drop in Input (or Checkbox, Select, …). Field still wires the label, description, and error.

You can omit Control and use Input instead

<UiFieldRoot>
  <UiFieldLabel>Name</UiFieldLabel>
  <UiInput required placeholder="e.g. Colm Tuite" />
  <UiFieldError match="valueMissing">Please enter your name</UiFieldError>
</UiFieldRoot>

Native label

nativeLabel defaults to true and renders a <label>. Set it false for Select and Combobox triggers so hovering or clicking the label does not fire on the trigger button.

Country

nativeLabel false avoids label behavior on triggers

<UiFieldLabel :native-label="false">Country</UiFieldLabel>

API reference

Parts receive data-disabled, data-valid, data-invalid, data-dirty, data-touched, data-filled, and data-focused from Root.

Root

Groups all parts of the field. Renders a <div>. Call validate() on a template ref to run the same checks as submit or blur.

PropTypeDefaultDescription
namestring—Identifies the field when a form is submitted. Takes precedence over name on Control.
disabledbooleanfalseIgnore interaction. Takes precedence over Control disabled.
invalidboolean—Force invalid when an external library owns state.
dirtyboolean—Controlled dirty. Uncontrolled: value differs from the initial value.
touchedboolean—Controlled touched. Uncontrolled: set on blur.
validate(value, formValues) => string | string[] | void | null | Promise<…>—Custom validation. Return a message (or array) when invalid. Async results do not block onSubmit.
validationMode'onSubmit' | 'onBlur' | 'onChange''onBlur' standalone, 'onSubmit' in FormWhen to validate. Takes precedence over Form.
validationDebounceTimenumber0Milliseconds to wait between onChange validate calls.
AttributeDescription
data-disabledPresent when the field is disabled.
data-validPresent when the field is valid.
data-invalidPresent when the field is invalid.
data-dirtyPresent when the value has changed from its initial value.
data-touchedPresent when the field has been touched.
data-filledPresent when the field has a value.
data-focusedPresent when the control is focused.

Label

Accessible label associated with the control. Renders a <label> by default.

PropTypeDefaultDescription
nativeLabelbooleantrueSet false to render a <span> instead of <label> (for Select / Combobox triggers).
forstringcontrol idOverride the labelled control.
AttributeDescription
data-disabledPresent when the field is disabled.
data-validPresent when the field is in a valid state.
data-invalidPresent when the field is in an invalid state.
data-dirtyPresent when the field’s value has changed.
data-touchedPresent when the field has been touched.
data-filledPresent when the field is filled.
data-focusedPresent when the field control is focused.

Control

Native <input>. Extra attributes such as type, required, pattern, min, max, and maxlength pass through. You can omit this part and use Input, Checkbox, or Select instead.

PropTypeDefaultDescription
defaultValuestring | number—Uncontrolled initial value.
valuestring—Controlled value (v-model:value).
disabledbooleanfalseIgnore this control. Root disabled still wins.
namestringRoot nameSubmitted name. Root name takes precedence.
AttributeDescription
data-disabledPresent when the field is disabled.
data-validPresent when the field is in a valid state.
data-invalidPresent when the field is in an invalid state.
data-dirtyPresent when the field’s value has changed.
data-touchedPresent when the field has been touched.
data-filledPresent when the field is filled.
data-focusedPresent when the field control is focused.

Description

Supporting text. Renders a <p>. Referenced by aria-describedby.

AttributeDescription
data-disabledPresent when the field is disabled.
data-validPresent when the field is in a valid state.
data-invalidPresent when the field is in an invalid state.
data-dirtyPresent when the field’s value has changed.
data-touchedPresent when the field has been touched.
data-filledPresent when the field is filled.
data-focusedPresent when the field control is focused.

Item

Groups a checkbox or radio with its own label and description. Renders a <div>.

PropTypeDefaultDescription
disabledbooleanfalseIgnore this item. Root disabled takes precedence.
AttributeDescription
data-disabledPresent when the field or item is disabled.
data-validPresent when the field is in a valid state.
data-invalidPresent when the field is in an invalid state.
data-dirtyPresent when the field’s value has changed.
data-touchedPresent when the field has been touched.
data-filledPresent when the field is filled.
data-focusedPresent when the field control is focused.

Error

Shown after validation. Renders a <div role="alert">. Animate with data-starting-style / data-ending-style. Omit match to show whenever the field is invalid. Empty content uses the native or form message.

PropTypeDefaultDescription
matchboolean | 'valid' | 'badInput' | 'customError' | 'patternMismatch' | 'rangeOverflow' | 'rangeUnderflow' | 'stepMismatch' | 'tooLong' | 'tooShort' | 'typeMismatch' | 'valueMissing'—true always shows (for external libraries). A ValidityState key shows when that flag is set.
AttributeDescription
data-disabledPresent when the field is disabled.
data-validPresent when the field is in a valid state.
data-invalidPresent when the field is in an invalid state.
data-dirtyPresent when the field’s value has changed.
data-touchedPresent when the field has been touched.
data-filledPresent when the field is filled.
data-focusedPresent when the field control is focused.
data-starting-stylePresent when the error message begins animating in.
data-ending-stylePresent when the error message is animating out.

Validity

Scoped slot for a custom message from field validity.

<UiFieldValidity v-slot="{ validity, error, errors, value, initialValue }">
  …
</UiFieldValidity>
FieldDescription
validityNative ValidityState plus valid: boolean | null.
errorCurrent error string.
errorsAll current error strings.
valueCurrent control value.
initialValueValue when the control registered.