Skip to content

Early previewhamur is not on npm yet. The components are being built in the open, follow along on GitHub.

FormsReact

Field

Labels and validates a form control.

Rendered by React 19.3.1

import { Field } from '@hamur/react/field'

export default function FieldExample() {
  return (
    <Field.Root name="email" className="field" validationMode="onBlur">
      <Field.Label>Email</Field.Label>
      <Field.Control
        className="input"
        type="email"
        required
        placeholder="name@example.com"
      />
      <Field.Description className="muted">
        We never share your address.
      </Field.Description>
      <Field.Error className="error" />
    </Field.Root>
  )
}
502Tests passing in React · 0 failing
11.1 KiBSize
Not measured yetMemory
Not measured yetSpeed
productdevbook and 16 upstream authors22 commits · last

Installation

npm i @hamur/react

Not on npm yet. The package goes out under the chosen name.

Anatomy

Import the component and assemble its parts:

<Field.Root>
  <Field.Label />
  <Field.Control />
  <Field.Description />
  <Field.Error />
</Field.Root>

// Not in this example: Field.Item, Field.Validity

Examples

The demo at the top is the one example this component has so far.

API reference

15 props across 7 parts, in React syntax. className, style, render are listed once, under Shared props.

ControlField.Control

The form control to label and validate. You can omit this part and use any Base UI input component instead. For example, Input, Checkbox, or Select, among others, will work with Field out of the box. Renders an <input>.

Control props
PropTypeDefault
defaultValuestring | number | readonly string[]—
onValueChangeCallback fired when the value changes.((value: string, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void)—
Control data attributes
Data 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-touchedPresent when the field has been touched.
data-dirtyPresent when the field's value has changed.
data-filledPresent when the field is filled.
data-focusedPresent when the field control is focused.

DescriptionField.Description

A paragraph with additional information about the field. Renders a <p>.

Description data attributes
Data 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-touchedPresent when the field has been touched.
data-dirtyPresent when the field's value has changed.
data-filledPresent when the field is filled.
data-focusedPresent when the field control is focused.

ErrorField.Error

An error message displayed if the field control fails validation. Renders a <div>.

Error props
PropTypeDefault
matchDetermines whether to show the error message according to the field'sboolean | keyof ValidityState—
Error data attributes
Data 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-touchedPresent when the field has been touched.
data-dirtyPresent when the field's value has changed.
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.

ItemField.Item

Groups individual items in a checkbox group or radio group with a label and description. Renders a <div>.

Item props
PropTypeDefault
disabledWhether the wrapped control should ignore user interaction.booleanfalse
Item data attributes
Data 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-touchedPresent when the field has been touched.
data-dirtyPresent when the field's value has changed.
data-filledPresent when the field is filled.
data-focusedPresent when the field control is focused.

LabelField.Label

An accessible label that is automatically associated with the field control. Renders a <label>.

Label props
PropTypeDefault
nativeLabelWhether the component renders a native <label> element when replacing it via the render prop.booleantrue
Label data attributes
Data 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-touchedPresent when the field has been touched.
data-dirtyPresent when the field's value has changed.
data-filledPresent when the field is filled.
data-focusedPresent when the field control is focused.

RootField.Root

Groups all parts of the field. Renders a <div>.

Root props
PropTypeDefault
nameIdentifies the field when a form is submitted.string—
actionsRefA ref to imperative actions.React.RefObject<FieldRootActions | null>—
dirtyWhether the field's value has been changed from its initial value.boolean—
touchedWhether the field has been touched.boolean—
disabledWhether the component should ignore user interaction.booleanfalse
invalidWhether the field is invalid.boolean—
validateA function for custom validation.((value: unknown, formValues: Record<string, any>) => string | void | string[] | Promise<string | void | string[] | null> | null)—
validationModeDetermines when the field should be validated.FormValidationMode'onSubmit'
validationDebounceTimeHow long to wait between validate callbacks ifnumber0
Root data attributes
Data attributeDescription
data-disabledPresent when the field is disabled.
data-touchedPresent when the field has been touched.
data-dirtyPresent when the field's value has changed.
data-validPresent when the field is valid.
data-invalidPresent when the field is invalid.
data-filledPresent when the field is filled.
data-focusedPresent when the field control is focused.

ValidityField.Validity

Used to display a custom message based on the field's validity. Requires children to be a function that accepts field validity state as an argument.

Validity props
PropTypeDefault
childrenrequiredA function that accepts the field validity state as an argument.(state: FieldValidityState) => React.ReactNode—

Shared props

Every part that renders an element takes these.

Shared props
PropType
classNameCSS class applied to the element, or a function that returns a class based on the component's state.string | ((state: State) => string | undefined)
styleStyle applied to the element, or a function that returns a style object based on the component's state.React.CSSProperties | ((state: State) => React.CSSProperties | undefined)
renderAllows you to replace the component's HTML element with a different tag, or compose it with another component.React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State>

Keyboard and accessibility

Keyboard

Field adds no keys; the control inside keeps its own. Pressing Enter in a form still submits it, and the field validates first.

Accessibility

What the parts set
PartSetsSo that
Labela <label> tied to the control, or aria-labelledby on the control when nativeLabel is offthe control is read with its name, and clicking the label focuses it
Controlaria-describedby to Description and Errorthe hint and the error are read with the control
Controlaria-invalid="true" when validation failsa screen reader says the value is not accepted
Errorrenders only while there is an error to showan empty error is never announced
Itemgroups one checkbox or radio with its own label and descriptioneach option in a group is named on its own

Focus order

  1. Control is the field's tab stop; Label, Description and Error are not focusable.
  2. When a form is submitted with errors, focus moves to the first invalid control (Form).