# List

An ordered or unordered list whose markers are text, so both outputs draw the same ones.

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

`List` prints numbered or bulleted items. The markers are text — `1.`, `a.`,
`i.`, `•` — written into the tree rather than asked of the renderer, because
the default PDF engine draws no list markers of its own. That is what makes
the preview and the PDF show the same characters.

## Preview


```tsx
import { Document } from "@/components/asterdoc/document";
import { List } from "@/components/asterdoc/list";
import { proposalForm } from "@/examples/proposal";
import { shortProposalData } from "@/examples/proposal-data";

export function ListDemo() {
  return (
    <Document artifact={proposalForm} data={shortProposalData} id="list-demo">
      <List
        id="exclusions"
        items={[
          { text: "Permits, inspections, and any fees a local authority charges." },
          { text: "Removal or disposal of equipment the site already carries." },
          { text: "Work outside the hours the site access agreement names." },
        ]}
      />
    </Document>
  );
}
```


## Installation


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


```bash
asterdoc add list
```


Installs to components/asterdoc/list.tsx.


## Usage


```tsx
import { List } from "@/components/asterdoc/list";

<List
  id="recitals"
  marker="roman"
  items={[{ text: "The provider supplies equipment." }, { text: "The customer procures it." }]}
/>
```

| Prop | Type | Optional | Default | Description |
| --- | --- | --- | --- | --- |
| `items` | `readonly ListItem[]` | No |  | The items, in order. |
| `marker` | `ListMarker` | Yes | "decimal" | How the top level's items are marked. |
| `nestedMarker` | `ListMarker` | Yes | "lower-alpha" | How every level nested under the top one is marked. |
| `id` | `string` | No |  | Prefix for each item's pagination id; an item's own id is `<id>:<index>`.

Required rather than defaulted: two lists sharing a prefix would claim the
same keep ids, and a duplicated id fails the whole page plan. |
| `className` | `string` | Yes |  | Classes replacing the top level's default column layout; a nested level keeps its own. |


## Composition

Items are data, not children: `items` is an array of `{ text, items? }`, and
an item's own `items` are a nested level. `text` takes anything React can
render, so a clause can carry a `<span>` of emphasis or a piece of text the
composition built — but never a [`Field`](/components/field),
[`Text`](/components/text), [`Table`](/components/table) or any other
[`Keep Together`](/components/keep-together), because the item already is one
and a keep inside a keep is measured twice. A value from the artifact goes
into an item as the text a composition read for it, not as a nested keep.

```tsx
<List
  id="clauses"
  items={[
    { text: "The provider performs the services." },
    {
      text: "The customer provides:",
      items: [{ text: "Site access." }, { text: "Power at each position." }],
    },
  ]}
/>
```

Every item is a [`Keep Together`](/components/keep-together) of its own, keyed
`<id>:<index>`, and a nested item extends its parent's key
(`clauses:1:0`). So a list that crosses a page boundary breaks between items,
never inside one, and the page plan can name any item as a break. A level
withdraws from a page holding none of its items, the same way a
[`Table`](/components/table) does, so a continued page carries no empty
indent.

A nested list carries its parent's marker as a prefix: the second sub-item of
clause 2 reads `2.b.`, which is how a numbered agreement refers to itself. A
bullet contributes nothing to that chain, because a bullet names nothing.

`marker` sets the top level's style and `nestedMarker` sets every level under
it. Markers, item text, and the gap between items all follow the document's
[typography](/components/typography) token.

`id` is required, not defaulted: it is the prefix every item's keep id is built
from, and two lists sharing one would claim the same ids and fail the page
plan. `className` replaces the top level's column layout; a nested level keeps
its own indent.

## Variants

### Unordered

`marker="bullet"` marks every item with the same character and numbers
nothing.


```tsx
import { Document } from "@/components/asterdoc/document";
import { List } from "@/components/asterdoc/list";
import { proposalForm } from "@/examples/proposal";
import { shortProposalData } from "@/examples/proposal-data";

export function ListVariantUnordered() {
  return (
    <Document artifact={proposalForm} data={shortProposalData} id="list-variant-unordered">
      <List
        id="deliverables"
        marker="bullet"
        items={[
          { text: "A site survey and the as-built drawings that follow it." },
          { text: "Commissioning against the agreed acceptance tests." },
          { text: "Twelve months of remote support." },
        ]}
      />
    </Document>
  );
}
```


### Nested

An item's own `items` are a level of their own, marked with `nestedMarker` and
prefixed with the parent's marker.


```tsx
import { Document } from "@/components/asterdoc/document";
import { List } from "@/components/asterdoc/list";
import { proposalForm } from "@/examples/proposal";
import { shortProposalData } from "@/examples/proposal-data";

export function ListVariantNested() {
  return (
    <Document artifact={proposalForm} data={shortProposalData} id="list-variant-nested">
      <List
        id="clauses"
        items={[
          { text: "The provider performs the services described above." },
          {
            text: "The customer provides, at its own cost:",
            items: [
              { text: "Access to the site during the hours named in the schedule." },
              { text: "Power and network drops at each equipment position." },
              { text: "A named contact who can accept the acceptance tests." },
            ],
          },
          { text: "Either party may terminate on thirty days' written notice." },
        ]}
      />
    </Document>
  );
}
```


### Roman

`marker="roman"` marks the items `i.`, `ii.`, `iii.`, the way a recitals block
is numbered.


```tsx
import { Document } from "@/components/asterdoc/document";
import { List } from "@/components/asterdoc/list";
import { proposalForm } from "@/examples/proposal";
import { shortProposalData } from "@/examples/proposal-data";

export function ListVariantRoman() {
  return (
    <Document artifact={proposalForm} data={shortProposalData} id="list-variant-roman">
      <List
        id="recitals"
        marker="roman"
        items={[{ text: "The provider supplies equipment." }, { text: "The customer procures it." }]}
      />
    </Document>
  );
}
```
