Skip to content

Text field

Preview

Source code
html
<h-text-field
    v-model="a"
    name="Text field example"
    label="Label text"
    :kind="state.kind"
    :disabled="state.disabled"
    :required="state.required"
    :show-required="state.required"
    :max-length="state.lengthLimit ? 20 : undefined"
    :min-length="state.lengthLimit ? 5 : undefined"
    :has-error="state.error"
    :multiline="state.multiline"
    :placeholder="state.placeholder ? 'Placeholder text' : ''"
>
    <template #helper    v-if="state.helper">Helper text</template>
    <template #prepended v-if="state.iconPrepended"><search/></template>
    <template #appended  v-if="state.iconAppended">
        <button
            @click="a = ''"
            aria-label="Clear input"
            :disabled="state.disabled"
        >
            <close-circle />
        </button>
    </template>
</h-text-field>
<h-text-field
    v-model="a"
    name="Text field example"
    label="Label text"
    :kind="state.kind"
    :disabled="state.disabled"
    :required="state.required"
    :show-required="state.required"
    :max-length="state.lengthLimit ? 20 : undefined"
    :min-length="state.lengthLimit ? 5 : undefined"
    :has-error="state.error"
    :multiline="state.multiline"
    :placeholder="state.placeholder ? 'Placeholder text' : ''"
>
    <template #helper    v-if="state.helper">Helper text</template>
    <template #prepended v-if="state.iconPrepended"><search/></template>
    <template #appended  v-if="state.iconAppended">
        <button
            @click="a = ''"
            aria-label="Clear input"
            :disabled="state.disabled"
        >
            <close-circle />
        </button>
    </template>
</h-text-field>

Text fields allow users to enter text into a UI. They typically appear in forms and dialogs. See the Material 3 documentation on this component.

Props

ts
defineProps<{
  // The name of the input. Must be unique on the page.
  name: string

  // The kind of input to render.
  kind: 'outlined' | 'filled'

  // The HTML input type to assign to this input.
  // See [1].
  // This will likely not work with input types which the browser renders in
  // special ways.
  inputType?: string

  // The label text to use.
  label: string

  // Passes along the HTML `required` attribute.
  required?: boolean

  // Show styling for the input being required. Note that this doesn't change
  // the HTML attribute. See [2] for guidance on when to use this.
  showRequired?: boolean

  // The text to use for the "required" text displayed in the supporting text
  // slot. Defaults to "required". Intended for localization.
  requiredText?: string

  // Whether the input is disabled.
  disabled?: boolean

  // The maximum (exclusive) length for this input.
  // You should not use this to actually validate input length, as HTML and JS
  // might not agree on how long an input is, and someone can simply edit the
  // contents regardless.
  maxLength?: number

  // The minimum (exclusive) length for this input.
  // See caveats on maxLength.
  minLength?: number

  // Whether to display an error state on this input.
  hasError?: boolean

  // Whether this input should allow multiple lines of input.
  multiline?: boolean

  // How many rows to render when using multiple lines of input by default.
  rows?: number

  // The placeholder text to show when the input is empty.
  placeholder?: string

  // A function which returns the text to use in the `aria-label` for the
  // character count. Defaults to
  // (current, max) => `Character count, ${current} out of ${max} characters entered`.
  // Intended for localization.
  formatCharCountText?:(current: number, max: number) => string

  // Whether to clean the input value before emitting it. Defaults to false.
  // "Cleaned" indicates running the value through this function:
  // (s: string) => s?.trim().split(/\s+/).join(' ') || ''
  // The length calculation uses the cleaned value, so it can be useful. However,
  // with multiline inputs in particular, this can be problematic.
  returnRaw?: boolean
  
  // Passes along the HTML `autocomplete` attribute.
  autocomplete?: string

  modelValue?: string
}>()
defineProps<{
  // The name of the input. Must be unique on the page.
  name: string

  // The kind of input to render.
  kind: 'outlined' | 'filled'

  // The HTML input type to assign to this input.
  // See [1].
  // This will likely not work with input types which the browser renders in
  // special ways.
  inputType?: string

  // The label text to use.
  label: string

  // Passes along the HTML `required` attribute.
  required?: boolean

  // Show styling for the input being required. Note that this doesn't change
  // the HTML attribute. See [2] for guidance on when to use this.
  showRequired?: boolean

  // The text to use for the "required" text displayed in the supporting text
  // slot. Defaults to "required". Intended for localization.
  requiredText?: string

  // Whether the input is disabled.
  disabled?: boolean

  // The maximum (exclusive) length for this input.
  // You should not use this to actually validate input length, as HTML and JS
  // might not agree on how long an input is, and someone can simply edit the
  // contents regardless.
  maxLength?: number

  // The minimum (exclusive) length for this input.
  // See caveats on maxLength.
  minLength?: number

  // Whether to display an error state on this input.
  hasError?: boolean

  // Whether this input should allow multiple lines of input.
  multiline?: boolean

  // How many rows to render when using multiple lines of input by default.
  rows?: number

  // The placeholder text to show when the input is empty.
  placeholder?: string

  // A function which returns the text to use in the `aria-label` for the
  // character count. Defaults to
  // (current, max) => `Character count, ${current} out of ${max} characters entered`.
  // Intended for localization.
  formatCharCountText?:(current: number, max: number) => string

  // Whether to clean the input value before emitting it. Defaults to false.
  // "Cleaned" indicates running the value through this function:
  // (s: string) => s?.trim().split(/\s+/).join(' ') || ''
  // The length calculation uses the cleaned value, so it can be useful. However,
  // with multiline inputs in particular, this can be problematic.
  returnRaw?: boolean
  
  // Passes along the HTML `autocomplete` attribute.
  autocomplete?: string

  modelValue?: string
}>()
  1. MDN docs on input
  2. Material 3 docs on the required attribute

Slots

helper

The helper slot is used for the helper text (called the supporting text in the official documentation).

prepended

The prepended slot is used for the prepended icon (i.e. the one at the start).

appended

The appended slot is used for the appended icon (i.e. the one at the end).

Known issues

  1. The text displayed in the supporting text is not used for the accessibility label, as proscribed by the docs.

Made with ❤ by Autumn