# Page Break

Starts a new page at its position, occupying no height of its own. The plan opens a page there in both outputs.

Canonical URL: https://docs.asterdoc.com/components/page-break/

`PageBreak` is a `KeepTogether` that carries no content: the measuring pass
reads its `data-break-before="page"` attribute and the plan opens a fresh
page there, the same way it already opens one for a keep that overflows. The
preview and the PDF read the same plan, so both start the next page in the
same place.

## Preview


```tsx
import { Document } from "@/components/asterdoc/document";
import { Field } from "@/components/asterdoc/field";
import { KeepTogether } from "@/components/asterdoc/keep-together";
import { PageBreak } from "@/components/asterdoc/page-break";
import { Pages } from "@/components/asterdoc/pages";
import { proposalForm } from "@/examples/proposal";
import { shortProposalData } from "@/examples/proposal-data";

export function PageBreakDemo() {
  return (
    <Pages>
      <Document artifact={proposalForm} data={shortProposalData} id="page-break-demo">
        <KeepTogether keepId="page-break-demo-first" className="flex flex-col gap-1">
          <Field path="proposalNumber" />
          <Field path="issuedOn" />
        </KeepTogether>
        <PageBreak keepId="page-break-demo-break" />
        <KeepTogether keepId="page-break-demo-second" className="flex flex-col gap-1">
          <Field path="customer" />
          <Field path="customerAddress" />
        </KeepTogether>
      </Document>
    </Pages>
  );
}
```


## Installation


```bash
npx shadcn@4 add @asterdoc/page-break
```


```bash
asterdoc add page-break
```


Installs to components/asterdoc/page-break.tsx.


## Usage


```tsx
import { PageBreak } from "@/components/asterdoc/page-break";

<PageBreak keepId="page-break-demo-break" />
```

| Prop | Type | Optional | Default | Description |
| --- | --- | --- | --- | --- |
| `keepId` | `string` | No |  | Stable id the page plan tracks this break by; must be unique within the document. |
| `table` | `string` | Yes |  | The table this break sits inside, when it separates two of a hand-built
table's rows. Named the same way a row is, so the table's header still
repeats on the page the break opens. |


## Composition

`PageBreak` needs a [`Document`](/components/document) above it like any
other keep, and a [`Pages`](/components/pages) preview above that for the
break to do anything: outside a paginated preview every keep renders, so an
unpaginated `Paper` view or a bare render shows nothing different.

It takes a required `keepId`, the same stable id every `KeepTogether` needs,
and an optional `table`. Leave `table` unset for a break between two
sections or two unrelated blocks. Set it to the same id a hand-built table's
rows carry when the break sits between two of them — the plan then treats
the break as belonging to that table, so the table's header still repeats
above the row that follows the break, on the new page. [`Table`](/components/table)
generates its own rows from a bound list and cannot be interrupted this way;
a table a break needs to split is built directly with `KeepTogether`, the
way `Table` itself is, and the break sets its own `table` to match.

An orphaned table header — one the plan would otherwise carry forward alone
to keep it off the foot of a page — still carries forward first: the break
opens the page either way, so the header is never stranded.

## Variants

`PageBreak` takes `keepId` and an optional `table`.

### Before a section

Placed directly ahead of a [`Section`](/components/section), the break
starts that section on a fresh page even though it would otherwise fit
under the section before it.


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

export function PageBreakVariantBeforeASection() {
  return (
    <Pages>
      <Document artifact={proposalForm} data={shortProposalData} id="page-break-variant-before-a-section">
        <Section id="summary" title="Summary" className="flex flex-col gap-1">
          <Field path="summary" label={false} />
        </Section>
        <PageBreak keepId="page-break-variant-before-a-section-break" />
        <Section id="customer" title="Prepared for" className="flex flex-col gap-1">
          <Field path="customer" label={false} />
          <Field path="customerAddress" label={false} />
        </Section>
      </Document>
    </Pages>
  );
}
```


### Inside a table's rows

Placed between two rows of a hand-built table and given the same `table` id
the rows carry, the break still lets the table's header repeat above the
row that follows it on the new page.


```tsx
import { useList } from "@asterdoc/react";
import { Document } from "@/components/asterdoc/document";
import { KeepTogether } from "@/components/asterdoc/keep-together";
import { PageBreak } from "@/components/asterdoc/page-break";
import { Pages } from "@/components/asterdoc/pages";
import { proposalForm } from "@/examples/proposal";
import { shortProposalData } from "@/examples/proposal-data";

const TABLE_ID = "page-break-variant-inside-a-tables-rows";

function PricedRows() {
  const list = useList("lineItems");
  return (
    <>
      <KeepTogether
        keepId={`${TABLE_ID}:header`}
        data-table-header={TABLE_ID}
        className="flex gap-4 border-b border-neutral-800 pb-1 text-xs font-semibold uppercase tracking-wide text-neutral-700"
      >
        <span className="basis-3/4 text-left">Description</span>
        <span className="basis-1/4 text-right">Qty</span>
      </KeepTogether>
      {list.rows.map((_row, index) => (
        <React.Fragment key={index}>
          {index === 2 ? <PageBreak keepId={`${TABLE_ID}:break`} table={TABLE_ID} /> : null}
          <KeepTogether
            keepId={`${TABLE_ID}:${index}`}
            data-table-row={TABLE_ID}
            className="flex gap-4 border-b border-neutral-200 py-1.5"
          >
            <span className="basis-3/4 text-left">{list.text(index, "description")}</span>
            <span className="basis-1/4 text-right">{list.text(index, "quantity")}</span>
          </KeepTogether>
        </React.Fragment>
      ))}
    </>
  );
}

export function PageBreakVariantInsideATablesRows() {
  return (
    <Pages>
      <Document artifact={proposalForm} data={shortProposalData} id="page-break-variant-inside-a-tables-rows">
        <PricedRows />
      </Document>
    </Pages>
  );
}
```
