caliper uidocs

Pricing template

Block

A pricing page in one voice: the deal in one line, plans worked out from the buyer's numbers, the switch row by row, the last doubts and one action.

Installs components/ui/pricing-template.tsxDepends on lucide-reactMotion none in component source
pnpm dlx shadcn@latest add https://caliperui.site/r/pricing-template.json
Skip to content

Pricing

Pay for the seats that close the books

Every plan includes unlimited entities on review, daily matching and the audit trail export.

  • 14 days free
  • No card to start
  • Cancel from settings

Choose a plan

Move the slider to your headcount. The plan that fits is marked, with the reason.

  • Starter

    —Not available for 14 seats

    Not available above 5 seats
    • 2 bank connections
    • Monthly close
    • Email support
  • TeamFor you

    /mo$448 per month

    14 seats × $32
    • Unlimited connections
    • Daily matching
    • Audit trail export
  • Scale

    /mo$672 per month

    14 seats × $48
    • Multi-entity
    • SSO and SCIM
    • Named accountant

14 seats is more than Starter allows, so Team fits.

Prices in USD, before tax.

Why switch

Month end, before and after

  • Matching bank lines

    Spreadsheets: VLOOKUPs across three exports, rerun after every correction.

    With Halden: Matched as each line lands, with the rule that matched it.

  • Finding a mismatch

    Spreadsheets: Scroll until the totals stop disagreeing.

    With Halden: Six lines, each with the likeliest invoice and who approved it.

  • Audit evidence

    Spreadsheets: Forty files, renamed by hand in October.

    With Halden: One export auditors can sample.

  • Time to close

    Spreadsheets: Nine working days.

    With Halden: A morning.

FAQ

Questions finance teams ask

Straight answers, each linked to the page that explains it in full.

Not here? Ask us about it

  • No. It prepares the close; your accountant reviews it and signs off, usually faster. How review works

Start today

Close October in a morning.

14 days free · no card · import your September close

When to use #

Use it for

  • A standalone pricing page linked from the header.
  • Plans that depend on seats, doors or usage.

Skip it when

  • One flat price; state it on the landing page.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/pricing-template.json

Adds its 14 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.

Usage #

This is the code behind the preview above.

example.tsx
import { PricingTemplate } from "@/components/ui/pricing-template"

const siteNav = (current?: string) => [
  { label: "Product", href: "#product" },
  { label: "Pricing", href: "#pricing", current: current === "pricing" },
  { label: "Customers", href: "#customers" },
  { label: "Changelog", href: "#changelog", current: current === "changelog" },
];

const pricingIntro: Parameters<typeof PricingTemplate>[0]["intro"] = { eyebrow: "Pricing", title: "Pay for the seats that close the books", lead: "Every plan includes unlimited entities on review, daily matching and the audit trail export.", facts: ["14 days free", "No card to start", "Cancel from settings"] };

export function PricingPageDemo() {
  return (
    <div className="h-[720px] w-full overflow-auto rounded-[14px] shadow-[0_0_0_1px_var(--border)]">
      <PricingTemplate
        brand="Halden"
        nav={siteNav("pricing")}
        signIn={{ label: "Sign in", href: "#" }}
        primary={heroes.primary!}
        intro={pricingIntro}
        pricing={{ ...pricing, eyebrow: undefined, title: "Choose a plan" }}
        comparison={comparisons}
        faq={faqs}
        cta={ctas}
        footer={footers}
      />
    </div>
  );
}

API reference #

PricingTemplate

component
PropTypeDefaultDescription
brand *string—
navreadonly BlockNavLink[][]
signInBlockAction—
primaryBlockAction—
intro *{ eyebrow?: string | undefined; title: string; lead?: string | undefined; facts?: readonly string[] | undefined; }—The page opening, e.g. "Pay for the seats you use", with the deal in one line.
pricing *Without<{ eyebrow?: string | undefined; title: ReactNode; lead?: string | undefined; plans: readonly BlockPlan[]; unit?: string | undefined; units?: { min: n…—
proofWithout<{ title?: string | undefined; logos: readonly string[]; caseStudy?: { figure: string; figureLabel: string; quote: string; person: string; action?: Bl…—
comparisonWithout<{ eyebrow?: string | undefined; title: string; lead?: string | undefined; beforeLabel: string; afterLabel: string; rows: readonly BlockComparisonRow[…—
faqWithout<{ eyebrow?: string | undefined; title: string; lead?: string | undefined; items: readonly BlockFaq[]; searchable?: boolean | undefined; ask?: { label…—
ctaWithout<{ eyebrow?: string | undefined; title: string; reassurance?: string | undefined; primary?: BlockAction | undefined; secondary?: BlockAction | undefin…—
footer(Omit<Without<{ brand: string; tagline?: string | undefined; columns: readonly BlockFooterColumn[]; newsletter?: { label: string; note?: string | undefined; …—
classNamestring—

Accessibility #

It is built on native elements and keeps aria-hidden in step with state.

No custom key handling; Tab and the native activation keys do the work.

Motion #

It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.