Build your own field

The label, description and error around a control envUI has no field for.

BetaSince 1.0.0
On this page

Overview

Show code, ProjectName.tsx

Anatomy

  1. Field

  2. Label

  3. Control

  4. Description

  5. Error

Show code, FieldAnatomy.tsx

Behaviour

Validate on blur

A field can check its value with a check of the application's own, which returns an error message or nothing, on submit, on blur or as people type.

Show code, ValidateOnBlur.tsx

A control of the application's own

The control can be any control, which the label and the description then name and describe.

Show code, ApplicationControl.tsx

Rules

An error shows once people have had a chance to answer, and adds to the description.

Use it when

  • A label, a description and an error for a control of the application's own
  • A value checked on blur or on submit, by the browser's rules or a check of its own
DoShow an error once people leave the field or submit.
Show code, ErrorAfterLeaving.tsx
Don’tAn error before people have had a chance to type.
Show code, ErrorOnArrival.tsx

Description and error

Keep the description while the error shows: the error adds to it.

Beside envUI's fields

Field is the low-level building block, its label above the control, while TextField, Select, the pickers and the other form fields take the notched label in their edge. Build a form's fields from those, and keep Field for a control they don't cover, so one form doesn't mix the two labels.

Accessibility

Keyboard

KeyAction
Tab, Shift+TabMoves to the control; no other part takes focus.

envUI provides

  • A label linked to the control, whose press focuses it.
  • The description and error as the control's description, and aria-invalid.
  • The error icon hidden from assistive technology.

You provide

  • A label for every field.
  • A control in render that forwards its props and ref to the element people use.

Import

import { Field } from '@envsemble/envui';

Usage

Field.Root holds a Field.Label, a Field.Control, a Field.Description and a Field.Error, and gives the field its name for a form. Field.Control is a native input by default.

  • It takes its native props, such as required and maxLength.
  • It takes defaultValue, or value and onValueChange.
  • It takes size, sm, md or lg, the control heights.
ProjectName.tsx
import { Field } from '@envsemble/envui';

export default function ProjectName() {
  return (
    <Field.Root name="project" style={{ maxInlineSize: '24rem' }}>
      <Field.Label>Project name</Field.Label>
      <Field.Control placeholder="Northwind launch" required maxLength={40} />
      <Field.Description>
        Up to 40 characters; people see it in their project list.
      </Field.Description>
      <Field.Error match="valueMissing">Enter a project name.</Field.Error>
    </Field.Root>
  );
}

Validation

validate on Field.Root returns an error message for a value, or nothing for a valid one.

  • validationMode checks onSubmit, the default, onBlur or onChange, with validationDebounceTime between checks as people type.
  • Without children, Field.Error shows the field's validation message, the one validate returns or the browser's; match shows an error for one kind of failure only, such as valueMissing.
  • invalid, dirty and touched take the state from a form library, and actionsRef validates on demand.
<Field.Root name="handle" validationMode="onBlur" validate={checkAddress}>
  <Field.Label>Workspace address</Field.Label>
  <Field.Control />
  <Field.Error />
</Field.Root>

Any control

render on Field.Control takes any control, which receives the id, the ids of the label and the description, and the ref; it must forward them to the element people use. A control that draws its own frame can take the field's outline off through style, as the ApplicationControl example does.

<Field.Control
  render={<Volume />}
  value={String(volume)}
  onValueChange={(next) => setVolume(Number(next))}
  style={{ border: 0, background: 'none', paddingInline: 0 }}
/>

Composition

The parts are the root, env-field, the label, env-field-label, the control, env-field-control, the description, env-field-description, and the error, env-field-error. TextField, DatePicker and envUI's other fields are built from them, and so are fields of an application's own. disabled and name on Field.Root take precedence over the control's.

Props

Field.Root

A labelled form control with its description and error, for a control envUI has no field for, such as a control of the application's own: Field.Label names Field.Control, and the description and the error describe it, with ids, aria-invalid and the disabled state wired through Base UI's Field.

PropTypeDescription
style
React.CSSProperties((state: State) => React.CSSProperties | undefined)undefined
Passed to Base UI. Style applied to the element, or a function that returns a style object based on the component's state.
disabledDefault false
booleanundefined
Passed to Base UI. Whether the component should ignore user interaction. Takes precedence over the `disabled` prop on the `<Field.Control>` component.
name
stringundefined
Passed to Base UI. Identifies the field when a form is submitted. Takes precedence over the `name` prop on the `<Field.Control>` component.
validate
((value: unknown, formValues: Form.Values) => string | string[] | null | void | Promise<string | string[] | null | void>)undefined
Passed to Base UI. A function for custom validation. Return a string or an array of strings with the error message(s) if the value is invalid. Returning nothing, `null`, an empty string, or an empty array means the value is valid. Asynchronous functions are supported, but they do not prevent form submission when using `validationMode="onSubmit"`.
validationModeDefault 'onSubmit'
Form.ValidationModeundefined
Passed to Base UI. Determines when the field should be validated. This takes precedence over the `validationMode` prop on `<Form>`. - `onSubmit`: triggers validation when the form is submitted, and re-validates on change after submission. - `onBlur`: triggers validation when the control loses focus. - `onChange`: triggers validation on every change to the control value.
validationDebounceTimeDefault 0
numberundefined
Passed to Base UI. How long to wait between `validate` callbacks if `validationMode="onChange"` is used. Specified in milliseconds.
invalid
booleanundefined
Passed to Base UI. Whether the field is invalid. Useful when the field state is controlled by an external library.
dirty
booleanundefined
Passed to Base UI. Whether the field's value has been changed from its initial value. Useful when the field state is controlled by an external library.
touched
booleanundefined
Passed to Base UI. Whether the field has been touched. Useful when the field state is controlled by an external library.
actionsRef
React.RefObject<FieldRoot.Actions | null>undefined
Passed to Base UI. A ref to imperative actions. - `validate`: Validates the field when called.
render
React.ReactElementComponentRenderFn<RenderFunctionProps, State>undefined
Passed to Base UI. Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.
className
string
The part's class, beside its own env-field class.

