Pricing
v1.0.18Updated 19 Oct 2026Pricing section with tier cards, billing toggles and comparison tables. Copy-paste block; baked-in demo content (edit the JSX to customise).
Preview
Live · 13 stories▸Why this is recommendedpricingplanstiersbilling+4
Pricing — three tier.
- ✓Landing pages
- ✓Pricing pages
- ✓Marketing pages
- Three-tier, monthly/annual toggle, comparison-table, single-plan and feature-list layouts
- Highlighted "popular" tier
- i18n: prices and counts format through the locale layer (LocaleProvider / useB69Locale) — the ฿/THB demo currency stays baked per the section-block contract
- Configured entirely by props, never by editing the vendored file: `plans` is the single source of truth (name, blurb, monthly, yearly, features, cta, ctaHref, popular) and drives every layout
- The comparison table DERIVES its column names, prices and popular column from `plans`; `compareGroups` carries only feature rows, index-aligned, and a short row renders the missing cells as not-included. Up to 1.0.13 COMPARE_PRICES kept a second copy of the tier prices, so the table and the cards could silently disagree (condo69 fb_bc8045e2 / fb_f8fba1de)
- Prices have NO default: with nothing passed a block renders its heading, eyebrow and subcopy plus a short empty note from labels (emptyPlans / emptyCompare / emptyAddons / emptyUsage) - never an empty grid, an empty table body, a baht-undefined or a NaN
- No dead controls: a plan button renders ONLY when the plan has a ctaHref or the family has an onPlanSelect (destination to anchor, handler to real type=button, neither to nothing). Each block CTA follows the same rule through ctaHref / onCtaClick
- Client-side routing: pass `linkComponent` (next/link, React Router Link) and every anchor renders through the host app link component instead of reloading the document (fb_bf7dc63a)
- currencySymbol replaces the baked baht sign everywhere, animated totals included, so a consumer outside Thailand is not stuck billing in baht; digit grouping still follows LocaleProvider
- ✕In-app billing settings
Install
Ask your agent, or call the MCP tool directly. The resolved bundle is written into your project.
Usage
Tick variants in the left menu — each adds a tab with that variant’s real story source, the same code the preview above renders.
Props
classNameOptional wrapper class override
—labelsOverride every built-in display string across the pricing family (eyebrows, headings, subcopy, billing-period toggle, per-plan chrome, button text, footnotes, aria-labels) for i18n or white-labelling. Merged over DEFAULT_PRICING_LABELS.
—plansThe plans on sale: [{ id?, name, blurb?, monthly, yearly?, features?, cta?, ctaHref?, popular? }]. Drives every layout; the single-plan blocks price plans[0]. Defaults to [] - a price is a commercial fact nobody proofreads, so a vendored copy shows labels.emptyPlans until you pass yours (fb_bc8045e2).
—compareGroupsPricingComparisonTable feature rows: [{ group, rows: [{ label, values }] }], each row index-aligned with `plans`. Column headers, prices and the popular column come from `plans`, never from here. Defaults to [].
—addonsPricingWithToggleAndAddons modules: [{ id?, name, blurb?, monthly, yearly? }], priced on top of plans[0]. Defaults to [] and the list is replaced by labels.emptyAddons.
—featureGroupsPricingWithFeatureList checklist: [{ title, items }]. Defaults to [] and the list is omitted entirely.
—enterpriseFeaturesPricingEnterpriseSplit bullets inside the contact-sales panel. Defaults to [].
—perSeatPricePricingUsageBased: what one seat costs per month. No default - without it (or invoiceBlockPrice) the block shows labels.emptyUsage instead of a calculator that quotes a price nobody set.
—invoiceBlockPricePricingUsageBased: what one block of invoices costs per month. No default, same reason as perSeatPrice.
—invoiceBlockSizePricingUsageBased: how many invoices one block buys. Defaults to 500; the matching copy spells the number out, so override labels.usageInvoicesPrice / usageInvoicesSlider with it.
—currencySymbolThe symbol in front of every amount, the animated totals included. Defaults to the baht sign (byte-identical to what these blocks shipped); one prop, so a card and a total cannot disagree.
—onPlanSelectWhat a plan button does. On its own it makes the button a real type=button; with plan.ctaHref it fires before navigation. With neither, no plan button renders.
—ctaHrefWhere the block own CTA goes (add-on summary, usage estimate, enterprise contact sales). Unwired, it renders nothing.
—onCtaClickWhat the block own CTA does; receives the click event so a routed host can preventDefault (fb_bf7dc63a).
—linkComponentThe host link component (next/link, React Router Link) for every anchor this family renders. Defaults to a plain anchor, which in a routed app means a full document reload (fb_bf7dc63a).
—