Plan Group
billui/plan-groupFreeComponent
A container for displaying multiple pricing plans with a monthly/yearly toggle.
Live preview
live · rendered by the registry
Rendered by billui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://billui.com/r/plan-group.jsonSource
1"use client";23import { cva, type VariantProps } from "class-variance-authority";4import * as React from "react";56import { cn } from "@/lib/utils";7import { PlanCardPrice } from "./plan-card";89const planGroupVariants = cva("w-full", {10 variants: {11 layout: {12 horizontal: "grid gap-6",13 vertical: "flex flex-col gap-6",14 },15 columns: {16 2: "md:grid-cols-2",17 3: "lg:grid-cols-3",18 4: "lg:grid-cols-2 xl:grid-cols-4",19 },20 },21 defaultVariants: {22 layout: "horizontal",23 columns: 2,24 },25});2627type BillingPeriod = "month" | "year";2829interface PlanGroupContextValue {30 period: BillingPeriod;31 setPeriod: (period: BillingPeriod) => void;32}3334const PlanGroupContext = React.createContext<PlanGroupContextValue | null>(35 null,36);3738function usePlanGroup() {39 const context = React.useContext(PlanGroupContext);40 if (!context) {41 throw new Error("usePlanGroup must be used within a PlanGroup");42 }43 return context;44}4546interface PlanGroupProps47 extends React.HTMLAttributes<HTMLDivElement>,48 VariantProps<typeof planGroupVariants> {49 defaultPeriod?: BillingPeriod;50 onPeriodChange?: (period: BillingPeriod) => void;51}5253const PlanGroup = React.forwardRef<HTMLDivElement, PlanGroupProps>(54 (55 {56 className,57 layout,58 columns,59 defaultPeriod = "month",60 onPeriodChange,61 children,62 ...props63 },64 ref,65 ) => {66 const [period, setPeriodState] =67 React.useState<BillingPeriod>(defaultPeriod);6869 const setPeriod = React.useCallback(70 (newPeriod: BillingPeriod) => {71 setPeriodState(newPeriod);72 onPeriodChange?.(newPeriod);73 },74 [onPeriodChange],75 );7677 return (78 <PlanGroupContext.Provider value={{ period, setPeriod }}>79 <div ref={ref} className={cn("space-y-8", className)} {...props}>80 {children}81 </div>82 </PlanGroupContext.Provider>83 );84 },85);86PlanGroup.displayName = "PlanGroup";8788const PlanGroupHeader = React.forwardRef<89 HTMLDivElement,90 React.HTMLAttributes<HTMLDivElement>91>(({ className, ...props }, ref) => (92 <div93 ref={ref}94 className={cn("flex flex-col items-center gap-4 text-center", className)}95 {...props}96 />97));98PlanGroupHeader.displayName = "PlanGroupHeader";99100const PlanGroupTitle = React.forwardRef<101 HTMLHeadingElement,102 React.HTMLAttributes<HTMLHeadingElement>103>(({ className, ...props }, ref) => (104 <h2105 ref={ref}106// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from billui
All 13 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Animated Usage Cardanimated-usage-card | billui | Components | Free | 2 deps | |
| Billing Addressbilling-address | billui | Components | Free | no deps | |
| Card Iconscard-icons | billui | Components | Free | 1 dep | |
| Card Inputcard-input | billui | Components | Free | no deps | |
| Invoice Cardinvoice-card | billui | Components | Free | 2 deps | |
| Payment Methodpayment-method | billui | Components | Free | 2 deps | |
| Plan Cardplan-card | billui | Components | Free | 2 deps | |
| Pricing Tablepricing-table | billui | Components | Free | 2 deps |
