# Form primitives

The shadcn `Field` family maps to this entrypoint. Use it to compose labels,
descriptions, grouped sections, separators, validation messages, and responsive
field rows around the existing `input`, `textarea`, `select`, `checkbox`,
`radio`, `switch`, and `button` primitives.

## Import

```ts
import {
  FormContentComponent,
  FormControlDirective,
  FormDescriptionComponent,
  FormFieldComponent,
  FormFieldsetComponent,
  FormGroupComponent,
  FormLabelComponent,
  FormLegendComponent,
  FormMessageComponent,
  FormSeparatorComponent,
  FormTitleComponent,
} from '@edsis/component/form';
```

## Composition

Use the primitives in these roles:

| Upstream concept   | Local Angular surface                                                                           |
| ------------------ | ----------------------------------------------------------------------------------------------- |
| `Field`            | `FormField`                                                                                     |
| `FieldSet`         | `fieldset[FormFieldset]`                                                                        |
| `FieldLegend`      | `legend[FormLegend]`                                                                            |
| `FieldGroup`       | `FormGroup`                                                                                     |
| `FieldContent`     | `FormContent`                                                                                   |
| `FieldLabel`       | `label[FormLabel]` for native controls, `label[Label]` wrappers for checkbox/radio/switch cards |
| `FieldTitle`       | `FormTitle`                                                                                     |
| `FieldDescription` | `p[FormDescription]`                                                                            |
| `FieldSeparator`   | `FormSeparator`                                                                                 |
| `FieldError`       | `p[FormMessage]`                                                                                |

## Basic Usage

For native inputs and textareas, pair `label[FormLabel]` with
`[FormControl]` so ids and helper text stay synchronized.

```html
<FormField>
  <label FormLabel>Email</label>
  <input Input FormControl type="email" placeholder="you@example.com" />
  <p FormDescription>We'll only use this address for account updates.</p>
  <p FormMessage>Enter a valid email address.</p>
</FormField>
```

## Common Patterns

### Grouped sections

Use semantic fieldsets and legends when several controls belong to the same
question or form section.

```html
<fieldset FormFieldset>
  <legend FormLegend>Address information</legend>
  <p FormDescription>We need your address to deliver your order.</p>

  <FormGroup>
    <FormField>
      <label FormLabel>Street address</label>
      <input Input FormControl placeholder="123 Main St" />
    </FormField>

    <div class="grid gap-4 sm:grid-cols-2">
      <FormField>
        <label FormLabel>City</label>
        <input Input FormControl placeholder="New York" />
      </FormField>

      <FormField>
        <label FormLabel>Postal code</label>
        <input Input FormControl placeholder="10001" />
      </FormField>
    </div>
  </FormGroup>
</fieldset>
```

### Horizontal checkbox, radio, and switch rows

For grouped controls, wrap the row in `label[Label]` so the entire card can
toggle the control, then use `FormContent` for the title and helper copy.

```html
<label Label class="block rounded-xl border border-border p-4">
  <FormField orientation="horizontal" class="gap-4">
    <Checkbox [(ngModel)]="syncDesktop" aria-label="Sync Desktop and Documents folders" />
    <FormContent>
      <FormTitle>Sync Desktop & Documents folders</FormTitle>
      <p FormDescription>Your Desktop & Documents folders are being synced with iCloud Drive.</p>
    </FormContent>
  </FormField>
</label>
```

### Select rows

Select keeps its own trigger and listbox behavior. Use `FormTitle` and
`p[FormDescription]` around it instead of relying on a generated `for`
relationship.

```html
<FormField>
  <FormTitle>Department</FormTitle>
  <SelectField aria-label="Department" class="block w-full" placeholder="Choose department">
    <SelectItem value="engineering">Engineering</SelectItem>
    <SelectItem value="design">Design</SelectItem>
    <SelectItem value="marketing">Marketing</SelectItem>
  </SelectField>
  <p FormDescription>Select your department or area of work.</p>
</FormField>
```

### Responsive layout

