# Page Number

The page being drawn and how many there are, for a document's page furniture.

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

`PageNumber` is the one component whose text comes from neither the artifact
nor the caller: the two numbers come from whatever is drawing the page. In the
preview that is the page plan, so each sheet prints its own number. On the PDF
path the engine repeats the footer on every page and fills the same two
numbers itself.

## Preview


```tsx
import { Document } from "@/components/asterdoc/document";
import { PageNumber } from "@/components/asterdoc/page-number";
import { Pages } from "@/components/asterdoc/pages";
import { Section } from "@/components/asterdoc/section";
import { Table } from "@/components/asterdoc/table";
import { proposalForm } from "@/examples/proposal";
import { overflowProposalData } from "@/examples/proposal-data";

export function PageNumberDemo() {
  return (
    <Pages furniture={{ footer: <PageNumber /> }}>
      <Document artifact={proposalForm} data={overflowProposalData} id="page-number-demo">
        <Section id="line-items" title="Scope and pricing" className="flex flex-col gap-3">
          <Table
            path="lineItems"
            id="line-items"
            columns={[
              { field: "description", width: "basis-1/2" },
              { field: "quantity", header: "Qty", width: "basis-1/12", align: "right" },
              { field: "unitPrice", header: "Unit price", width: "basis-1/6", align: "right" },
              { field: "amount", width: "basis-1/6", align: "right" },
            ]}
          />
        </Section>
      </Document>
    </Pages>
  );
}
```


## Installation


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


```bash
asterdoc add page-number
```


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


## Usage


```tsx
import { PageNumber } from "@/components/asterdoc/page-number";

<PageNumber />
```

| Prop | Type | Optional | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `string` | Yes | "Page" | Words before the page number. Empty prints the number alone. |
| `separator` | `string` | Yes | "of" | Words between the page number and the page count. |
| `total` | `boolean` | Yes | true | Prints the page count after the separator. |
| `className` | `string` | Yes |  | Application-owned classes on the wrapper. |


## Composition

It belongs in a page-furniture slot: the `furniture` prop of
[`Pages`](/components/pages) or [`Paper`](/components/paper). Hand the same
object to `renderPdf(element, { plan, furniture })` from
[`@asterdoc/react-pdf`](/sdk/react-pdf) and the PDF carries the footer the
preview drew, page for page.

```tsx
import { renderPdf } from "@asterdoc/react-pdf";
import { PageNumber } from "@/components/asterdoc/page-number";
import { Pages } from "@/components/asterdoc/pages";

const furniture = { footer: <PageNumber /> };

<Pages furniture={furniture}>{document}</Pages>;
// and, on the server:
await renderPdf(document, { plan, furniture });
```

The numbers are two marked slots rather than one string, because the PDF
engine substitutes its own counters into them. That is why the wording is
`label` and `separator` rather than a format function: a function could not
run inside the engine. Anywhere with nothing paginating above it — a bare
`Paper`, a component rendered on its own — it reads "Page 1 of 1", because
there is one sheet.

It carries no pagination unit of its own: furniture is not part of the flow,
so it is never planned onto a page and never a
[`Keep Together`](/components/keep-together).

## Variants

### Number only

`total` drops the page count, so the foot reads "Page 2" rather than
"Page 2 of 4".


```tsx
import { Document } from "@/components/asterdoc/document";
import { PageNumber } from "@/components/asterdoc/page-number";
import { Pages } from "@/components/asterdoc/pages";
import { Section } from "@/components/asterdoc/section";
import { Table } from "@/components/asterdoc/table";
import { proposalForm } from "@/examples/proposal";
import { overflowProposalData } from "@/examples/proposal-data";

export function PageNumberVariantNumberOnly() {
  return (
    <Pages furniture={{ footer: <PageNumber total={false} /> }}>
      <Document artifact={proposalForm} data={overflowProposalData} id="page-number-number-only">
        <Section id="line-items" title="Scope and pricing" className="flex flex-col gap-3">
          <Table
            path="lineItems"
            id="line-items"
            columns={[
              { field: "description", width: "basis-1/2" },
              { field: "amount", width: "basis-1/6", align: "right" },
            ]}
          />
        </Section>
      </Document>
    </Pages>
  );
}
```


### Custom wording

`label` and `separator` replace the default "Page" and "of", so the same two
numbers read "Sheet 2 / 4".


```tsx
import { Document } from "@/components/asterdoc/document";
import { PageNumber } from "@/components/asterdoc/page-number";
import { Pages } from "@/components/asterdoc/pages";
import { Section } from "@/components/asterdoc/section";
import { Table } from "@/components/asterdoc/table";
import { proposalForm } from "@/examples/proposal";
import { overflowProposalData } from "@/examples/proposal-data";

export function PageNumberVariantCustomWording() {
  return (
    <Pages furniture={{ footer: <PageNumber label="Sheet" separator="/" /> }}>
      <Document artifact={proposalForm} data={overflowProposalData} id="page-number-custom-wording">
        <Section id="line-items" title="Scope and pricing" className="flex flex-col gap-3">
          <Table
            path="lineItems"
            id="line-items"
            columns={[
              { field: "description", width: "basis-1/2" },
              { field: "amount", width: "basis-1/6", align: "right" },
            ]}
          />
        </Section>
      </Document>
    </Pages>
  );
}
```
