PlanPicker
Compare plans, see the price difference, and switch.
SourcePackage @weft-js/warp
Preview
tsx
import { state } from '@weft-js/core'import { PlanPicker, Toaster } from '@weft-js/warp'import type { BillingPlan } from '@weft-js/warp'export function Team() { const current = state('team') const change = async (plan: { id: string }) => { await wait(700) current.value = plan.id } return ( <> <PlanPicker plans={PLANS} current={current.value} seats={8} daysLeft={9} losses={plan => (plan.id === 'hobby' ? ['Preview environments', '7 of your 10 seats'] : [])} onChange={change} /> <Toaster /> </> )}const PLANS: BillingPlan[] = [ { id: 'hobby', name: 'Hobby', price: 0, description: 'For side projects.', features: ['3 seats', '100 deploys a month', '1 region'] }, { id: 'team', name: 'Team', price: 24, description: 'For product teams.', features: ['10 seats', 'Unlimited deploys', '5 regions', 'Preview environments'] }, { id: 'scale', name: 'Scale', price: 64, description: 'For many teams.', features: ['50 seats', 'Unlimited deploys', 'Every region', 'SSO and audit export'] },]const wait = (ms: number) => new Promise<void>(done => { setTimeout(done, ms) })Installation
npm install @weft-js/warpUsage
tsx
import { PlanPicker } from '@weft-js/warp'Accessibility
- This has no shortcuts of its own: controls inside it use Tab, Enter and Space as usual, and warp's parts keep their roles and labels.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
plans | BillingPlan[] | — | The plans to compare, one card each. |
current | string | — | The id of the plan the workspace is on. |
selected | State<string> | — | The checked card, when something else needs to set it. |
interval | State<BillingInterval> | — | Monthly or yearly, when you want to own it. |
seats | number | — | Seats, for the price. |
daysLeft | number | — | Days left in this period, for the proration. |
periodDays | number | 30 | The length of a period in days. |
currency | string | — | The ISO 4217 code prices are shown in, such as EUR. |
locale | string | — | The language and region used to format values. |
preview | ((plan: BillingPlan, interval: BillingInterval) => Proration | Promise<P… | — | Your server's proration, to replace the built-in one. |
losses | ((plan: BillingPlan) => string[]) | — | What stops working on a downgrade. |
| Event | Type | Default | Description |
|---|---|---|---|
onChange | (plan: BillingPlan, interval: BillingInterval) => string | void | Promis… | — | Makes the change. Resolve with a message to keep the dialog open and show it. |
Parts
Every element carries a stable name, so you can style it from your own CSS: [data-scope="stack"] [data-part="grid"]
gridnameradiopricetotal