DHxWhy

Plan Finder Pricing Comparison Table

Pricing 24

About

Plan Finder Pricing Comparison Table for React and Tailwind CSS (shadcn/ui) matches features to plans. It is built to find the cheapest plan that covers your needs. Includes feature checkboxes, group headers, a moving spotlight and a sales fallback. Controlled needs, recommendation and selection callbacks; keyboard support, reduced motion, light and dark themes. Use it for SaaS pricing and upgrades. The included demo uses sample plans; the component makes no requests. Requires React and lucide-react, with no animation library.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Plan Finder Pricing Comparison Table to your project and fits it to your theme.

Code

How Plan Finder Pricing Comparison Table is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";

import * as React from "react";
import { Pause, RotateCcw } from "lucide-react";
import { PlanFinderPricingTable } from "@/components/ui/plan-finder-pricing-table";
import type { PlanFinderFeature, PlanFinderPlan } from "@/components/ui/plan-finder-pricing-table";

export const PLAN_FINDER_PLANS: PlanFinderPlan[] = [
  { id: "free", name: "Free", price: 0, cta: "Start free" },
  { id: "pro", name: "Pro", price: 29, cta: "Choose Pro" },
  { id: "business", name: "Business", price: 59, cta: "Choose Business" },
];

export const PLAN_FINDER_FEATURES: PlanFinderFeature[] = [
  { id: "boards", label: "Shared boards", group: "Create together", availability: { free: true, pro: true, business: true } },
  { id: "history", label: "Version history", group: "Create together", availability: { free: "7 days", pro: "90 days", business: "Unlimited" } },
  { id: "automations", label: "Automations", group: "Workflow & control", availability: { free: false, pro: true, business: true } },
  { id: "sso", label: "SAML SSO", group: "Workflow & control", availability: { free: false, pro: false, business: true } },
  { id: "region", label: "Dedicated region", group: "Workflow & control", availability: { free: false, pro: false, business: false } },
];

export default function PlanFinderPricingTableDemo({ autoplay = true }: { autoplay?: boolean }) {
  const [needs, setNeeds] = React.useState([] as string[]);
  const [reduced, setReduced] = React.useState(true);
  const [paused, setPaused] = React.useState(false);
  const [finished, setFinished] = React.useState(false);
  const [run, setRun] = React.useState(0);
  const [choice, setChoice] = React.useState("");
  const playing = autoplay && !reduced && !paused && !finished;

  React.useEffect(() => {
    const media = window.matchMedia("(prefers-reduced-motion: reduce)");
    const sync = () => setReduced(media.matches);
    sync();
    media.addEventListener("change", sync);
    return () => media.removeEventListener("change", sync);
  }, []);

  React.useEffect(() => {
    if (!playing) return;
    const steps: [number, () => void][] = [
      [1200, () => setNeeds(["boards"])],
      [2800, () => setNeeds(["boards", "automations"])],
      [4600, () => setNeeds(["boards", "automations", "sso"])],
      [6200, () => setFinished(true)],
    ];
    const timers = steps.map(([delay, action]) => window.setTimeout(action, delay));
    return () => timers.forEach((timer) => window.clearTimeout(timer));
  }, [playing, run]);

  return (
    <main data-plan-finder-demo data-autoplay={autoplay} data-playing={playing} className="flex min-h-svh w-full items-center justify-center bg-background px-4 py-3 text-foreground">
      <div className="w-full max-w-[692px]">
        <header className="mb-3 px-1">
          <div className="mb-1.5 flex items-center justify-between text-[9px] font-medium uppercase tracking-[0.18em] text-muted-foreground"><span>Plan finder</span><span className="rounded-full border border-border px-2 py-0.5 text-[8px] tracking-wider">Sample pricing</span></div>
          <h1 className="text-[25px] font-semibold leading-7 tracking-tight">A plan that checks your boxes.</h1>
          <p className="mt-1 text-xs text-muted-foreground">Choose your must-haves. We’ll find the fit.</p>
        </header>
        <div onPointerDownCapture={() => setPaused(true)} onKeyDownCapture={() => setPaused(true)}>
          <PlanFinderPricingTable plans={PLAN_FINDER_PLANS} features={PLAN_FINDER_FEATURES} needs={needs} onNeedsChange={(next) => { setPaused(true); setNeeds(next); setChoice(""); }} onSelect={(id) => { setPaused(true); setChoice(PLAN_FINDER_PLANS.find((plan) => plan.id === id)?.name ?? id); }} />
        </div>
        <footer className="mt-2 flex min-h-6 items-center justify-between gap-3 px-1 text-[10px] text-muted-foreground">
          <p role="status" aria-live="polite" data-demo-choice>{choice ? `${choice} selected · sample only` : "Sample plans · billed monthly"}</p>
          {autoplay && !reduced ? <button type="button" data-demo-playback onClick={() => {
            if (playing) setPaused(true);
            else { setNeeds([]); setChoice(""); setPaused(false); setFinished(false); setRun((value) => value + 1); }
          }} className="flex items-center gap-1.5 rounded px-1 py-1 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">{playing ? <Pause aria-hidden="true" className="size-3" /> : <RotateCcw aria-hidden="true" className="size-3" />}{playing ? "Pause demo" : "Replay demo"}</button> : <span>Pick what matters to you</span>}
        </footer>
      </div>
    </main>
  );
}

Dependencies

More by DHxWhy

View all
  • Sun Moon Dark Mode Theme Toggle

    Sun Moon Dark Mode Theme Toggle

    186
  • Live Notification Feed

    Live Notification Feed

    110
  • Country Flags Globe

    Country Flags Globe

    110
  • Airplane Window Gallery

    Airplane Window Gallery

    96
  • Domino Scroll Image Gallery

    Domino Scroll Image Gallery

    93
  • QR Code Scan Login Form with Password Fallback

    QR Code Scan Login Form with Password Fallback

    82
  • Constellation Image Gallery

    Constellation Image Gallery

    80
  • Ferris Wheel Image Gallery

    Ferris Wheel Image Gallery

    73

More in Pricing

View all
  • Pricing Section

    Pricing Section

    582
  • Pricing Cards

    Pricing Cards

    31
  • Pricing Card

    Pricing Card

    535
  • Pricing Section

    Pricing Section

    173
  • pricing section

    pricing section

    158
  • Single Pricing Card

    Single Pricing Card

    795
  • Pricing

    Pricing

    125
  • Glowing Pricing Tiers

    Glowing Pricing Tiers

    45