Skip to content
Template Empire
Browse components

Pricing Add-on Builder

A free pricing add on builder React component for composing transparent plan totals in Next.js.

Configure your workspace

Add only what moves the work forward

Start with Studio, then choose the capabilities your team needs. Every selection is itemised before checkout.

Available add-ons

Customise

4px
0.35s
24px

Code

<PricingAddOnBuilder basePlan={basePlan} addOns={addOns} selectedIds={selectedIds} onSelectionChange={setSelectedIds} checkoutHref="/checkout" />

Pricing Add-on Builder is a free pricing component for Next.js and React, styled with Tailwind and animated with Motion. It presents one to eight optional products as native checkbox rows, keeps selections controlled by the parent, and calculates an itemised recurring total from the base plan and valid selected ids.

The summary stays sticky beside the catalogue on wide screens and returns to normal document flow before the layout becomes narrow. Checked rows state that they are included, every total is formatted through Intl.NumberFormat, and the complete new price is announced in a polite live region. Reduced motion keeps the same checkbox, calculation and checkout workflow while removing row lift, check drawing and digit travel.

Install

Add the @te registry to your components.json once:

{
  "registries": {
    "@te": "https://templateempire.io/r/{name}.json"
  }
}

Then install the component:

npx shadcn@latest add @te/pricing-add-on-builder

Usage

"use client";

import { useState } from "react";

import { PricingAddOnBuilder } from "@/components/pricing-add-on-builder";

const basePlan = {
  name: "Studio",
  price: 39,
  period: "month",
};

const addOns = [
  {
    id: "priority-support",
    name: "Priority support",
    description: "Replies from a product specialist within four working hours.",
    price: 12,
  },
  {
    id: "team-insights",
    name: "Team insights",
    description: "A clear weekly report from workspace activity.",
    price: 18,
  },
];

export default function PricingPage() {
  const [selectedIds, setSelectedIds] = useState<string[]>([]);

  return (
    <PricingAddOnBuilder
      basePlan={basePlan}
      addOns={addOns}
      selectedIds={selectedIds}
      onSelectionChange={setSelectedIds}
      checkoutHref="/checkout"
    />
  );
}

Props

PropTypeDefaultDescription
basePlan{ name: string; price: number; period: string }requiredBase recurring plan and price in minor-free display units.
addOnsReadonlyArray<{ id: string; name: string; description: string; price: number }>requiredOne to eight optional add-ons with unique ids, descriptions and non-negative prices.
selectedIdsReadonlyArray<string>[]Controlled selected add-on ids. Unknown and repeated ids are ignored.
currencystring"GBP"ISO 4217 currency code passed to Intl.NumberFormat. Invalid values fall back to GBP.
localestring"en-GB"Formatting locale passed to Intl.NumberFormat with an en-GB fallback.
density"comfortable" | "compact""comfortable"Controls the vertical spacing inside each add-on row.
selectionLiftnumber4Selected-row lift in CSS pixels, clamped to the range 0 to 10.
totalDurationnumber0.35Total crossfade duration in seconds, clamped to the range 0 to 0.8.
summarySide"left" | "right""right"Wide-screen sticky-summary position. Both options stack on narrow screens.
radiusnumber24Add-on row and summary radius in CSS pixels, clamped to 0 to 44.
onSelectionChange(ids: string[]) => voidrequiredReceives the next controlled selection in original catalogue order.
checkoutHrefstringrequiredMeaningful relative or HTTP checkout destination rendered as a real anchor.
classNamestringundefinedAdditional classes merged onto the section.

Customisation

Pricing Add-on Builder exposes three Tier 3 CSS variables. The accent token colours checked controls and the total, the panel token controls row and summary surfaces, and the divider token separates the itemised total. Density and motion geometry remain available as typed props:

<div
  style={{
    "--addon-builder-accent": "var(--ring)",
    "--addon-builder-panel": "var(--surface)",
    "--addon-builder-divider": "var(--border)",
  }}
>
  <PricingAddOnBuilder
    basePlan={basePlan}
    addOns={addOns}
    selectedIds={selectedIds}
    onSelectionChange={setSelectedIds}
    checkoutHref="/checkout"
    density="compact"
    selectionLift={6}
    totalDuration={0.25}
    summarySide="left"
    radius={18}
  />
</div>

Frequently asked questions

Is Pricing Add-on Builder free for commercial use?
Yes. Pricing Add-on Builder is MIT licensed, so you can use it in personal and commercial projects without attribution.
Is the add-on builder accessible and performant?
Yes. It uses a labelled fieldset, native checkboxes, visible focus rings, a semantic itemised summary and a polite total announcement. Motion is limited to transforms, opacity and the check path, while reduced motion updates every state instantly.
How can I customise the pricing add-on builder?
Use the density, selectionLift, totalDuration, summarySide and radius props for layout and motion geometry. Override the three component CSS variables to retheme checked controls, panel surfaces and summary dividers without changing selection logic.

Related components

Want the full pricing page this belongs to?Template Empire builds complete Next.js templates with pricing journeys, conversion sections and the same accessible motion system. Browse the templates that pair with these free components.Explore Template Empire templates