KQ-1323 · UPGRADE/WALL

Upgrade Wall

A paywall whose comparison shows what the chosen plan unlocks: those rows light in a cascade and their locks lift open on snap, and a plan change re-lights only the rows that changed while the chosen column's cells roll and, in the all-plans view, a band slides across to the new column on snap. Plan and billing are radiogroups with pills that slide on snap, every price rolls digit by digit, and the trial is drawn as a track from today to the first charge whose span sweeps in on glide, ticking off each day, with the reminder above it. The purchase button holds its width through pending, success and error — success stamps its check on recoil and turns the track and the unlocked rows green — and the plan and billing groups take arrow keys while the comparison is a real table.

KQ-1323 · UPGRADE/WALL

Upgrade to keep your dashboards live

Gaugeworks · Your team has used 3 of 3 dashboards on Free.

Free compared with Team
FeatureFreeNowTeam
Dashboards3Unlimited
Live refreshNot includedEvery minute
Data retention30 days1 year
AlertsNot includedIncluded
Shared workspacesNot includedIncluded
SSO and SCIMNot includedNot included
Audit logNot includedNot included
SupportCommunityEmail

Your 14-day trial

  1. Today: full access starts, nothing to pay.
  2. 14 Oct: we email you a reminder.
  3. 16 Oct: €360 charged. Cancel before then and pay nothing.
€10/ seat / mo€360 on 16 Oct

team · yearly · €360 on 16 oct

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/upgrade-wall

Props

timeline
"track" | "list" | "none"
default "track"
The trial drawn as a track from today to the first charge, as a vertical list of the same three moments, or no trial at all (billed today).
compare
"table" | "unlocks" | "all"
default "table"
The current plan against the chosen one, only what the chosen plan unlocks, or every plan side by side with a band behind the chosen column.
cycle
"both" | "monthly" | "yearly"
default "both"
The billing cycles offered: both behind a switch with the yearly saving, or only one.
plans
UpgradePlan[]
default defaultUpgradePlans
The plans, the current one included: name, tagline, monthly and yearly per-seat price, current flag and badge.
features
UpgradeFeature[]
default defaultUpgradeFeatures
The comparison rows, each with a value per plan: included, not included, or a short amount.
current
string
default the plan marked current
The id of the plan the account is on now.
plan / defaultPlan
string
default the first plan with a badge
The chosen plan. Controlled or uncontrolled.
onPlanChange
(plan: string) => void
default —
Fires from the press or arrow key that chose a plan.
billing / defaultBilling
"monthly" | "yearly"
default "yearly"
The billing cycle when both are offered. Controlled or uncontrolled.
onBillingChange
(billing: UpgradeBilling) => void
default —
Fires from the press or arrow key that switched billing.
seats
number
default 3
Seats the per-seat price is multiplied by.
trialDays
number
default 14
Length of the free trial, in days; the track has a tick for each.
reminderDays
number
default 2
How many days before the first charge the reminder goes out.
now
Date | number
default defaultUpgradeNow
Today, for the dates on the timeline. Days are UTC days, so server and client print the same dates.
format
(amount: number) => string
default euros through Intl.NumberFormat
Prints every amount: prices, totals and the first charge.
state
"idle" | "pending" | "success" | "error"
default —
Controlled purchase state. Without it the wall follows the promise onPurchase returns.
onStateChange
(state: UpgradeState) => void
default —
Fires from the press that started a purchase, and again when it settles.
onPurchase
(selection: UpgradeSelection) => void | Promise<void>
default —
Starts the purchase with the plan, billing, seats, trial, amount and first-charge date. Return a promise to hold the button pending; reject with an Error to show its message.
onDismiss
() => void
default —
The Not now button in the corner. Hidden without it.
title
string
default "Upgrade to keep your dashboards live"
The heading and the region's accessible name.
subtitle
string
default —
The line under it: why the wall is here.
status
"ready" | "loading" | "error"
default "ready"
Loading draws placeholders; error offers Retry.
onRetry
() => void
default —
The Retry button of the error state.
sound
boolean
default false
Play a click on plan and billing changes and a chime when your purchase lands. Off unless asked for.
disabled
boolean
default false
Shows the wall but takes no input.
label
string
default —
The region's accessible name, when it should differ from the title.
className
string
default —
Classes for the root. It is h-[560px] by default; pass a height to change it — the columns scroll inside.