Staaarter

Billing Subscription Swap Preview

A confirmation preview for a plan upgrade or downgrade, shown before the change is committed. It puts the current plan and the new plan side by side, lists prorated line items such as unused-time credit and estimated tax, and totals the amount due today. An optional note explains scheduled downgrades that won't charge until the next cycle. Built for self-serve plan-change flows where surprise charges are the main source of support tickets.

By Staaarter Team
Billing
Updated May 27, 2026
Docs
Live preview

Docs

Installation

A real shadcn registry command, not a copy-paste stand-in: it fetches this block plus its badge, button dependencies and any missing npm packages, and installs them straight into your project.

npx shadcn add https://staaarter.com/r/billing-subscription-swap-preview.json

Prefer not to use the CLI? Copy the source from the Code toggle above into src/components/blocks/billing/billing134.tsx instead.

Usage

The file also exports billing134Demo, the exact props behind the preview above. Spread it to get a working section in one line, then replace it with your own data.

import { Billing134, billing134Demo } from "@/components/blocks/billing/billing134";

export default function Page() {
  return <Billing134 {...billing134Demo} />;
}

Props

PropTypeDefaultDescription
titlestring"Confirm your plan change"Heading above the plan comparison.
currentPlanSwapPlannoneThe plan the account is currently on.
newPlanSwapPlannoneThe plan being switched to.
lineItemsSwapLineItem[]noneBreakdown rows shown between the plan comparison and the total, in the order given.
totalDueTodayLabelstring"Total due today"Label on the total row.
totalDueTodaystringnoneFormatted total amount, already computed by the caller.
scheduledNotestringnoneOptional note shown below the total, for example explaining a downgrade takes effect at the end of the cycle.
confirmLabelstring"Confirm change"Label on the confirm button.
confirmHrefstring"#"Link the confirm button points to.
classNamestringnoneExtra classes for the outer container.

Types

interface SwapPlan {
  name: string;
  price: string;
  interval?: string;
}

interface SwapLineItem {
  label: string;
  amount: string;
  isCredit?: boolean;
}

Behavior notes

  • All amounts are plain strings, not numbers. The component does no proration math itself, it only displays values computed on your backend, typically from your billing provider's invoice-preview endpoint.
  • Line items with isCredit set true render their amount in the same emerald tone used elsewhere for positive states, so unused-time credits read visually distinct from charges.
  • The current-plan card and new-plan card are laid out side by side with an arrow between them; the new-plan card gets a primary ring to draw the eye.
  • scheduledNote is entirely optional and only renders when passed, useful for downgrades where you want to say no charge happens until the next billing cycle.
  • The confirm button is a real link (via next/link), not a submit handler, so wire your own onClick or route it to a server action if you fork the component for a real confirmation flow.

Frequently asked questions