# Invoice

> A printable invoice card — sender and recipient details, a ToneBadge payment status, a line-item table with totals, and a download action.

A shadcn/ui block from the [@quill](https://www.quilldesignsystem.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/quill/invoice).

- Page, with a live preview: https://shadcn.exchange/r/quill/invoice
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/quill/invoice-light-6f65e31bcfc0dfdf.png
- Registry item: https://www.quilldesignsystem.com/r/invoice.json
- Categories: commerce, data-display
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://www.quilldesignsystem.com/r/invoice.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `card`, `table`, `https://www.quilldesignsystem.com/r/tone-badge.json`, `button`, `separator`, `https://www.quilldesignsystem.com/r/icon.json`

## Notes from the registry

A printable invoice card — sender and recipient details, a ToneBadge payment status, a line-item table with totals, and a download action. Do: Keep the total in a table footer, visually distinct from line items (its own row, right-aligned). Don't: Let the total blend in as just another line item — it needs to read as the sum, not another charge. Use order-summary when you're showing a cart before payment, not a record of a completed transaction. Use data-table when you need a list of many invoices to browse, not the full detail of one.

## Files

### `registry/blocks/invoice.tsx`

```tsx
import { Card, CardHeader, CardContent, CardFooter } from '@/components/ui/card'
import {
  Table,
  TableBody,
  TableCell,
  TableFooter,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { ToneBadge } from '@/components/ui/tone-badge'
import { Button } from '@/components/ui/button'
import { Icon } from '@/components/ui/icon'
import { Separator } from '@/components/ui/separator'

const lines = [
  { item: 'Design system retainer — June', qty: 1, rate: '$3,200.00', amount: '$3,200.00' },
  { item: 'Brand lock-up refinements', qty: 6, rate: '$140.00', amount: '$840.00' },
  { item: 'Storybook pattern library', qty: 12, rate: '$95.00', amount: '$1,140.00' },
]

/** A printable invoice card — sender and recipient details, a ToneBadge payment status, a line-item table with totals, and a download action. */
export function Invoice() {
  return (
    <Card className="mx-auto w-full max-w-[640px]">
      <CardHeader className="gap-3">
        <div className="flex items-start justify-between gap-4">
          <div className="flex flex-col gap-1">
            <span className="font-heading text-lg text-foreground">Invoice 0042</span>
            <span className="text-sm text-muted-foreground">Issued June 30, 2026 · Due July 14, 2026</span>
          </div>
          <ToneBadge tone="moss">Paid</ToneBadge>
        </div>
        <Separator />
        <div className="grid grid-cols-2 gap-4 text-sm">
          <div className="flex flex-col gap-0.5">
            <span className="text-xs tracking-label uppercase text-muted-foreground">From</span>
            <span className="font-medium text-foreground">Craftwell</span>
            <span className="text-muted-foreground">hello@craftwell.ai</span>
          </div>
          <div className="flex flex-col gap-0.5">
            <span className="text-xs tracking-label uppercase text-muted-foreground">Billed to</span>
            <span className="font-medium text-foreground">Northwind Ltd.</span>
            <span className="text-muted-foreground">accounts@northwind.com</span>
          </div>
        </div>
      </CardHeader>
      <CardContent>
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead>Description</TableHead>
              <TableHead className="text-right">Qty</TableHead>
              <TableHead className="text-right">Rate</TableHead>
              <TableHead className="text-right">Amount</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {lines.map((l) => (
              <TableRow key={l.item}>
                <TableCell className="font-medium text-foreground">{l.item}</TableCell>
                <TableCell className="text-right text-muted-foreground">{l.qty}</TableCell>
                <TableCell className="text-right text-muted-foreground">{l.rate}</TableCell>
                <TableCell className="text-right text-foreground">{l.amount}</TableCell>
              </TableRow>
            ))}
          </TableBody>
          <TableFooter>
            <TableRow>
              <TableCell colSpan={3}>Total</TableCell>
              <TableCell className="text-right">$5,180.00</TableCell>
            </TableRow>
          </TableFooter>
        </Table>
      </CardContent>
      <CardFooter className="justify-between">
        <span className="text-xs text-muted-foreground">Thank you — see you next issue.</span>
        <Button variant="outline" size="sm">
          <Icon name="download" size={16} /> Download PDF
        </Button>
      </CardFooter>
    </Card>
  )
}
```
