KQ-1272 · PRICING/PLINTH

Pricing Plinth

A pricing table whose plans stand on plinths along a floor: choosing one lifts it on the glide spring while its plinth grows underneath, a spotlight pans across to it from above on the same spring and pools light on its head, the other plans step back, and the chosen plan's features check in one after another with each tick drawn on the flick spring. The Monthly/Yearly switch slides its thumb on snap and re-rolls every price on an odometer whose wheels each go round once more and settle on their new digits on glide, a beat apart, as a save tag swings in on its string on the recoil spring. Plans and billing are real radiogroups where the arrow keys move and choose and Home and End jump, a polite live region speaks the chosen plan and price once, and under reduced motion nothing rises, pans or spins while the light, ring and prices still change.

KQ-1272 · PRICING/PLINTH

Plans

Save 20%

Studio includes

Studio · $20 a month, billed monthly

Studio · $20 a month · billed monthly

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/pricing-plinth

Props

plans
PricingPlan[]
default defaultPricingPlans
The plans, left to right: { id, name, blurb?, monthly, yearly, features }, with monthly and yearly both as prices per month.
value / defaultValue
string | null
default the second plan
The chosen plan's id, controlled or initial; null chooses none and puts the light out.
onValueChange
(id: string) => void
default —
Fires from the press or the key that chose a plan.
cycle / defaultCycle
"monthly" | "yearly"
default "monthly"
The billing cycle, controlled or initial. Changing it re-rolls every price.
onCycleChange
(cycle: "monthly" | "yearly") => void
default —
Fires from the switch that changed it.
onConfirm
(id: string, cycle: "monthly" | "yearly") => void
default —
The Continue button, with the chosen plan and cycle.
rise
number
default 14
How high the chosen plan rises on its plinth, in px (up to 28); a hovered plan rises 30% of it.
spotlight
number
default 0.7
How strong the light on the chosen plan is, 0 to 1: the cone, the pool on its head and the lit plinth. 0 puts the spotlight out.
stagger
number
default 40
Delay between the odometer's wheels as prices re-roll, in ms.
title
string
default "Plans"
The heading, and the plans' accessible name.
monthlyLabel
string
default "Monthly"
The switch's first option.
yearlyLabel
string
default "Yearly"
The switch's second option.
saveLabel
string
default "Save N%"
The tag that swings in for yearly billing, by default the best saving across the plans; an empty string hides it.
actionLabel
(plan: PricingPlan) => string
default "Continue with {name}"
The Continue button's text for a plan. The button is always as wide as the longest.
currency
string
default "USD"
ISO 4217 code the prices are in.
locale
string
default "en-US"
Locale the prices are written in.
size
"sm" | "md" | "lg"
default "md"
The prices' type scale.
accent
string
default "var(--accent-bright)"
The light, the chosen ring, the tag and the ticks, any CSS colour.
sound
boolean
default false
Play a click on the switch, a chime as the saving swings in and a snap as a plan lands on its plinth.
disabled
boolean
default false
Nothing can be chosen or switched, and the table is drawn at reduced strength.
className
string
default —
Classes for the table's outer box.