# Field

- Page: <https://kznlabs.github.io/labsUI/components/field>

## Field (`field`, component)

Label, control, description and error as one unit. Controls inside (Input, Textarea, Select, Checkbox, Switch, RadioGroup) get id, aria-describedby, aria-invalid and required automatically; errors spring in and are announced.

- Install: `npx @kznlabs/labsui add field`
- Docs: <https://kznlabs.github.io/labsUI/components/field>
- Brings: label, utils
- npm: clsx@^2.1.1, motion@14.7.1, tailwind-merge@^3.7.0

### API

- `useFieldControl(props: Props) => Props`: For controls: fills id, aria-describedby, aria-invalid, required and disabled from the
enclosing <Field>. Explicit props win. Outside a Field it returns the props unchanged.
- `<Field>`: Label, control, description and error as one unit, with ids and ARIA wired automatically.
  - `children: ReactNode`: One form control; it picks up id, aria and state from the Field.
  - `description?: ReactNode`: Hint under the control.
  - `disabled?: boolean` = `false`: Dims the label and disables the control.
  - `error?: ReactNode`: Shown under the control and marks it aria-invalid. Springs in and out.
  - `id?: string`: Use when the control renders its own id (it must match).
  - `label?: ReactNode`: Label wired to the control's id.
  - `orientation?: "vertical" | "horizontal"` = `"vertical"`: "horizontal": control first, label beside it (Checkbox, Switch).
  - `required?: boolean` = `false`: Marks the label and makes the control required.

### Usage

```tsx
<Field label="Email" description="We never share it." error={errors.email} required><Input name="email" type="email" /></Field>
```

### Example: signup-form.tsx

```tsx
"use client";

import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Field } from "@/components/ui/field";
import { Input } from "@/components/ui/input";

export function SignupForm() {
  const [error, setError] = useState<string>();
  return (
    <form
      noValidate
      onSubmit={(e) => {
        e.preventDefault();
        const email = String(new FormData(e.currentTarget).get("email"));
        setError(email.includes("@") ? undefined : "Enter a valid email address.");
      }}
    >
      <Field label="Email" description="We never share it." error={error} required>
        <Input name="email" type="email" />
      </Field>
      <Button type="submit">Create account</Button>
    </form>
  );
}
```
