Billing Discount Badge
A promotional discount badge for pricing pages, checkout flows, and upgrade prompts. Shows the computed percent-off next to the discounted price and the struck-through original price, with an optional expiry note and a hover-lift on the call-to-action. Built with shadcn/ui Badge and Button components, Lucide icons, and Tailwind CSS.
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-discount-badge.jsonPrefer not to use the CLI? Copy the source from the Code toggle above into src/components/blocks/billing/billing48.tsx instead.
Usage
The file also exports billing48Demo, 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 { Billing48, billing48Demo } from "@/components/blocks/billing/billing48"; export default function Page() { return <Billing48 {...billing48Demo} />; }
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | "Limited-time offer" | Small label next to the percent-off badge. |
| originalPrice | number | none | Full price shown struck through, also used to compute the percent-off value. |
| discountedPrice | number | none | Discounted price shown as the primary figure. |
| currencySymbol | string | "$" | Symbol shown before both prices. |
| period | string | "/month" | Billing period suffix shown after the discounted price. |
| expiresLabel | string | none | Static text describing when the offer ends, omitted if not passed. |
| ctaLabel | string | "Claim discount" | Label on the call-to-action button. |
| ctaHref | string | "#" | Destination for the call-to-action link. |
| className | string | none | Extra classes for the outer container. |
Behavior notes
- The percent-off value is computed from originalPrice and discountedPrice on every render, it's never passed in directly, so the badge and the two price figures can never disagree.
- Both prices are formatted with toFixed(2), so pass numeric dollar values rather than pre-formatted strings.
- expiresLabel is a plain string, not a live countdown, if you need a real ticking timer you'll need to add your own interval and pass the formatted remaining time in on each render.
- Hovering the card lifts the call-to-action button slightly and darkens the border, both handled with Tailwind's group-hover utilities rather than JavaScript state.
- The call-to-action renders as a real next/link through the Button component's render prop, so it behaves like a normal link (right-click, open in new tab) rather than a JavaScript-only click handler.
Frequently asked questions
More Billing Blocks
View all →Billing Invoice List
Invoice history table with status badges, formatted amounts, and a per-row download link, built with shadcn/ui and Tailwind CSS.
Billing Failed Payment Alert
High-contrast failed-payment alert with a message, a retry button, and an optional update-payment-method button, built with shadcn/ui and Tailwind CSS.
Billing Credit Balance
Compact credit balance card with a large total, an optional purchased-versus-promotional breakdown, a low-balance notice, and a top-up button.
Billing Payment Methods
A saved payment method list for React and Next.js with brand icons, a default badge, near-expiry warnings, and remove/set-default actions per row.
Billing Add Card
A card entry form for React and Next.js with auto-formatted fields, internal brand detection, and per-field validation feedback built with shadcn/ui and Tailwind CSS.
Billing Coupon Code
An inline promo code input for React and Next.js with a simulated loading state, an applied summary showing the discount amount, and an invalid-code message.