# Form layout

Lays out a form's fields: stacked, or with the labels in a column beside the controls. Put `Field`s in it, grouped by `FormSection` where a long form has parts. A horizontal form keeps its labels in a column only while its container is wide enough (36rem), and stacks them on a narrow one, so the same form works in a page and in a side panel.

- Registry name: `form-layout` (`@candor/form-layout`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/form-layout

## Install

```bash
npx candor-ui add form-layout
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/form-layout`.
It brings in: stack, tokens, utils.
npm packages: @base-ui/react@^1.9.0.

## Example

```tsx
"use client"

import { FormLayout, FormSection } from "@/components/candor/form-layout"
import { Field } from "@/components/candor/ui/field"
import { Input } from "@/components/candor/ui/input"
import { Textarea } from "@/components/candor/ui/textarea"

// Labels sit in a column while the container is wide enough, and stack on a narrow one.
export default function Example() {
  return (
    <FormLayout orientation="horizontal" className="w-full max-w-2xl">
      <FormSection title="Agent" description="How the agent is named in the app.">
        <Field label="Name" required>
          <Input name="name" />
        </Field>
        <Field label="Instructions" hint="What it should and shouldn't do." optional>
          <Textarea name="instructions" rows={3} />
        </Field>
      </FormSection>
      <FormSection title="Escalation">
        <Field label="Email" hint="Where it sends what it can't decide.">
          <Input name="email" type="email" />
        </Field>
      </FormSection>
    </FormLayout>
  )
}
```

## <FormLayout>

Props:

- `orientation?: "vertical" | "horizontal" | undefined` (default `"vertical"`): `vertical` (the default) puts each label above its control; `horizontal` puts labels in a column beside the controls on a wide container.
- `labelWidth?: keyof typeof labelWidths | undefined` (default `"md"`): How wide the label column is in a horizontal form: `sm` 8rem, `md` 11rem (the default), `lg` 14rem.
- `render?: useRender.RenderProp | undefined`: The element to draw instead of a `<div>`: `render={<form onSubmit={…} />}` to make it the form.
- `className?: string | undefined`: Classes for the element, applied last, so they win over the props.
- `children?: React.ReactNode | undefined`: The fields and sections.

Also takes the props of `React.ComponentProps<"div">`.

## <FormSection>

A part of a long form, as a `fieldset` named by its `legend`, so a screen reader says which part a field is in. The description is read with the part.

Props:

- `title: string`: The part's name, as its legend: "Contact details".
- `description?: string | undefined`: A sentence under the title saying what the part is for.
- `className?: string | undefined`: Classes for the fieldset, applied last.
- `children?: React.ReactNode | undefined`: The part's fields.

Also takes the props of `Omit<React.ComponentProps<"fieldset">, "title">`.

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider`: its fixed strings in `strings`, its nouns in `nouns`; entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
