UIPackage
Menu

Framework

Change language

Boilerplate repo

Billing Account

blockfinance

Stripe-style account billing page: current-plan card with Pro badge, price and renewal date plus Upgrade / Cancel actions, usage meters for seats and projects, a payment-method row with update and delete actions, and a compact billing-history list with paid badges and per-invoice downloads. Data is hardcoded inline so you can wire it to your own billing API.

Also available for Vue ->

Installation

$npx shadcn@latest add https://uipkge.dev/r/react/billing-account.json
Named registry:npx shadcn@latest add @uipkge-react/billing-accountInstalls to:components/blocks/

Variants

Loading interactive previews…

Schema

Type aliases exported from this item's source. Use these to shape the data you pass in.

UsageMetric
interface UsageMetric {
  label: string
  used: number
  total: number
}
Invoice
interface Invoice {
  id: string
  date: string
  amount: string
  status: 'Paid' | 'Open' | 'Past due'
}

Files installed (1)

  • components/blocks/BillingAccount.tsx5.7 kB
    'use client'
    
    import { CreditCard, Download, Trash2 } from 'lucide-react'
    import { cn } from '@/lib/utils'
    import { Badge } from '@/components/ui/badge'
    import { Button } from '@/components/ui/button'
    import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
    import { Progress } from '@/components/ui/progress'
    import { Separator } from '@/components/ui/separator'
    
    interface UsageMetric {
      label: string
      used: number
      total: number
    }
    
    interface Invoice {
      id: string
      date: string
      amount: string
      status: 'Paid' | 'Open' | 'Past due'
    }
    
    const plan = {
      name: 'Pro',
      price: '$49',
      cadence: 'month',
      renewalDate: 'September 12, 2026',
    }
    
    const usage: UsageMetric[] = [
      { label: 'Seats', used: 18, total: 20 },
      { label: 'Projects', used: 7, total: 10 },
    ]
    
    const paymentMethod = {
      brand: 'Visa',
      last4: '4242',
      expiry: '04/28',
    }
    
    const invoices: Invoice[] = [
      { id: 'inv-2026-08', date: 'Aug 12, 2026', amount: '$49.00', status: 'Paid' },
      { id: 'inv-2026-07', date: 'Jul 12, 2026', amount: '$49.00', status: 'Paid' },
      { id: 'inv-2026-06', date: 'Jun 12, 2026', amount: '$49.00', status: 'Paid' },
      { id: 'inv-2026-05', date: 'May 12, 2026', amount: '$49.00', status: 'Paid' },
    ]
    
    export function BillingAccount({ className }: { className?: string }) {
      return (
        <div data-slot="billing-account" className={cn('mx-auto w-full max-w-2xl space-y-6', className)}>
          <Card>
            <CardHeader>
              <div className="flex items-center gap-2">
                <CardTitle>Current plan</CardTitle>
                <Badge>Pro</Badge>
              </div>
              <CardDescription>Your subscription renews automatically each month.</CardDescription>
            </CardHeader>
            <CardContent className="space-y-4">
              <div className="flex flex-wrap items-end justify-between gap-4">
                <div>
                  <p className="text-2xl font-bold tracking-tight">
                    {plan.price}
                    <span className="text-muted-foreground text-sm font-normal"> / {plan.cadence}</span>
                  </p>
                  <p className="text-muted-foreground mt-1 text-xs">Renews on {plan.renewalDate}</p>
                </div>
                <div className="flex items-center gap-2">
                  <Button size="sm">Upgrade</Button>
                  <Button variant="ghost" size="sm" className="text-destructive hover:text-destructive">
                    Cancel subscription
                  </Button>
                </div>
              </div>
            </CardContent>
          </Card>
    
          <Card>
            <CardHeader>
              <CardTitle>Usage</CardTitle>
              <CardDescription>Consumption against your plan limits this cycle.</CardDescription>
            </CardHeader>
            <CardContent className="space-y-5">
              {usage.map((metric) => (
                <div key={metric.label} className="space-y-2">
                  <div className="flex items-center justify-between text-sm">
                    <span className="font-medium">{metric.label}</span>
                    <span className="text-muted-foreground text-xs tabular-nums">
                      {metric.used} of {metric.total} used
                    </span>
                  </div>
                  <Progress value={(metric.used / metric.total) * 100} />
                </div>
              ))}
            </CardContent>
          </Card>
    
          <Card>
            <CardHeader>
              <CardTitle>Payment method</CardTitle>
              <CardDescription>Charged when your subscription renews.</CardDescription>
            </CardHeader>
            <CardContent>
              <div className="flex items-center justify-between gap-4">
                <div className="flex items-center gap-3">
                  <div
                    aria-hidden="true"
                    className="bg-muted text-muted-foreground border-border flex size-9 shrink-0 items-center justify-center rounded-md border shadow-xs"
                  >
                    <CreditCard className="size-4" />
                  </div>
                  <div>
                    <p className="text-sm font-medium tabular-nums">•••• •••• •••• {paymentMethod.last4}</p>
                    <p className="text-muted-foreground text-xs">
                      {paymentMethod.brand} · Expires {paymentMethod.expiry}
                    </p>
                  </div>
                </div>
                <div className="flex items-center gap-1">
                  <Button variant="ghost" size="sm">
                    Update
                  </Button>
                  <Button variant="ghost" size="icon-sm" aria-label="Delete payment method">
                    <Trash2 className="text-muted-foreground size-4" />
                  </Button>
                </div>
              </div>
            </CardContent>
          </Card>
    
          <Card>
            <CardHeader>
              <CardTitle>Billing history</CardTitle>
              <CardDescription>Invoices from the last 12 months.</CardDescription>
            </CardHeader>
            <CardContent>
              <ul className="-my-2 divide-y">
                {invoices.map((invoice) => (
                  <li key={invoice.id} className="flex items-center justify-between gap-4 py-3">
                    <div className="min-w-0">
                      <p className="text-sm font-medium">{invoice.date}</p>
                      <p className="text-muted-foreground text-xs tabular-nums">{invoice.amount}</p>
                    </div>
                    <div className="flex items-center gap-2">
                      <Badge variant="success">{invoice.status}</Badge>
                      <Separator orientation="vertical" className="!h-4" />
                      <Button variant="ghost" size="icon-sm" aria-label="Download invoice">
                        <Download className="text-muted-foreground size-4" />
                      </Button>
                    </div>
                  </li>
                ))}
              </ul>
            </CardContent>
          </Card>
        </div>
      )
    }
    

Raw manifest:https://uipkge.dev/r/react/billing-account.json