Staaarter

Billing Early Renewal Bonus

A renewal-incentive card for account and billing settings pages. It shows how many days are left in the current renewal window with a progress bar, highlights a bonus (extra credits, a feature unlock, a price lock) for renewing early, and links straight to a renew action. Built for SaaS billing flows that want to smooth out cash flow by pulling renewals forward.

By Staaarter Team
Billing
Updated July 28, 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-early-renewal-bonus.json

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

Usage

The file also exports billing51Demo, 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 { Billing51, billing51Demo } from "@/components/blocks/billing/billing51";

export default function Page() {
  return <Billing51 {...billing51Demo} />;
}

Props

PropTypeDefaultDescription
headingstring"Renew early and get a bonus"Card heading.
descriptionstringnoneOptional supporting sentence under the heading.
planNamestringnoneOptional plan name shown next to the days-left label.
daysRemainingnumbernoneDays left in the early-renewal window. Clamped between 0 and windowDays for display.
windowDaysnumber60Total length of the early-renewal window in days, used to size the progress bar.
bonusLabelstringnoneWhat the customer gets for renewing early, e.g. "10% extra API credits".
bonusValueLabelstringnoneOptional dollar value of the bonus, shown under bonusLabel.
renewLabelstring"Renew now"Label on the renew button.
renewHrefstringnoneDestination the renew button links to.
classNamestringnoneExtra classes for the outer container.

Behavior notes

  • The progress bar fills based on daysRemaining divided by windowDays, and its color switches from the primary color to amber once 20% or less of the window is left, as a soft visual cue to act soon.
  • daysRemaining is clamped between 0 and windowDays before it's used for the bar or the day count text, so passing a value outside that range won't overflow or invert the bar.
  • There's no countdown timer or interval, the days-left number is static per render. Recompute it server-side from the actual renewal date and pass it in fresh.
  • The renew button renders as a next/link via the Button component's render prop, so renewHref can point straight at a pre-filled checkout session.

Frequently asked questions