Also accepts the native props of <div>, such as ref, className and aria-* attributes.

Field.Label

The field's visible name; it names the control for assistive technology.

PropTypeDescription
style
React.CSSProperties((state: State) => React.CSSProperties | undefined)undefined
Passed to Base UI. Style applied to the element, or a function that returns a style object based on the component's state.
render
React.ReactElementComponentRenderFn<RenderFunctionProps, State>undefined
Passed to Base UI. Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.
nativeLabelDefault true
booleanundefined
Passed to Base UI. Whether the component renders a native `<label>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a label (for example, `<div>`). This is useful to avoid inheriting label behaviors on `<button>` controls (such as `<Select.Trigger>` and `<Combobox.Trigger>`), including avoiding `:hover` on the button when hovering the label, and preventing clicks on the label from firing on the button.
className
string
The part's class, beside its own env-field class.

Also accepts the native props of <label>, such as ref, className and aria-* attributes.

Field.Control

The control: a native text input in the outlined field look by default, or any control through render, such as render={<MyControl />}, which receives the control's props, id and ref. A custom control styles itself; the class env-field-control gives it the field's outline.

PropTypeDescription
style
React.CSSProperties((state: State) => React.CSSProperties | undefined)undefined
Passed to Base UI. Style applied to the element, or a function that returns a style object based on the component's state.
defaultValue
React.ComponentProps<'input'>['defaultValue']undefined
Passed to Base UI.
render
React.ReactElementComponentRenderFn<RenderFunctionProps, State>undefined
Passed to Base UI. Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.
onValueChange
((value: string, eventDetails: FieldControl.ChangeEventDetails) => void)undefined
Passed to Base UI. Callback fired when the `value` changes. Use when controlled.
className
string
The part's class, beside its own env-field class.
size
'sm''md''lg'
The height, as on every control: sm, md or lg in the current scale. Without it, the control height of the container.

Also accepts the native props of <input>, such as ref, className and aria-* attributes.

Field.Description

Lasting guidance under the control, such as a format or a limit, linked to the control as its description.

PropTypeDescription
style
React.CSSProperties((state: State) => React.CSSProperties | undefined)undefined
Passed to Base UI. Style applied to the element, or a function that returns a style object based on the component's state.
render
React.ReactElementComponentRenderFn<RenderFunctionProps, State>undefined
Passed to Base UI. Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.
className
string
The part's class, beside its own env-field class.

Also accepts the native props of <p>, such as ref, className and aria-* attributes.

Field.Error

A message under the control that says how to correct the value, with an error icon. It shows while the field is invalid, from its own validation or from invalid on Field.Root, and is linked to the control; match="valueMissing" and the like show it for one kind of failure, and match={true} always.

PropTypeDescription
style
React.CSSProperties((state: State) => React.CSSProperties | undefined)undefined
Passed to Base UI. Style applied to the element, or a function that returns a style object based on the component's state.
render
React.ReactElementComponentRenderFn<RenderFunctionProps, State>undefined
Passed to Base UI. Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.
match
booleankeyof ValidityStateundefined
Passed to Base UI. Determines whether to show the error message according to the field's [ValidityState](https://developer.mozilla.org/en-US/docs/Web/API/ValidityState). Specifying `true` will always show the error message, and lets external libraries control the visibility.
className
string
The part's class, beside its own env-field class.
children
ReactNode
How to correct the value. Without children, the browser's validation message shows.

Also accepts the native props of <div>, such as ref, className and aria-* attributes.

Part names

Each part's class and state attributes are public and versioned, for an application's CSS to style.

env-field
The field: label, control, description and error.
env-field-control
The control.
env-field-description
The description under the control.
env-field-error
The error message.
env-field-label
The label.
data-disabled
Any value, or present on env-field, env-field-control
data-invalid
Any value, or present on env-field-control
data-size
lg · md · sm on env-field-control

Changelog

1.0.0

Field, on Base UI's Field.

1.0.0-prerelease.6

Field.Label takes the size, weight and muted color of a field's floated label, so it reads as the labels of envUI's own fields do.

Field.Control takes a text field's rounded corners rather than round ends.