# Section

A titled container that collapses on pages holding none of its keeps.

Canonical URL: https://docs.asterdoc.com/components/section/

`Section` groups related `Field`s and `Table`s under a heading. It carries no
pagination id of its own — `data-section`, not `data-keep-id` — precisely so
a section that runs well past one page is never treated as a single thing
that has to stay together; the keeps inside it are what the page plan
actually moves.

## Preview


```tsx
import { Document } from "@/components/asterdoc/document";
import { Field } from "@/components/asterdoc/field";
import { Section } from "@/components/asterdoc/section";
import { proposalForm } from "@/examples/proposal";
import { shortProposalData } from "@/examples/proposal-data";

export function SectionDemo() {
  return (
    <Document artifact={proposalForm} data={shortProposalData} id="section-demo">
      <Section id="customer" title="Prepared for" className="flex flex-col gap-1">
        <Field path="customer" label={false} className="font-medium text-neutral-900" />
        <Field path="customerContact" label={false} className="text-neutral-700" />
        <Field path="customerAddress" label={false} className="text-neutral-600" />
      </Section>
    </Document>
  );
}
```


## Installation


```bash
npx shadcn@4 add @asterdoc/section
```


```bash
asterdoc add section
```


Installs to components/asterdoc/section.tsx.


## Usage


```tsx
import { Section } from "@/components/asterdoc/section";

<Section id="customer" title="Prepared for" className="flex flex-col gap-1">
  <Field path="customer" label={false} className="font-medium text-neutral-900" />
  <Field path="customerContact" label={false} className="text-neutral-700" />
  <Field path="customerAddress" label={false} className="text-neutral-600" />
</Section>
```

| Prop | Type | Optional | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | No |  | Stable id the page plan uses to decide whether this section renders on a page. |
| `title` | `string` | Yes |  | Heading shown above the section's children; omitted renders no heading. |
| `className` | `string` | Yes |  | Classes replacing the section's default column layout. |
| `children` | `ReactNode` | No |  | The fields, tables, or other content grouped under this section. |


## Composition

A `Section` needs a [`Document`](/components/document) above it for the
same reason a `Field` does: it reads, from context only `Document`'s tree
provides, which of its own keeps landed on the current page. Give it a
stable `id` — the page plan uses it to decide whether the section shows at
all on a given page, so it should be unique within the document and stable
across renders, not derived from the data being shown.

A `Section`'s heading, when it has a `title`, is itself a
[`Keep Together`](/components/keep-together) — that is
the one piece of pagination machinery it brings along automatically. The
heading stays with the section's first keep: when that keep starts the next
page, the heading moves there with it rather than ending a page alone. The
rest of the section is ordinary children: put whatever
[`Field`](/components/field)s or [`Table`](/components/table)s belong
together inside it. `Section` renders them as given and collapses to
nothing — heading included — on any page holding none of them, without ever
treating the section itself as one unit that has to stay together.

When a tenant sets an accent color, a titled section's heading is one of the
three places it lands, alongside an emphasized Totals row and an emphasized
Table footer row. See [Document](/components/document) for how tokens reach a
document.

The heading's size follows the document's [typography](/components/typography)
token, and it is already at the smallest verified size, so `compact` leaves it
where it is.

## Variants

`Section` takes an optional `title` and a `className` that replaces its
default column layout.

### Titled

The default: a `title` renders a heading above the section's children.


```tsx
import { Document } from "@/components/asterdoc/document";
import { Field } from "@/components/asterdoc/field";
import { Section } from "@/components/asterdoc/section";
import { proposalForm } from "@/examples/proposal";
import { shortProposalData } from "@/examples/proposal-data";

export function SectionVariantTitled() {
  return (
    <Document artifact={proposalForm} data={shortProposalData} id="section-variant-titled">
      <Section id="variant-titled" title="Prepared for">
        <Field path="customer" label={false} />
      </Section>
    </Document>
  );
}
```


### Untitled

Omitting `title` renders no heading at all — just the children.


```tsx
import { Document } from "@/components/asterdoc/document";
import { Field } from "@/components/asterdoc/field";
import { Section } from "@/components/asterdoc/section";
import { proposalForm } from "@/examples/proposal";
import { shortProposalData } from "@/examples/proposal-data";

export function SectionVariantUntitled() {
  return (
    <Document artifact={proposalForm} data={shortProposalData} id="section-variant-untitled">
      <Section id="variant-untitled">
        <Field path="customer" label={false} />
      </Section>
    </Document>
  );
}
```


### Row layout

A custom `className` replaces the default column layout with a row.


```tsx
import { Document } from "@/components/asterdoc/document";
import { Field } from "@/components/asterdoc/field";
import { Section } from "@/components/asterdoc/section";
import { proposalForm } from "@/examples/proposal";
import { shortProposalData } from "@/examples/proposal-data";

export function SectionVariantRow() {
  return (
    <Document artifact={proposalForm} data={shortProposalData} id="section-variant-row">
      <Section id="variant-row" title="Provider" className="flex flex-row items-baseline gap-6">
        <Field path="provider" label={false} />
        <Field path="providerPhone" label={false} />
      </Section>
    </Document>
  );
}
```
