À la Carte Plan Builder React component
A build-your-own plan: pick modules, set seats and watch the total update, with bundle discounts that unlock as you add more, modules that bring their dependencies along, a yearly switch and a live summary.
About the À la Carte Plan Builder component
À la Carte Plan Builder lets customers assemble their own plan instead of choosing from fixed tiers: tick the modules they need, set the number of seats and see the price update line by line.
Bundle discounts reward adding more, with a progress track showing how close the next one is. Modules can depend on each other, so choosing SSO brings the audit log with it, and removing the audit log takes SSO away.
When to use it
Use it for modular SaaS, agency retainers, insurance or telecom add-ons and any product sold as building blocks.
With only two or three options, fixed plans are quicker to choose from.
Installation
Add the À la Carte Plan Builder component to your project with the shadcn CLI. It lands in components/a-la-carte-plan-builder.tsx as plain React + Tailwind CSS source you own and can edit.
npx shadcn@latest add @reactframe/a-la-carte-plan-builderOr copy the source by hand and install its dependencies:
npm install clsx tailwind-mergeProps
<ALaCartePlanBuilder /> accepts 11 props, all optional. It also accepts the usual <div> attributes, like className, style, id and aria-*, and passes them to its root element.
| Prop | Type | Default |
|---|---|---|
| theme | "dark" | "light" | "dark" |
| title | string | "Build your plan" |
| subtitle | string | "Pay only for what your team uses. Add more and the whole plan gets cheaper." |
| modules | { id: string; name: string; description: string; price: number; perSeat?: boolean; required?: boolean; requires?: string[] }[] | DEFAULT_MODULES |
| tiers | { count: number; discount: number }[] | DEFAULT_TIERS |
| yearlyDiscount Discount for paying yearly (0–1), on top of the bundle discount. | number | 0.15 |
| defaultSelected | string[] | ["automations", "analytics"] |
| defaultSeats | number | 8 |
| maxSeats | number | 250 |
| currency | string | "$" |
| onCheckout | (plan: { modules: string[]; seats: number; yearly: boolean; monthly: number; }) => void | — |
- theme"dark" | "light"Default: "dark"
- titlestringDefault: "Build your plan"
- subtitlestringDefault: "Pay only for what your team uses. Add more and the whole plan gets cheaper."
- modules{ id: string; name: string; description: string; price: number; perSeat?: boolean; required?: boolean; requires?: string[] }[]Default: DEFAULT_MODULES
- tiers{ count: number; discount: number }[]Default: DEFAULT_TIERS
- yearlyDiscount
Discount for paying yearly (0–1), on top of the bundle discount.
numberDefault: 0.15 - defaultSelectedstring[]Default: ["automations", "analytics"]
- defaultSeatsnumberDefault: 8
- maxSeatsnumberDefault: 250
- currencystringDefault: "$"
- onCheckout(plan: { modules: string[]; seats: number; yearly: boolean; monthly: number; }) => void
npm dependencies
Installed for you by the shadcn CLI.
À la Carte Plan Builder FAQ
- How do the discounts work?
- tiers lists how many optional modules unlock each discount, and the highest tier reached applies to the whole subtotal. The yearly discount applies after that.
- What are dependencies?
- requires lists the module ids a module needs. They're added with it, and removing one also removes whatever depends on it.
- Can something be always included?
- Yes, required: true keeps a module in the plan and doesn't count it toward bundle tiers.
- How do I get the result?
- onCheckout receives the chosen module ids, seats, whether it's yearly and the monthly total.