# Field

The shared labeling and validation shell for composing a custom form control with a label, description, and error text.

## Installation

```tsx
import { Field, FieldDescription, FieldLabel } from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";
```
## Usage

```tsx
import { Field, FieldDescription, FieldLabel } from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

export default function BasicDemo() {
  return (
    <Field name="displayName">
      <FieldLabel size="lg" inset={false} required>
        Display name
      </FieldLabel>
      <Input size="lg" placeholder="Ada Lovelace" required />
      <FieldDescription size="lg">Shown anywhere your profile is visible.</FieldDescription>
    </Field>
  );
}
```
## Examples

### Sizes

Pass the same `size` to every part of a field so the label, control, and description scale together.

```tsx
import {
  Field,
  FieldDescription,
  FieldLabel,
  type FieldSize,
} from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

const SIZES: FieldSize[] = ["lg", "xl", "2xl"];

export default function SizesDemo() {
  return (
    <div className="flex flex-wrap items-start gap-8">
      {SIZES.map((size) => (
        <Field key={size} name={`displayName-${size}`}>
          <FieldLabel size={size} inset={false} required>
            Display name ({size})
          </FieldLabel>
          <Input size={size} placeholder="Ada Lovelace" required />
          <FieldDescription size={size}>Shown anywhere your profile is visible.</FieldDescription>
        </Field>
      ))}
    </div>
  );
}
```

### Invalid

```tsx
import { Field, FieldError, FieldLabel } from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

export default function InvalidDemo() {
  return (
    <Field name="workspaceSlug" invalid>
      <FieldLabel size="lg" inset={false}>
        Workspace slug
      </FieldLabel>
      <Input size="lg" defaultValue="Already taken" />
      <FieldError size="lg" match={true}>
        Choose a different workspace slug.
      </FieldError>
    </Field>
  );
}
```

### Required validation

Native constraint validity drives `FieldError` through `match`; with `validationMode="onBlur"` the message appears when the user leaves the field empty and clears once a value is committed.

```tsx
import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
} from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

export default function RequiredValidationDemo() {
  return (
    <Field name="fullName" validationMode="onBlur">
      <FieldLabel size="lg" inset={false} required>
        Full name
      </FieldLabel>
      <Input size="lg" placeholder="Ada Lovelace" required />
      <FieldError size="lg" match="valueMissing">
        Enter your full name.
      </FieldError>
      <FieldDescription size="lg">Visible on your profile.</FieldDescription>
    </Field>
  );
}
```

### Horizontal label

`FieldLabelGroup` bundles the label and description into one block; with `orientation="horizontal"` it sits beside the control in a flex row. Supporting text is one tier below the label at every size, whether it sits under the label or under the control.

```tsx
import { Field, FieldLabelGroup } from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

export default function HorizontalDemo() {
  return (
    <Field name="workspaceName">
      <div className="flex items-start gap-4">
        <FieldLabelGroup
          size="lg"
          orientation="horizontal"
          required
          label="Workspace name"
          description="Shown across your projects."
        />
        <Input size="lg" placeholder="Acme Inc." />
      </div>
    </Field>
  );
}
```

### Helper text

`FieldHelperText` renders the `hint` below the control and swaps it for the `error` when one is set, keeping the error-XOR-hint rule in one part.

```tsx
import { Field, FieldHelperText, FieldLabel } from "@makeplane/propel/components/field";
import { Input } from "@makeplane/propel/components/input";

export default function HelperTextDemo() {
  return (
    <div className="flex flex-wrap items-start gap-8">
      <Field name="slug">
        <FieldLabel size="lg" inset={false}>
          Slug
        </FieldLabel>
        <Input size="lg" placeholder="acme-inc" />
        <FieldHelperText size="lg" hint="Lowercase letters, numbers, and dashes." />
      </Field>
      <Field name="slugTaken">
        <FieldLabel size="lg" inset={false}>
          Slug
        </FieldLabel>
        <Input size="lg" defaultValue="acme inc" />
        <FieldHelperText
          size="lg"
          hint="Lowercase letters, numbers, and dashes."
          error="Only lowercase letters, numbers, and dashes are allowed."
        />
      </Field>
    </div>
  );
}
```
## API Reference

### Field

The shared field chrome for custom controls: Base UI's labeling/validation `Field.Root` behavior
grafted onto the styled `Field` element (rule 1a). Compose it with `FieldLabel`, a control,
`FieldDescription`, and `FieldError`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, FieldRootState>` | — | 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. |
| `size` | `"md" \| "lg" \| "xl" \| "2xl"` | — |  |

### FieldLabel

The ready-made field label: Base UI's `Field.Label` (auto-associated with the control) grafted
onto the styled `FieldLabel` element (rule 1a), plus a `FieldLabelRequiredMarker` when
`required`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` (required) | `"md" \| "lg" \| "xl" \| "2xl"` | — |  |
| `inset` (required) | `NonNullable<boolean \| null \| undefined>` | — |  |
| `render` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, FieldLabelState>` | — | 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. |
| `required` | `boolean` | — |  |

### FieldLabelGroup

The ready-made label/description block of a field: lays out an optional `FieldLabel` and
`FieldDescription` inside the `FieldLabelGroup` container. Renders nothing when both are absent.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `orientation` (required) | `"vertical" \| "horizontal"` | — |  |
| `size` (required) | `"md" \| "lg" \| "xl" \| "2xl"` | — |  |
| `required` | `boolean` | — |  |
| `label` | `string` | — |  |
| `description` | `ReactNode` | — |  |

### FieldItemContent

The label + description column for a single choice option (checkbox/radio/switch row).

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` (required) | `"md" \| "lg" \| "xl" \| "2xl"` | — |  |
| `description` | `ReactNode` | — |  |

### FieldDescription

Supporting / helper text for a field: Base UI's `Field.Description` (auto-associated as the
control's accessible description) grafted onto the styled `FieldDescription` element (rule 1a).

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` (required) | `"md" \| "lg" \| "xl" \| "2xl"` | — |  |
| `render` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, FieldDescriptionState>` | — | 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. |

### FieldError

Error text for a field: Base UI's `Field.Error` (shown per the control's validity / `match`)
grafted onto the styled `FieldError` element (rule 1a).

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` (required) | `"md" \| "lg" \| "xl" \| "2xl"` | — |  |
| `render` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, FieldErrorState>` | — | 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. |

### FieldHelperText

The error-or-hint line beneath a field: shows the `FieldError` when there is an error, otherwise
the `FieldDescription` hint. With no explicit `error`, the `FieldError` renders unmatched so Base
UI's own error channel stays open — validity messages and external `Form` `errors` for this field
display (and clear) automatically. A components-tier composition of the two elements parts;
shared by the ready-made field types so the error-XOR-hint rule lives in one place.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` (required) | `"md" \| "lg" \| "xl" \| "2xl"` | — |  |
| `hint` | `ReactNode` | — |  |
| `error` | `ReactNode` | — |  |