Set `orientation="responsive"` on `FormField` when the label and content
should stack on narrow widths and move into columns on wider screens.

```html
<FormField orientation="responsive">
  <FormContent>
    <label FormLabel>Display name</label>
    <p FormDescription>Provide the public name shown in comments and invoices.</p>
  </FormContent>
  <input Input FormControl placeholder="Evil Rabbit" />
</FormField>
```

### Validation and errors

`[FormControl]` will reflect Angular form state automatically. For external
validation flows or static examples, use the `invalid` input on
`FormField`.

```html
<FormField invalid>
  <label FormLabel>Email</label>
  <input Input FormControl type="email" aria-invalid="true" placeholder="name@example.com" />
  <p FormMessage>Enter a valid email address.</p>
</FormField>
```

## API Reference

| Primitive                  | Selector                              | Inputs                            | Notes                                                                                  |
| -------------------------- | ------------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------- |
| `FormFieldComponent`       | `FormField`                           | `class`, `orientation`, `invalid` | Core field wrapper. `orientation` supports `vertical`, `horizontal`, and `responsive`. |
| `FormFieldsetComponent`    | `fieldset[FormFieldset]`              | `class`                           | Semantic fieldset reset with spacing presets.                                          |
| `FormLegendComponent`      | `legend[FormLegend]`                  | `class`, `variant`                | Uses either standard legend sizing or label-sized copy.                                |
| `FormGroupComponent`       | `FormGroup`                           | `class`                           | Stacks related fields and separators.                                                  |
| `FormContentComponent`     | `FormContent`                         | `class`                           | Secondary text column for horizontal fields and card layouts.                          |
| `FormLabelComponent`       | `FormLabel, label[FormLabel]`         | `class`                           | Visible label tied to the generated control id inside a field.                         |
| `FormTitleComponent`       | `FormTitle`                           | `class`                           | Non-label heading for grouped controls.                                                |
| `FormDescriptionComponent` | `FormDescription, p[FormDescription]` | `class`                           | Helper text inside a field or at the fieldset level.                                   |
| `FormSeparatorComponent`   | `FormSeparator`                       | `class`                           | Divider between stacked sections.                                                      |
| `FormMessageComponent`     | `FormMessage, p[FormMessage]`         | `class`                           | Error text shown when the field is invalid.                                            |
| `FormControlDirective`     | `[FormControl]`                       | none                              | Auto-wires `id`, `aria-describedby`, and invalid state for native controls.            |

## Styling and Theming

- Field primitives use the same design tokens as the rest of the library:
  `border-border`, `text-foreground`, `text-muted-foreground`, `ring-ring`,
  and `text-destructive`.
- Pass `class` to widen or tighten the layout around a specific field.
- `FormSeparator` uses the border token rather than current text color so
  dividers remain consistent across themes.

## Accessibility

- Prefer real `fieldset` and `legend` elements for grouped questions.
- Keep native controls on `[FormControl]` when they need synchronized labels,
  descriptions, and message ids.
- Use `label[Label]` wrappers when the entire checkbox, radio, or switch row
  should toggle the control.
- `p[FormMessage]` emits `role="alert"` and `aria-live="polite"`.

## Keyboard Interactions

- Input and textarea fields preserve browser-native editing behavior.
- Select, checkbox, radio, and switch rows keep the interaction model of their
  own entrypoints.
- Field wrappers add structure and semantics but do not create extra tab stops.

## Angular Notes

- `FormLabel` is best for native controls that participate in
  `[FormControl]`.
- Use `FormTitle` when the primary text is descriptive rather than a direct
  form label.
- The local `responsive` orientation uses breakpoint-based layout instead of the
  upstream container-query API.

## Source Parity

This package is the durable Angular-first mapping for the shadcn `Field`
documentation. It mirrors the same information architecture while staying
honest about local differences: there is no dedicated `field` entrypoint, and
grouped controls continue to use the runtime behavior of the existing input,
textarea, select, checkbox, radio, switch, and button packages.
