Early bird: 30% off Dashral ProSee pricing

Dashral

Billing overviewPro

A workspace's billing at a glance: the plan and its price monthly or yearly, the card on file as a card you can tilt, usage near its limits, and invoices as lines of what they were for. A failed payment raises a banner with Pay now. On motion.

Installation

When to use

  • A workspace's billing page at a glance: the plan and its price, the card on file, usage near its limits and the invoices, with a way to pay one that failed.
  • Subscription products with a few plans and add-ons, where people mostly check what they pay, upgrade and settle a failed payment.

When not to use

  • Usage-based pricing that needs the spend, where it's heading and alerts: Billing settings.
  • One invoice in full, to send or record a payment: Invoice detail.

Usage

Billing overview with your own data: every prop has the sample as its default, so pass only what you have.

example.tsx
"use client"

import { BillingOverview } from "@/components/dashral/blocks/billing-overview"

export default function Billing() {
  return (
    <BillingOverview
      workspace="Acme Inc."
      plan={{ id: "growth", name: "Growth", monthly: 199, billing: "monthly", renews: "Dec 14, 2026", includes: ["15 seats", "1M API calls"] }}
      // The plans above this one, for the Upgrade dialog.
      plans={[{ id: "business", name: "Business", monthly: 499, includes: ["50 seats", "10M API calls"], note: "Most teams" }]}
      card={{ brand: "Visa", last4: "4242", expires: "08/28", holder: "Acme Inc." }}
      meters={[{ id: "seats", label: "Seats", used: 12, limit: 15 }]}
      invoices={[
        { id: "INV-31", date: "Nov 14, 2026", title: "Growth plan", detail: "Nov 14 – Dec 13", amount: 199, status: "paid" },
        { id: "INV-30", date: "Nov 3, 2026", title: "Log retention add-on", detail: "Card declined by the bank", amount: 36, status: "failed" },
      ]}
      recipient={{ name: "Olivia Martin", email: "olivia@acme.com" }}
      // While a promise is pending its button shows it; a thrown Error changes nothing and its message shows at the top.
      onChangePlan={async (plan, billing) => console.log("switch to", plan.id, billing)}
      onBillingChange={async (billing) => console.log("billing", billing)}
      onPay={async (invoice) => console.log("pay", invoice.id)}
      onUpdateCard={() => console.log("open your card form")}
    />
  )
}

API reference

BillingOverview

A workspace's billing at a glance: the plan and its price (monthly or yearly), the card on file as a card you can tilt, usage of the plan's limits, and the invoices as lines of what they were for, paid, failed, due or refunded. A payment that failed raises a banner with Pay now; paying turns its invoice to Paid. Every part comes from props; every action calls your handler first.

PropTypeDefault
workspacestring

The workspace the page is for, at the top.

"Acme Inc."
planOverviewPlansample
cardOverviewCard | null

The card on file; null shows none, with a way to add one.

sample
metersOverviewMeter[]sample
periodstring

When the usage period runs, as shown: "Nov 14 – Dec 13".

"Nov 14 – Dec 13"
invoicesOverviewInvoice[]sample
recipient{ name: string; email?: string }

Who the invoices go to.

sample
currencystring"USD"
localestring"en-US"
onBillingChange(billing: OverviewBilling) => Promise<void> | void

Monthly or yearly picked: while the promise is pending the switch shows it; a throw puts it back and says why.

—
plansOverviewPlanOption[]

The plans to move up to: Upgrade opens them, growing out of the button. Left out or empty, Upgrade calls onUpgrade.

sample
onChangePlan(plan: OverviewPlanOption, billing: OverviewBilling) => Promise<void> | void

Move to a plan from the Upgrade list: its Switch shows it's working while the promise is pending; on success the plan card shows it, a throw says why.

—
onUpgrade() => void

Upgrade without a list of plans: open your own plans or checkout.

—
onUpdateCard() => void—
onPay(invoice: OverviewInvoice) => Promise<void> | void

Pay an invoice that failed or is due: its button shows it's working while the promise is pending; on success it turns Paid.

—
onDownload(invoice: OverviewInvoice) => void

An invoice without an href: download it yourself.

—
classNamestring—

OverviewPaymentCard

The card on file as a card: its network's logo, chip and number, the holder and when it expires. It tilts toward the pointer with a sheen that follows it, and settles back when the pointer leaves; with reduced motion it stays flat.

PropTypeDefault
cardOverviewCard

Required.

—
classNamestring—

OverviewMeterTile

One thing the plan limits, as a tile: what's used turning up from zero, its bar growing, and a badge near the limit.

PropTypeDefault
meterOverviewMeter

Required.

—
readybooleantrue

type OverviewBilling

= "monthly" | "yearly"

type OverviewPlan

PropTypeDefault
idstring—
namestring—
iconReact.ReactNode—
monthlynumber

The price a month, and a year (a year is ten months when left out).

—
yearlynumber—
billingOverviewBilling—
renewsstring

When it renews, as shown: "Dec 14, 2026".

—
includesstring[]

What it includes, in short: "15 seats", "1M API calls".

—

type OverviewPlanOption

A plan to move up to, in the Upgrade list: what it adds (includes), a short note ("Most teams").

PropTypeDefault
idstring—
namestring—
monthlynumber—
yearlynumber—
includesstring[]—
notestring—
iconReact.ReactNode—

type OverviewCard

The card on file. mark is its network's logo (white, on the card); left out, Visa's.

PropTypeDefault
brandstring—
last4string—
expiresstring—
holderstring—
markReact.ReactNode—

type OverviewMeter

One thing the plan limits; format writes its numbers, unit follows them.

PropTypeDefault
idstring—
labelstring—
usednumber—
limitnumber—
unitstring—
format(value: number) => string—

type OverviewInvoiceStatus

= "paid" | "failed" | "due" | "refunded"

type OverviewInvoice

An invoice as a line of what it was for: title ("Growth plan"), detail under it (the period, why a payment failed, when a transfer is due).

PropTypeDefault
idstring—
datestring—
titlestring—
detailstring—
amountnumber—
statusOverviewInvoiceStatus—
hrefstring—