Skip to content
HHydro UIdocs
Navigate
ImplementedForms / relationships

Field

Connect a control with its label, description, required state, and validation message.

Interactive

Try it

invalid, required, aria-label
Email addressUse your work address.Enter a valid email address.
Live previewReady
MarkupStateEvents
<hui-field id="playground-field">
  <hui-field-label>Email address</hui-field-label>
  <input type="email" value="name@example.com" />
  <hui-field-description>Use your work address.</hui-field-description>
  <hui-field-error>Enter a valid email address.</hui-field-error>
</hui-field>
data-state
Waiting for enhancement

No component events yet.

Usage

Use hui-field to connect a control with its label, description, required state, and error message. Do not use it as a replacement for the projected control's value, disabled state, or native constraint-validation behavior.

Anatomy

  • Root: hui-field
  • Label: hui-field-label
  • Description: hui-field-description
  • Error: hui-field-error
  • Projected control: one native or supported Hydro control

Examples

Fixture exampleSource-backed
<section aria-labelledby="field-heading">
    <h2 id="field-heading">Account details</h2>
    <form id="account-form">
      <hui-field id="email-field">
        <hui-field-label>Email</hui-field-label>
        <input name="email" type="email" value="person@example.com">
        <hui-field-description>Use your work address.</hui-field-description>
        <hui-field-error>Enter a valid email address.</hui-field-error>
      </hui-field>

      <hui-field id="invalid-field" invalid required>
        <hui-field-label>Username <span aria-hidden="true">*</span></hui-field-label>
        <input name="username" type="text" value="" required>
        <hui-field-description>Choose a unique username.</hui-field-description>
        <hui-field-error>Enter a username.</hui-field-error>
      </hui-field>
    </form>
  </section>

API reference

AttributeMeaning
idStable identity used to derive part IDs and deterministic ARIA references.
invalidMarks the field invalid and exposes aria-invalid="true" on its control.
requiredExposes required state through aria-required="true" on its control.
aria-labelOptional accessible name forwarded to the control.
aria-labelledbyAdditional accessible-name references forwarded to the control.
aria-describedbyAdditional description references forwarded to the control.

The field accepts one native control (input, select, or textarea) or one supported Hydro control such as hui-checkbox, hui-select, hui-combobox, hui-slider, or hui-number-field. The first matching control is wired; additional controls are left untouched. Invalid transitions emit hui-invalid-change with { invalid }.

States and styling

StateContract and styling guidance
DefaultValid field with projected label and description relationships.
HoverOwned by the projected control; use that component's interactive hover alias.
ActiveOwned by the projected control; use that component's interactive active alias.
FocusThe projected control keeps focus and its visible focus ring.
DisabledThe projected control owns disabled semantics and disabled tokens.
Errorinvalid exposes data-invalid, aria-invalid, and the active error relationship; use --hui-color-danger for messages.
State channel

Attributes are the source of truth. Style derived state with data-state, ARIA attributes, and the --hui-* token aliases.

Accessibility and keyboard support

Field adds no keyboard handling. The projected control remains responsible for its native keyboard behavior, focus ring, and validation semantics.

SSR and forms

The projected native or Hydro control remains usable without JavaScript. Stable field IDs allow generated label, description, and error relationships to survive server rendering and adoption.

Code

<hui-field id="email-field" invalid>
  <hui-field-label>Email</hui-field-label>
  <input id="email" name="email" type="email" />
  <hui-field-description>Use your work address.</hui-field-description>
  <hui-field-error>Enter a valid email address.</hui-field-error>
</hui-field>

The field adds no keyboard handling and does not replace native form validation. The projected control remains responsible for name, value, required, disabled, and constraint validation. Without JavaScript, the native control and its text remain usable; dynamic relationship updates require enhancement.

For a required field, put native required on the projected control as well as required on the field. Provide a visible, authored indicator; hide a decorative asterisk from assistive technology so it does not become part of the accessible name.

<hui-field id="username-field" required>
  <hui-field-label>Username <span aria-hidden="true">*</span></hui-field-label>
  <input name="username" type="text" required />
  <hui-field-description>Choose a unique username.</hui-field-description>
  <hui-field-error>Enter a username.</hui-field-error>
</hui-field>

The consumer decides when to set invalid, such as after blur or submission. Do not style every untouched required control as an error using a global :invalid rule.

Opt-in hui-user-validation styling uses native :user-invalid and :has() to mark interacted invalid controls and their labels without changing the field's invalid state or error relationships. The consumer still owns when to reveal authored errors. The hui-field-sizing-content class enables native input/textarea content sizing with a token-backed minimum and parent-width constraint; unsupported browsers retain normal sizing.

<hui-field id="playground-field">
  <hui-field-label>Email address</hui-field-label>
  <input type="email" value="name@example.com" />
  <hui-field-description>Use your work address.</hui-field-description>
  <hui-field-error>Enter a valid email address.</hui-field-error>
</hui-field>