# Field primitive (/components/primitives/field)



Use the field primitives to build a custom field with Luke UI labels, descriptions, and validation
messages. Start with [`TextField`](/components/forms/text-field) or
[`ComboboxField`](/components/forms/combobox-field) when one of those components fits.

apps/docs/src/examples/field-primitive/basic.tsx

```tsx
import { Field, FieldDescription, FieldLabel } from '@luke-ui/react/primitives/field';
import { InputGroup, InputGroupInput } from '@luke-ui/react/primitives/input-group';

export default () => {
	return (
		<Field>
			<FieldLabel htmlFor="work-email">Email</FieldLabel>
			<InputGroup>
				<InputGroupInput
					aria-describedby="work-email-description"
					id="work-email"
					name="email"
					type="email"
				/>
			</InputGroup>
			<FieldDescription id="work-email-description">Use your work email.</FieldDescription>
		</Field>
	);
};
```

## Best practices [#best-practices]

| Guidance | Practices                                                                                                            |
| -------- | -------------------------------------------------------------------------------------------------------------------- |
| Do       | Use [`TextField`](/components/forms/text-field) or another supported field when it fits.                             |
| Do       | Use field primitives when a custom control needs a different documented arrangement.                                 |
| Don't    | Assume adjacent parts create semantics. Connect the label, description, and control through their public HTML props. |

## Anatomy [#anatomy]

`Field` arranges a label, control, description, and validation message. Field components such as
`TextField` connect these parts for their supported controls.

For a custom structure, use `FieldLabel`, `FieldDescription`, and `FieldError` with the field
control. Connect each part through its public HTML props, as the primary example shows.

## Required fields [#required-fields]

`necessityIndicator` changes the visible marker on `FieldLabel`. It does not make the control
required, so set the required state on the control separately.

## Validation messages [#validation-messages]

Use `errorMessage` for validation feedback. `FieldError` is styled for the field error slot and
works with the validation state from the surrounding React Aria form control.

## API [#api]

### FieldProps [#fieldprops]

<ComponentPropsTable
  id="type-table-field.tsx-FieldProps"
  type="{
  &#x22;id&#x22;: &#x22;field.tsx-FieldProps&#x22;,
  &#x22;name&#x22;: &#x22;FieldProps&#x22;,
  &#x22;description&#x22;: &#x22;Props for the field primitive.&#x22;,
  &#x22;entries&#x22;: [
    {
      &#x22;name&#x22;: &#x22;children&#x22;,
      &#x22;description&#x22;: &#x22;&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;ReactNode&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;ReactNode&#x22;,
      &#x22;required&#x22;: true,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;description&#x22;,
      &#x22;description&#x22;: &#x22;Optional helper text shown below the control.&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;ReactNode&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;ReactNode&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;errorMessage&#x22;,
      &#x22;description&#x22;: &#x22;Error content passed to `FieldError`. Accepts React Aria's render-prop form.&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;ChildrenOrFunction<FieldErrorRenderProps>&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;ChildrenOrFunction<object>&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;label&#x22;,
      &#x22;description&#x22;: &#x22;Label content shown above the control.&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;ReactNode&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;ReactNode&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;necessityIndicator&#x22;,
      &#x22;description&#x22;: &#x22;Label necessity style.&#x22;,
      &#x22;tags&#x22;: [
        {
          &#x22;name&#x22;: &#x22;default&#x22;,
          &#x22;text&#x22;: &#x22;'icon'&#x22;
        }
      ],
      &#x22;type&#x22;: &#x22;\&#x22;label\&#x22; | \&#x22;icon\&#x22; | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;union&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;deprecated&#x22;: false,
      &#x22;description&#x22;: &#x22;`FieldProps` also accepts compatible DOM and ARIA attributes and event handlers for its rendered element.&#x22;,
      &#x22;name&#x22;: &#x22;__nativePropsForwarding&#x22;,
      &#x22;required&#x22;: true,
      &#x22;simplifiedType&#x22;: &#x22;&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;&#x22;
    }
  ]
}"
/>

### FieldLabelProps [#fieldlabelprops]

<ComponentPropsTable
  id="type-table-label.tsx-FieldLabelProps"
  type="{
  &#x22;id&#x22;: &#x22;label.tsx-FieldLabelProps&#x22;,
  &#x22;name&#x22;: &#x22;FieldLabelProps&#x22;,
  &#x22;description&#x22;: &#x22;Props for `FieldLabel`.&#x22;,
  &#x22;entries&#x22;: [
    {
      &#x22;name&#x22;: &#x22;htmlFor&#x22;,
      &#x22;description&#x22;: &#x22;Associates the label with a form control.&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;string | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;string&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;elementType&#x22;,
      &#x22;description&#x22;: &#x22;&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;string | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;string&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;render&#x22;,
      &#x22;description&#x22;: &#x22;Overrides the default DOM element with a custom render function.\nThis allows rendering existing components with built-in styles and behaviors\nsuch as router links, animation libraries, and pre-styled components.\n\nRequirements:\n\n- You must render the expected element type (e.g. if `<button>` is expected, you cannot render an\n  `<a>`).\n- Only a single root DOM element can be rendered (no fragments).\n- You must pass through props and ref to the underlying DOM element, merging with your own prop\n  as appropriate.&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;DOMRenderFunction<\&#x22;label\&#x22;, undefined> | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;DOMRenderFunction<\&#x22;label\&#x22;, undefined>&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;necessityIndicator&#x22;,
      &#x22;description&#x22;: &#x22;Shows how required fields are marked.&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;\&#x22;label\&#x22; | \&#x22;icon\&#x22; | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;union&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;deprecated&#x22;: false,
      &#x22;description&#x22;: &#x22;`FieldLabelProps` also accepts compatible DOM and ARIA attributes and event handlers for its rendered element.&#x22;,
      &#x22;name&#x22;: &#x22;__nativePropsForwarding&#x22;,
      &#x22;required&#x22;: true,
      &#x22;simplifiedType&#x22;: &#x22;&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;&#x22;
    }
  ]
}"
/>

