Inputs

Text field

The foundation of every form: a labelled single-line input with filled and outlined surfaces, leading and trailing slots, helper text, and error states connected to the theme.

We only use it to send the invite

At least 8 characters

Name every field

A field without a programmatic name is unusable with assistive technology.

  • Label ties to input

    The label's for attribute references the input id so the name is announced on focus.

  • Supporting text is described

    Helper and error text are linked with aria-describedby so they are read after the name.

  • Invalid is programmatic

    The error state sets aria-invalid so the field's validity is exposed, not only shown by color.

  • Required is explicit

    The required prop sets the native required attribute rather than relying on an asterisk alone.

Keyboard and focus

Every field must be reachable and editable without a pointer.

  • Tab reaches the input

    The field is a native input, so Tab moves to it and Shift+Tab moves away in reading order.

  • Visible focus

    Focus lifts the container rule or outline so keyboard users can see the active field.

  • Read only stays focusable

    A read-only field can still receive focus so its value can be selected and copied.

  • Disabled leaves the order

    A disabled field is removed from the tab order and cannot trap focus.

Names and status

A visible field still needs a complete assistive-technology contract. Tab through the fields to hear what a screen reader announces.

A screen reader announces

  • Accessible name

    The visible label becomes the field's accessible name; never ship a field without one.

  • Error is announced

    The error message is linked with aria-describedby so it is read alongside the field's name.

  • Required and read only

    Required and read-only states are exposed natively so their status is not conveyed by color alone.

  • Comfortable target

    Keep the container height and spacing generous enough to focus reliably on touch.

Vue
<m-text-field
  v-model="email"
  label="Work email"
  required
  :error="invalid"
  :error-message="invalid ? 'Enter a valid email' : undefined"
/>