Document page
ProA page of a source document as a reader would see it, with numbered clauses an agent can point at and mark while it explains them.
npx prodular-ui add document-pagePart of Prodular UI Pro. Preview and read the docs freely, install with a license. See pricing
Clauses
The document and page above, the text on a sheet. marked shows the clause the agent is talking about.
12.1 Exclusions. Neither party is liable for indirect, incidental or consequential losses, including lost profits, arising out of this agreement.
12.2 Limitation of liability. Each party's total liability under this agreement is limited to the fees paid by the customer in the twelve months before the event giving rise to the claim.
12.3 Notice of claims. A party must give written notice of a claim within ninety days of becoming aware of it.
import { DocumentClause, DocumentPage } from "@/components/ui/document-page"
export default function DocumentPageClauses() { return ( <DocumentPage title="Master services agreement, Halcyon Labs and Tidewater Freight" page="Page 4 of 12" className="w-full max-w-2xl"> <DocumentClause number="12.1" title="Exclusions"> Neither party is liable for indirect, incidental or consequential losses, including lost profits, arising out of this agreement. </DocumentClause> <DocumentClause id="msa-12-2" number="12.2" title="Limitation of liability" marked> Each party's total liability under this agreement is limited to the fees paid by the customer in the twelve months before the event giving rise to the claim. </DocumentClause> <DocumentClause number="12.3" title="Notice of claims"> A party must give written notice of a claim within ninety days of becoming aware of it. </DocumentClause> </DocumentPage> )}Two documents
With Connector, a bracket runs from one clause to the one that overrides it.
12.2 Limitation of liability. Each party's total liability is limited to the fees paid in the twelve months before the claim.
9.2 Precedence. Data protection claims are not subject to any limit of liability. Where this exhibit conflicts with the agreement, this exhibit controls.
import { Connector, ConnectorAnchor, ConnectorLabel, ConnectorRoot } from "@/components/ui/connector"import { DocumentClause, DocumentPage } from "@/components/ui/document-page"
export default function DocumentPageLinked() { return ( <ConnectorRoot className="flex w-full max-w-2xl flex-col gap-8 ps-28"> <DocumentPage title="Master services agreement" page="Page 4 of 12"> <ConnectorAnchor name="msa" render={<DocumentClause number="12.2" title="Limitation of liability" marked />}> Each party's total liability is limited to the fees paid in the twelve months before the claim. </ConnectorAnchor> </DocumentPage> <DocumentPage title="Exhibit B, data processing" page="Page 2 of 5"> <ConnectorAnchor name="exhibit" render={<DocumentClause number="9.2" title="Precedence" marked />}> Data protection claims are not subject to any limit of liability. Where this exhibit conflicts with the agreement, this exhibit controls. </ConnectorAnchor> </DocumentPage> <Connector from="msa" to="exhibit" shape="bracket" inset={100} className="text-foreground"> <ConnectorLabel>Overrides</ConnectorLabel> </Connector> </ConnectorRoot> )}Anatomy
<DocumentPage title="Master services agreement" page="Page 4 of 12"> <DocumentClause id="msa-12-2" number="12.2" title="Limitation of liability" marked> … </DocumentClause></DocumentPage>Guidance
Use it when
- Use it to show the source an answer came from: a contract, a policy, a filing, a report.
- Keep the original numbering and wording. People compare it with the document they signed.
- Mark the clause the agent is talking about, one or two at a time.
Avoid
- Generated text. An Artifact holds what the model wrote; a document page holds what people wrote.
- Whole documents. Show the page or the clauses that matter, and link to the full file.
- Marking every clause on the page.
Rules for AI agents
Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.
- Quote clauses exactly as extracted. Never rewrite, summarize or fix them inside a DocumentClause.
- Pass title with the document's name and page with its position, for example "Page 4 of 12", from the source file.
- Give each clause a stable id built from the document and number, for example id="msa-12-2", so citations and links can scroll to it.
- Set marked only on the clauses the current answer cites. To link two clauses, wrap them in ConnectorAnchor with render={<DocumentClause />}.
- The sheet uses font-doc, which is the theme's font. Set --font-document only when the customer wants documents in their own typeface.
API
DocumentPage
| Prop | Type | Default | Description |
|---|---|---|---|
| title | ReactNode | The document's name. | |
| page | ReactNode | Where this is, for example "Page 4 of 12". |
DocumentClause
| Prop | Type | Default | Description |
|---|---|---|---|
| number / title | string | Shown in bold before the text, for example "12.2 Limitation of liability." | |
| marked | boolean | false | Tints the clause the agent is talking about. Exposed as data-marked. |
Installation
The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.
npx prodular-ui add document-page# or, with the registry in components.jsonnpx shadcn@latest add @prodular/document-page