# Checkpoint: Spend Policy

> A studio's company card policy: a flight waits on its receipt, and a casino charge is blocked by merchant category.

A shadcn/ui block from the [@keyframeui](https://keyframeui.com/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/keyframeui/checkpoint-spend-demo).

- Page, with a live preview: https://shadcn.exchange/r/keyframeui/checkpoint-spend-demo
- Screenshot: https://shadcn.exchange/shot/keyframeui/checkpoint-spend-demo/light.png
- Registry item: https://keyframeui.com/r/checkpoint-spend-demo.json
- Categories: ai, interaction, data
- Listed: 2026-11-02, source last changed 2026-11-02

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/keyframeui/checkpoint-spend-demo.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: `https://keyframeui.com/r/checkpoint.json`

## Notes from the registry

Live preview, examples and props: https://keyframeui.com/components/checkpoint#checkpoint-spend-demo

## Files

### `registry/demos/checkpoint-spend-demo.tsx`

```tsx
import * as React from "react";

import { Checkpoint, type CheckpointRequest, type CheckpointRule } from "@/components/ui/checkpoint";

function Glyph({ children }: { children: React.ReactNode }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.8"
      strokeLinecap="round"
      strokeLinejoin="round"
      aria-hidden
    >
      {children}
    </svg>
  );
}

const card = (
  <Glyph>
    <rect x="3" y="5.5" width="18" height="13" rx="2.5" />
    <path d="M3 10h18M7 15h4" />
  </Glyph>
);

// Tinta, a design studio, and its company card policy. Merchants and people are made up.
const RULES: CheckpointRule[] = [
  {
    id: "merchant",
    label: "Merchant",
    detail: "Software, travel, meals, print",
    value: "Allowed",
    icon: (
      <Glyph>
        <path d="M4 9.5L5.5 4h13L20 9.5M4 9.5h16M4 9.5c0 1.5 1.2 2.5 2.7 2.5s2.6-1 2.6-2.5c0 1.5 1.2 2.5 2.7 2.5s2.7-1 2.7-2.5c0 1.5 1.1 2.5 2.6 2.5S20 11 20 9.5M5.5 12v8h13v-8" />
      </Glyph>
    ),
  },
  {
    id: "limit",
    label: "Per charge",
    detail: "Anything larger goes through a PO",
    value: "≤ $2,000",
    icon: (
      <Glyph>
        <path d="M4 18h16M6.5 18V11M12 18V6M17.5 18v-4" />
      </Glyph>
    ),
  },
  {
    id: "receipt",
    label: "Receipt",
    detail: "Over $75 needs one, or finance signs",
    value: "> $75",
    icon: (
      <Glyph>
        <path d="M6 3.5h12v17l-2-1.3-2 1.3-2-1.3-2 1.3-2-1.3-2 1.3z" />
        <path d="M9 8h6M9 11.5h6M9 15h3.5" />
      </Glyph>
    ),
  },
  {
    id: "budget",
    label: "Budget",
    detail: "Design team, Q4",
    value: "$18,400 left",
    icon: (
      <Glyph>
        <path d="M12 3.5a8.5 8.5 0 1 0 8.5 8.5H12z" />
        <path d="M15 3.8A8.5 8.5 0 0 1 20.2 9H15z" />
      </Glyph>
    ),
  },
];

const REQUESTS: CheckpointRequest[] = [
  { id: "figma", label: "FIGMA* ANNUAL", meta: "$45.00 · Lena Ortiz", icon: card },
  {
    id: "flight",
    label: "NORDAIR 0742",
    meta: "$1,386.40 · Sam Okafor, client visit in Oslo",
    verdicts: { receipt: "hold" },
    icon: card,
  },
  {
    id: "casino",
    label: "LUCKY STAR CASINO",
    meta: "$600.00 · Sam Okafor",
    verdicts: { merchant: "block" },
    reason: "Gambling isn't covered",
    icon: card,
  },
];

export function CheckpointSpendDemo() {
  return (
    <div className="w-full max-w-xl rounded-[26px] border border-zinc-950/[0.08] bg-white p-1.5 shadow-[0_1px_2px_rgba(0,0,0,0.04)] dark:border-white/10 dark:bg-zinc-950">
      <div className="rounded-[20px] bg-zinc-50 bg-[radial-gradient(120%_70%_at_50%_0%,rgba(10,159,92,0.08),transparent_70%)] p-4 sm:p-5 dark:bg-white/[0.03] dark:bg-[radial-gradient(120%_70%_at_50%_0%,rgba(50,213,131,0.08),transparent_70%)]">
        <div className="mb-4 flex items-baseline justify-between gap-4 px-0.5">
          <p className="text-[13px] font-semibold tracking-tight text-zinc-950 dark:text-zinc-100">
            Card policy <span className="font-normal text-zinc-500 dark:text-zinc-400">· Tinta Studio</span>
          </p>
          <p className="text-[12px] text-zinc-500 tabular-nums dark:text-zinc-400">3 cards live</p>
        </div>
        <Checkpoint
          rules={RULES}
          requests={REQUESTS}
          approver="Finance"
          className="[--checkpoint-accent:#0a9f5c] dark:[--checkpoint-accent:#32d583]"
        />
      </div>
    </div>
  );
}
```
