# Field

A compound component that provides consistent wrapper structure for form fields
with label, helper text, and error messaging. Handles all a11y wiring automatically.

## Usage

```tsx
<Field error={hasError} required>
  <Field.Label>Email</Field.Label>
  <Field.Control>
    <input type="email" />
  </Field.Control>
  <Field.HelperText>We'll never share your email.</Field.HelperText>
  <Field.Error>Please enter a valid email address.</Field.Error>
</Field>
```

## Accessibility

Field automatically wires up:

- `htmlFor` on the label pointing to the control
- `aria-labelledby` on the control when `Field.Label` is present (essential for non-labelable elements like `<button>`, `role="switch"`)
- `aria-describedby` on the control referencing helper text and error
- `aria-invalid` on the control when in error state
- `aria-required` on the control when required
- Screen reader text for required indicator

**Self-labelling controls** (e.g. Checkbox with `label` prop): omit `Field.Label` — the control provides its own accessible name and `Field.Control` will not inject a phantom `aria-labelledby`.

```tsx
import { Field } from '@tangible/ui';
```

## Field props

| Prop | Type | Default | Description |
| - | - | - | - |
| `children?` | `React.ReactNode` | | |
| `className?` | `string` | | Additional class name for the field wrapper |
| `disabled?` | `boolean` | `false` | Whether the field is disabled |
| `error?` | `boolean` | `false` | Whether the field has an error state |
| `inline?` | `boolean` | `false` | Inline layout: label and control on same row |
| `labels?` | `FieldLabels` | | Overridable strings for i18n. |
| `required?` | `boolean` | `false` | Whether the field is required |

### Field.Label

| Prop | Type | Default | Description |
| - | - | - | - |
| `as?` | `"label" \| "span"` | `'label'` | Element to render. Use 'span' for group controls (RadioGroup, SegmentedControl — anything rendering role="radiogroup"/"group" on a <div>) where <label for> would reference a non-labelable element. The aria-labelledby wiring via Field.Control is unaffected. |
| `children?` | `React.ReactNode` | | |
| `className?` | `string` | | |
| `hidden?` | `boolean` | `false` | Visually hide the label while keeping it accessible |
| `htmlFor?` | `string` | | Only in some variants; the others reject it. |

Also accepts the standard attributes of `LabelHTMLAttributes` (`data-*`, `aria-*`, event handlers), passed to the element it renders.

### Field.Control

| Prop | Type | Default | Description |
| - | - | - | - |
| `children` | `React.ReactElement` | | |

### Field.HelperText

| Prop | Type | Default | Description |
| - | - | - | - |
| `children?` | `React.ReactNode` | | |
| `className?` | `string` | | |

Also accepts the standard attributes of `HTMLAttributes` (`data-*`, `aria-*`, event handlers), passed to the element it renders.

### Field.Error

| Prop | Type | Default | Description |
| - | - | - | - |
| `children?` | `React.ReactNode` | | |
| `className?` | `string` | | |

Also accepts the standard attributes of `HTMLAttributes` (`data-*`, `aria-*`, event handlers), passed to the element it renders.

## Examples

- [Hidden Label](https://storybook-tangible-ui.pages.dev/?path=/story/forms-field--hidden-label): Use `hidden` on Field.Label to visually hide the label while keeping it accessible to screen readers.

- [Interactive Validation](https://storybook-tangible-ui.pages.dev/?path=/story/forms-field--interactive-validation): Field handles the error state display - validation logic stays in the consuming component.

- [Inline](https://storybook-tangible-ui.pages.dev/?path=/story/forms-field--inline): Use `inline` prop to place label and control on the same row.

- [Helper Text Above](https://storybook-tangible-ui.pages.dev/?path=/story/forms-field--helper-text-above): Slot order determines layout. Place HelperText before Control to show it above the input.

Other stories: Default, Required, With Error, Disabled, With Textarea, Layout Comparison, Multiple Fields.

## Component API tokens

Read via fallback, never declared. Set one on an ancestor to restyle every instance under it.

- `--tui-field-gap`
- `--tui-field-label-fg`
- `--tui-field-helper-fg`
- `--tui-field-error-fg`
