# Form

## Overview

`Form` is the integration layer between `react-hook-form` and Xertica UI components. It provides a context-aware set of wrappers (`FormField`, `FormItem`, `FormLabel`, `FormControl`, `FormMessage`, `FormDescription`) that automatically connect to form state, display validation errors, and manage ARIA attributes.

---

## When to Use

- Any data-entry form that requires validation.
- Always used with `react-hook-form` + `zod`.

## When NOT to Use

- Simple one-field forms without validation — use a plain `<Input>` with `onChange` state.
- Server-side rendered read-only data — display with `<Card>` and typography.

---

## Required Dependencies

```bash
npm install react-hook-form zod @hookform/resolvers
```

---

## Anatomy

```tsx
<Form {...form}>
  {' '}
  ← Spreads RHF context
  <form onSubmit={form.handleSubmit(onSubmit)}>
    <FormField
      control={form.control}
      name="fieldName"
      render={({ field }) => (
        <FormItem>
          <FormLabel>Label</FormLabel>
          <FormControl>
            <Input {...field} /> ← Spread field props here
          </FormControl>
          <FormDescription>Helper text</FormDescription>
          <FormMessage /> ← Auto error from zod
        </FormItem>
      )}
    />
    <Button type="submit">Submit</Button>
  </form>
</Form>
```

---

## Sub-Components

| Component         | Description                                                              |
| ----------------- | ------------------------------------------------------------------------ |
| `Form`            | Wraps the form with react-hook-form context. Spread `{...form}` on it.   |
| `FormField`       | Connects a single field to form state via `control` and `name`.          |
| `FormItem`        | Layout wrapper for label + control + message.                            |
| `FormLabel`       | Accessible label, automatically linked to the control's `id`.            |
| `FormControl`     | Wrapper that applies `aria-invalid` and `aria-describedby` to the child. |
| `FormDescription` | Helper text shown below the control.                                     |
| `FormMessage`     | Renders the zod validation error for this field. Auto-hides when valid.  |

---

## Props

### FormField

| Prop      | Type                       | Required | Description                           |
| --------- | -------------------------- | -------- | ------------------------------------- |
| `control` | `Control`                  | **Yes**  | `form.control` from `useForm()`       |
| `name`    | `string`                   | **Yes**  | Field name, must match schema key     |
| `render`  | `({ field }) => ReactNode` | **Yes**  | Render function receiving field props |

---

## Examples

### Complete Validated Form

```tsx
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import * as z from 'zod';
import {
  Form,
  FormField,
  FormItem,
  FormLabel,
  FormControl,
  FormMessage,
  Input,
  Button,
  Card,
  CardContent,
  CardFooter,
  CardHeader,
  CardTitle,
} from 'xertica-ui/ui';

const schema = z.object({
  name: z.string().min(2, 'Name must be at least 2 characters'),
  email: z.string().email('Invalid email'),
});

export function MyForm() {
  const form = useForm({ resolver: zodResolver(schema), defaultValues: { name: '', email: '' } });

  return (
    <Card>
      <CardHeader>
        <CardTitle>Create User</CardTitle>
      </CardHeader>
      <Form {...form}>
        <form onSubmit={form.handleSubmit(data => console.log(data))}>
          <CardContent className="grid gap-4">
            <FormField
              control={form.control}
              name="name"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Full Name</FormLabel>
                  <FormControl>
                    <Input placeholder="John Doe" {...field} />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="email"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Email</FormLabel>
                  <FormControl>
                    <Input type="email" placeholder="john@example.com" {...field} />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
          </CardContent>
          <CardFooter className="justify-end">
            <Button type="submit">Create</Button>
          </CardFooter>
        </form>
      </Form>
    </Card>
  );
}
```

---

## AI Rules

- **Never implement manual validation state** (`useState` + if blocks). Use `zod` + `react-hook-form`.
- **Never render error `<span>` or `<p>` manually** — `<FormMessage />` handles this automatically.
- The `{...field}` spread goes on the **inner input component** (`<Input>`, `<Textarea>`, etc.), not on `<FormControl>`.
- For `<Select>` fields, use `onValueChange={field.onChange}` and `defaultValue={field.value}` — do not spread `{...field}` on `<Select>`.
- For `<Checkbox>` fields, use `checked={field.value}` and `onCheckedChange={field.onChange}`.
- `<FormControl>` must be the **direct parent** of the input component — wrapping it further breaks the ARIA linking.

---

## Related Components

- [`Input`](./input.md), [`Textarea`](./textarea.md), [`Select`](./select.md), [`Checkbox`](./checkbox.md), [`Switch`](./switch.md)
- [`Dialog`](./dialog.md) — Common container for forms
- [Form Pattern](../patterns/form.md) — Complete real-world usage example