### FieldDescriptionProps [#fielddescriptionprops]

<ComponentPropsTable
  id="type-table-description.tsx-FieldDescriptionProps"
  type="{
  &#x22;id&#x22;: &#x22;description.tsx-FieldDescriptionProps&#x22;,
  &#x22;name&#x22;: &#x22;FieldDescriptionProps&#x22;,
  &#x22;description&#x22;: &#x22;Props for `FieldDescription`.&#x22;,
  &#x22;entries&#x22;: [
    {
      &#x22;name&#x22;: &#x22;id&#x22;,
      &#x22;description&#x22;: &#x22;Element id referenced by `aria-describedby` on the control.&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;string | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;string&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;elementType&#x22;,
      &#x22;description&#x22;: &#x22;&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;string | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;string&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;render&#x22;,
      &#x22;description&#x22;: &#x22;Overrides the default DOM element with a custom render function.\nThis allows rendering existing components with built-in styles and behaviors\nsuch as router links, animation libraries, and pre-styled components.\n\nRequirements:\n\n- You must render the expected element type (e.g. if `<button>` is expected, you cannot render an\n  `<a>`).\n- Only a single root DOM element can be rendered (no fragments).\n- You must pass through props and ref to the underlying DOM element, merging with your own prop\n  as appropriate.&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;DOMRenderFunction<any, any> | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;DOMRenderFunction<any, any>&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;deprecated&#x22;: false,
      &#x22;description&#x22;: &#x22;`FieldDescriptionProps` also accepts compatible DOM and ARIA attributes and event handlers for its rendered element.&#x22;,
      &#x22;name&#x22;: &#x22;__nativePropsForwarding&#x22;,
      &#x22;required&#x22;: true,
      &#x22;simplifiedType&#x22;: &#x22;&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;&#x22;
    }
  ]
}"
/>

### FieldErrorProps [#fielderrorprops]

<ComponentPropsTable
  id="type-table-error.tsx-FieldErrorProps"
  type="{
  &#x22;id&#x22;: &#x22;error.tsx-FieldErrorProps&#x22;,
  &#x22;name&#x22;: &#x22;FieldErrorProps&#x22;,
  &#x22;description&#x22;: &#x22;Props for `FieldError`.&#x22;,
  &#x22;entries&#x22;: [
    {
      &#x22;name&#x22;: &#x22;elementType&#x22;,
      &#x22;description&#x22;: &#x22;The HTML element type to render. Defaults to `'span'`.\nSet to `'div'` when using block-level children (e.g. `<ul>`) to avoid invalid HTML.&#x22;,
      &#x22;tags&#x22;: [
        {
          &#x22;name&#x22;: &#x22;default&#x22;,
          &#x22;text&#x22;: &#x22;'span'&#x22;
        }
      ],
      &#x22;type&#x22;: &#x22;string | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;string&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;children&#x22;,
      &#x22;description&#x22;: &#x22;The children of the component. A function may be provided to alter the children based on\ncomponent state.&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;ChildrenOrFunction<FieldErrorRenderProps>&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;ChildrenOrFunction<object>&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;render&#x22;,
      &#x22;description&#x22;: &#x22;Overrides the default DOM element with a custom render function.\nThis allows rendering existing components with built-in styles and behaviors\nsuch as router links, animation libraries, and pre-styled components.\n\nRequirements:\n\n- You must render the expected element type (e.g. if `<button>` is expected, you cannot render an\n  `<a>`).\n- Only a single root DOM element can be rendered (no fragments).\n- You must pass through props and ref to the underlying DOM element, merging with your own prop\n  as appropriate.&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;DOMRenderFunction<\&#x22;div\&#x22;, FieldErrorRenderProps> | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;DOMRenderFunction<\&#x22;div\&#x22;, object>&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;id&#x22;,
      &#x22;description&#x22;: &#x22;The element's unique identifier. See\n[MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id).&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;string | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;string&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;deprecated&#x22;: false,
      &#x22;description&#x22;: &#x22;`FieldErrorProps` also accepts compatible DOM and ARIA attributes and event handlers for its rendered element.&#x22;,
      &#x22;name&#x22;: &#x22;__nativePropsForwarding&#x22;,
      &#x22;required&#x22;: true,
      &#x22;simplifiedType&#x22;: &#x22;&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;&#x22;
    }
  ]
}"
/>
