Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Addon Builder Pricing Block for React

A CRM sold as a base plan plus six add-ons that switch on and off in cells sharing hairlines, with the price per seat rolling big beside them and a sticky total bar on phones.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Let customers build their own package with this add-on builder, shown here for Holloway CRM. A compact header names the product and its base price, with a count of the add-ons that are on. Below it, a ruled grid whose cells share solid hairlines, with + marks on its corners: on the right, the Base plan at $24 a seat with what it includes, and under it your monthly price per seat in large type, rolling to each new sum with Sliding Number above one Shine Button, the block's only primary control. On the left, six add-on cells (Sequences, Dialer, Forecasting, Enrichment, Call AI and Territories) each show an icon, a price per seat and a one-line description, and switch on and off as Toggle buttons: a selected add-on gets a tinted cell, a filled check and a dark icon tile. The grid and the price sit side by side, so the first screen of a laptop holds the choices and the sum. On a phone the Base plan comes first, the add-ons follow in one column, and the price and the call to action ride a sticky bar at the foot of the screen. Built with Toggle, Sliding Number, Shine Button, Guides and Lucide icons, with CSS transitions only. For CRMs, helpdesks, hosting plans and any product sold as a base plan plus independent modules.

FAQ

How do I change the base plan and the add-ons?

Edit the constants at the top of the file. BASE_PLAN has the plan's name, per-seat price and features. ADDONS lists the modules: each has an id, a name, a one-line description, a per-seat price and a Lucide icon. STARTING lists the ids switched on when the page opens; empty it to start from the base plan alone. The total, the "3 of 6 add-ons on" count, the breakdown line and the button's label are all worked out from the selection, so they can't disagree. CURRENCY is the symbol written before every price.

How do I send the selection to checkout?

Both call to action buttons, the one in the grid and the one in the phone's bar, are real links: build their href from the selected ids, for example /checkout?plan=base&addons=sequences,call-ai, and let your server turn the plan and each add-on into a line item with its own price, so the invoice lists every module. Each is a ShineButton with render set to an a element and nativeButton={false}.

Is the add-on builder accessible to keyboard and screen reader users?

Yes. Each add-on cell is a toggle button that reports whether it's pressed, named by its own text: the add-on, its price "per seat per month" and its description. The cells sit in a group named "Add-ons, per seat per month"; Tab moves from cell to cell and Space or Enter switches one. After each change a polite live region says how many add-ons are on and the new price per seat, and the large price keeps its amount in text a screen reader can read while its digits roll. A selected add-on isn't marked by colour alone: it has a filled check and a dark icon tile.

How does it look on a phone?

The grid becomes a single column in the order a buyer works in: the Base plan, then the six add-ons, one cell each. The price in the grid is hidden, and a bar sticks to the foot of the screen while the section is in view with the price per seat, how many add-ons are on and the call to action, so the button is on the first screen however far down the add-ons the visitor is. The bar is position: sticky inside the section, so it leaves with it and never covers the next one.

How do I include an add-on that can't be removed?

Keep its id in STARTING and disable its toggle, so it shows as selected and counts in the price but can't be switched off: set disabled on that Toggle. Say why in its description ("Included with Forecasting"), since a disabled control isn't explained by its look alone.

When should I use an add-on builder instead of fixed pricing tiers?

Use an add-on builder when your product has distinct modules that different customers need in different combinations: the base price stays approachable and teams add only what they sell with. Fixed tiers work better when features depend on each other or most customers need the same bundle, since every extra choice slows the decision down.

  • Pro

    Bundle Deal Pricing

    Discounts and offers

    Two products priced alone beside a bundle of both: the bundle leads on a raised card with the sum of the parts struck through, the bundle price at display size, and a list of features that collapses on phones.

  • Pro

    An add-on marketplace for a CMS: an editor's pick in one compact band with its install button, over two shelves of add-on tiles that share their lines, each shelf a row to swipe on phones.

  • Pro

    A seat calculator: a slider sets the team size with its count riding the thumb, ticks at the 10, 25 and 50 seat discounts, shortcuts to them, and a panel that rolls the seat price and monthly total.

  • Pro

    A product-led split: a mock of the app built from our own components with numbered callouts on it, matching a 'what you get' list, beside the one plan as a card in a card with a monthly and yearly switch.

  • Pro

    Comparison Table Pricing

    Comparison tables

    Four plans compared feature by feature in one table whose hairlines meet the page rails, with a billing switch, a tinted popular column and, on a phone, a plan switch that keeps the feature column beside one plan.

  • Pro

    The canonical three-column pricing section for a team knowledge base: Personal, Team and Company cells under a monthly and yearly switch, each outlined by hairlines that overshoot its corners, the recommended plan raised, one plan at a time on phones.