# Totals

The artifact's computed amounts, evaluated by @asterdoc/core.

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

`Totals` prints nothing it computes itself: each row names a `def` the
artifact declares as a computed field with its own expression, and
`@asterdoc/core` evaluates it. `Totals` only reads the def's label and its
serializer-formatted amount, the same way a `Field` reads a plain one.

## Preview


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

export function TotalsDemo() {
  return (
    <Document artifact={proposalForm} data={shortProposalData} id="totals-demo">
      <Totals
        rows={[
          { def: "subtotal" },
          { def: "tax", ratePath: "taxRatePercent" },
          { def: "total", emphasis: true },
        ]}
      />
    </Document>
  );
}
```


## Installation


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


```bash
asterdoc add totals
```


Installs to components/asterdoc/totals.tsx.


## Usage


```tsx
import { Totals } from "@/components/asterdoc/totals";

<Totals rows={[{ def: "total", label: "Amount due", emphasis: true }]} />
```

| Prop | Type | Optional | Default | Description |
| --- | --- | --- | --- | --- |
| `rows` | `readonly TotalRow[]` | No |  | The computed amounts to show, in order. |
| `id` | `string` | Yes | "totals" | Stable keep id. |
| `className` | `string` | Yes |  | Application-owned classes replacing the block's default column layout. |


## Composition

`Totals` needs the same `Document` context every other component here does,
and each row's `def` names a computed field the artifact declares —
`subtotal`, `tax`, `total`, and so on — the same convention
[`Field`](/components/field) uses for a plain path, pointed instead at an
expression. It is a `Keep Together`, so the whole block is never split
across a page break.

`Totals` normally follows the [`Table`](/components/table) it totals, inside
the same [`Section`](/components/section): a table of line items, then the
subtotal, tax, and grand total beneath it. A row's optional `ratePath`
prints a percentage field beside that row's own label — a tax rate next to
"Tax" — without a separate row for it, and `emphasis` marks the grand total
with a rule and bolder text. When a tenant sets an accent color, an
emphasized row's rule is one of three places it lands, alongside a titled
section's heading and an emphasized [`Table`](/components/table) footer row.

The rows' sizes, and the emphasized total's, follow the document's
[typography](/components/typography) token.

## Variants

### Single row

One emphasized def, for a document with nothing to subtotal separately.


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

export function TotalsVariantSingleRow() {
  return (
    <Document artifact={proposalForm} data={shortProposalData} id="totals-variant-single-row">
      <Totals rows={[{ def: "total", emphasis: true }]} />
    </Document>
  );
}
```


### With tax rate

`ratePath` prints the rate field beside the tax row's own label.


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

export function TotalsVariantWithTaxRate() {
  return (
    <Document artifact={proposalForm} data={shortProposalData} id="totals-variant-with-tax-rate">
      <Totals rows={[{ def: "subtotal" }, { def: "tax", ratePath: "taxRatePercent" }]} />
    </Document>
  );
}
```


### Custom label

`label` overrides the total def's own label.


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

export function TotalsVariantCustomLabel() {
  return (
    <Document artifact={proposalForm} data={shortProposalData} id="totals-variant-custom-label">
      <Totals rows={[{ def: "total", label: "Amount due", emphasis: true }]} />
    </Document>
  );
}
```
