Web InnoventixFreeCode

FAQ Combo Pricing

Original · free

pricing with an FAQ below

byWeb InnoventixReact + Tailwind
pricexfaqcombopricing
Open

Copy prompt gives Claude Code, Cursor or v0 a ready-to-paste prompt that recreates this exact component.

npx shadcn@latest add https://webinnoventix.com/r/pricex-faq-combo.json
pricex-faq-combo.tsx
"use client";

import { useState } from "react";
import { motion, AnimatePresence, useReducedMotion } from "motion/react";

type BillingCycle = "monthly" | "annual";

interface Tier {
  id: string;
  name: string;
  tagline: string;
  monthly: number;
  annual: number;
  cta: string;
  features: string[];
  popular?: boolean;
}

interface Faq {
  q: string;
  a: string;
}

const TIERS: Tier[] = [
  {
    id: "starter",
    name: "Starter",
    tagline: "For individuals shipping their first automations.",
    monthly: 15,
    annual: 12,
    cta: "Start free",
    features: [
      "Up to 3 active workflows",
      "2,000 tasks per month",
      "Core integrations library",
      "7-day run history",
      "Community support",
    ],
  },
  {
    id: "team",
    name: "Team",
    tagline: "For growing teams that need control and speed.",
    monthly: 39,
    annual: 31,
    cta: "Start 14-day trial",
    popular: true,
    features: [
      "Everything in Starter",
      "Unlimited workflows",
      "50,000 tasks per month",
      "Advanced branching & error handling",
      "Role-based access controls",
      "90-day run history",
      "Priority email support",
    ],
  },
  {
    id: "scale",
    name: "Scale",
    tagline: "For organizations with security and SLA needs.",
    monthly: 89,
    annual: 71,
    cta: "Contact sales",
    features: [
      "Everything in Team",
      "Unlimited tasks",
      "SSO & SCIM provisioning",
      "Audit logs & data residency",
      "99.9% uptime SLA",
      "Dedicated success manager",
    ],
  },
];

const FAQS: Faq[] = [
  {
    q: "Can I switch plans or cancel at any time?",
    a: "Yes. Upgrades take effect immediately and we prorate the difference, so you only pay for what you use. Downgrades and cancellations apply at the end of your current billing period, and you keep full access until then.",
  },
  {
    q: "What exactly counts as a task?",
    a: "A task is a single automated action a workflow performs, such as sending a message, updating a record, or calling an external API. Steps that only route or filter data do not count, so most teams use far fewer tasks than they expect.",
  },
  {
    q: "Is there a free trial, and do I need a card?",
    a: "Every paid plan includes a 14-day trial with no credit card required. You get the full Team feature set during the trial so you can test real workflows before committing to anything.",
  },
  {
    q: "How much do I save with annual billing?",
    a: "Annual billing is roughly 20% cheaper than paying month to month. The savings are shown live on each plan when you switch the toggle, and you are charged once per year instead of every month.",
  },
  {
    q: "How is my data secured?",
    a: "All data is encrypted in transit and at rest, and we run on SOC 2 Type II certified infrastructure. On the Scale plan you can add audit logs, single sign-on, and choose the region where your data is stored.",
  },
  {
    q: "Do you offer discounts for startups or nonprofits?",
    a: "We do. Registered nonprofits and early-stage startups can apply for up to 30% off any plan. Reach out to our team with a bit of context and we will get you set up within a day or two.",
  },
];

function CheckIcon({ className }: { className?: string }) {
  return (
    <svg
      className={className}
      viewBox="0 0 20 20"
      fill="none"
      stroke="currentColor"
      strokeWidth={2}
      strokeLinecap="round"
      strokeLinejoin="round"
      aria-hidden="true"
    >
      <path d="M4 10.5l3.5 3.5L16 5.5" />
    </svg>
  );
}

function SparkIcon({ className }: { className?: string }) {
  return (
    <svg className={className} viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
      <path d="M12 2l1.9 5.6L19.5 9l-4.6 3.3L16.4 18 12 14.7 7.6 18l1.5-5.7L4.5 9l5.6-1.4z" />
    </svg>
  );
}

function ChevronIcon({ className }: { className?: string }) {
  return (
    <svg
      className={className}
      viewBox="0 0 20 20"
      fill="none"
      stroke="currentColor"
      strokeWidth={2}
      strokeLinecap="round"
      strokeLinejoin="round"
      aria-hidden="true"
    >
      <path d="M5 7.5l5 5 5-5" />
    </svg>
  );
}

function formatUsd(value: number): string {
  return `$${value.toLocaleString("en-US")}`;
}

export default function PricexFaqCombo() {
  const reduce = useReducedMotion();
  const [cycle, setCycle] = useState<BillingCycle>("annual");
  const [openFaq, setOpenFaq] = useState<number | null>(0);

  const enter = (delay: number) =>
    reduce
      ? {}
      : {
          initial: { opacity: 0, y: 22 },
          whileInView: { opacity: 1, y: 0 },
          viewport: { once: true, margin: "-80px" },
          transition: { duration: 0.5, delay, ease: [0.22, 1, 0.36, 1] as const },
        };

  return (
    <section className="relative w-full overflow-hidden bg-gradient-to-b from-slate-50 via-white to-slate-50 py-24 text-slate-900 sm:py-32 dark:from-slate-950 dark:via-slate-950 dark:to-slate-900 dark:text-slate-100">
      <style>{`
        @keyframes pfc-blob-drift {
          0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
          50% { transform: translate3d(0, -28px, 0) scale(1.08); }
        }
        @keyframes pfc-badge-shimmer {
          0% { background-position: -160% 0; }
          100% { background-position: 260% 0; }
        }
        .pfc-blob { animation: pfc-blob-drift 14s ease-in-out infinite; }
        .pfc-blob-slow { animation: pfc-blob-drift 20s ease-in-out infinite; }
        .pfc-shimmer {
          background-size: 220% 100%;
          animation: pfc-badge-shimmer 3.2s linear infinite;
        }
        @media (prefers-reduced-motion: reduce) {
          .pfc-blob, .pfc-blob-slow, .pfc-shimmer { animation: none !important; }
        }
      `}</style>

      {/* decorative background */}
      <div className="pointer-events-none absolute inset-0 overflow-hidden" aria-hidden="true">
        <div className="pfc-blob absolute -left-24 top-10 h-72 w-72 rounded-full bg-indigo-400/20 blur-3xl dark:bg-indigo-500/20" />
        <div className="pfc-blob-slow absolute -right-16 top-1/3 h-80 w-80 rounded-full bg-violet-400/20 blur-3xl dark:bg-violet-600/20" />
        <div className="absolute inset-0 bg-[radial-gradient(circle_at_center,rgba(99,102,241,0.05),transparent_60%)]" />
      </div>

      <div className="relative mx-auto max-w-6xl px-6">
        {/* header */}
        <motion.div className="mx-auto max-w-2xl text-center" {...enter(0)}>
          <span className="inline-flex items-center gap-2 rounded-full border border-indigo-200 bg-indigo-50 px-4 py-1.5 text-xs font-semibold uppercase tracking-wider text-indigo-700 dark:border-indigo-500/30 dark:bg-indigo-500/10 dark:text-indigo-300">
            <SparkIcon className="h-3.5 w-3.5" />
            Nimbus pricing
          </span>
          <h2 className="mt-6 text-4xl font-bold tracking-tight text-slate-900 sm:text-5xl dark:text-white">
            Automation that scales with you
          </h2>
          <p className="mt-4 text-lg text-slate-600 dark:text-slate-400">
            Start free, upgrade when your workflows grow. Simple, predictable pricing with no
            per-seat surprises and no long-term lock-in.
          </p>
        </motion.div>

        {/* billing toggle */}
        <motion.div className="mt-10 flex flex-col items-center gap-3" {...enter(0.06)}>
          <div
            role="group"
            aria-label="Billing period"
            className="relative flex w-72 rounded-full border border-slate-200 bg-white p-1 shadow-sm dark:border-slate-700 dark:bg-slate-900"
          >
            <span
              aria-hidden="true"
              className="absolute inset-y-1 left-1 w-[calc(50%-0.25rem)] rounded-full bg-gradient-to-r from-indigo-600 to-violet-600 shadow-lg shadow-indigo-500/30"
              style={{
                transform: cycle === "annual" ? "translateX(100%)" : "translateX(0)",
                transition: reduce ? "none" : "transform 0.32s cubic-bezier(0.22,1,0.36,1)",
              }}
            />
            <button
              type="button"
              onClick={() => setCycle("monthly")}
              aria-pressed={cycle === "monthly"}
              className={`relative z-10 flex-1 rounded-full px-4 py-2 text-sm font-semibold transition-colors ${
                cycle === "monthly"
                  ? "text-white"
                  : "text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200"
              }`}
            >
              Monthly
            </button>
            <button
              type="button"
              onClick={() => setCycle("annual")}
              aria-pressed={cycle === "annual"}
              className={`relative z-10 flex-1 rounded-full px-4 py-2 text-sm font-semibold transition-colors ${
                cycle === "annual"
                  ? "text-white"
                  : "text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200"
              }`}
            >
              Annual
            </button>
          </div>
          <span className="inline-flex items-center gap-1.5 rounded-full bg-emerald-100 px-3 py-1 text-xs font-semibold text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300">
            <SparkIcon className="h-3 w-3" />
            Save 20% with annual billing
          </span>
        </motion.div>

        {/* pricing cards */}
        <div className="mt-14 grid grid-cols-1 gap-6 lg:grid-cols-3 lg:items-stretch">
          {TIERS.map((tier, i) => {
            const price = cycle === "annual" ? tier.annual : tier.monthly;
            const yearlyTotal = tier.annual * 12;
            return (
              <motion.div
                key={tier.id}
                className={`relative flex flex-col rounded-3xl border p-8 ${
                  tier.popular
                    ? "border-indigo-300 bg-white shadow-2xl shadow-indigo-500/10 lg:-my-4 lg:pb-12 dark:border-indigo-500/40 dark:bg-slate-900"
                    : "border-slate-200 bg-white/70 shadow-sm dark:border-slate-800 dark:bg-slate-900/60"
                }`}
                {...enter(0.1 + i * 0.08)}
              >
                {tier.popular && (
                  <span className="pfc-shimmer absolute -top-3 left-1/2 -translate-x-1/2 rounded-full bg-[linear-gradient(110deg,#4f46e5,45%,#a78bfa,55%,#4f46e5)] px-4 py-1 text-xs font-bold uppercase tracking-wide text-white shadow-lg">
                    Most popular
                  </span>
                )}

                <h3 className="text-lg font-semibold text-slate-900 dark:text-white">
                  {tier.name}
                </h3>
                <p className="mt-2 min-h-[2.5rem] text-sm text-slate-600 dark:text-slate-400">
                  {tier.tagline}
                </p>

                <div className="mt-6 flex items-baseline gap-1">
                  <span className="text-5xl font-bold tracking-tight text-slate-900 dark:text-white">
                    {formatUsd(price)}
                  </span>
                  <span className="text-sm font-medium text-slate-500 dark:text-slate-400">
                    /mo
                  </span>
                </div>
                <p className="mt-1 h-5 text-xs text-slate-500 dark:text-slate-400">
                  {cycle === "annual"
                    ? `Billed ${formatUsd(yearlyTotal)} per year`
                    : "Billed monthly"}
                </p>

                <button
                  type="button"
                  className={`mt-6 w-full rounded-xl px-5 py-3 text-sm font-semibold transition-transform duration-200 hover:-translate-y-0.5 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 ${
                    tier.popular
                      ? "bg-gradient-to-r from-indigo-600 to-violet-600 text-white shadow-lg shadow-indigo-500/30 hover:shadow-xl hover:shadow-indigo-500/40"
                      : "border border-slate-300 bg-white text-slate-900 hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-800 dark:text-white dark:hover:bg-slate-700"
                  }`}
                >
                  {tier.cta}
                </button>

                <ul className="mt-8 space-y-3.5" role="list">
                  {tier.features.map((feature) => (
                    <li key={feature} className="flex items-start gap-3">
                      <span className="mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-emerald-100 text-emerald-600 dark:bg-emerald-500/15 dark:text-emerald-400">
                        <CheckIcon className="h-3.5 w-3.5" />
                      </span>
                      <span className="text-sm text-slate-700 dark:text-slate-300">
                        {feature}
                      </span>
                    </li>
                  ))}
                </ul>
              </motion.div>
            );
          })}
        </div>

        <motion.p
          className="mt-8 text-center text-sm text-slate-500 dark:text-slate-400"
          {...enter(0.1)}
        >
          All plans include unlimited team members, 250+ integrations, and a 30-day money-back
          guarantee.
        </motion.p>

        {/* FAQ */}
        <div className="mx-auto mt-24 max-w-3xl">
          <motion.div className="text-center" {...enter(0)}>
            <h3 className="text-3xl font-bold tracking-tight text-slate-900 sm:text-4xl dark:text-white">
              Frequently asked questions
            </h3>
            <p className="mt-3 text-slate-600 dark:text-slate-400">
              Everything you need to know about plans and billing. Still stuck?{" "}
              <span className="font-semibold text-indigo-600 dark:text-indigo-400">
                Talk to our team.
              </span>
            </p>
          </motion.div>

          <motion.div
            className="mt-10 divide-y divide-slate-200 overflow-hidden rounded-2xl border border-slate-200 bg-white dark:divide-slate-800 dark:border-slate-800 dark:bg-slate-900/60"
            {...enter(0.06)}
          >
            {FAQS.map((faq, i) => {
              const isOpen = openFaq === i;
              const panelId = `pfc-faq-panel-${i}`;
              const buttonId = `pfc-faq-button-${i}`;
              return (
                <div key={faq.q}>
                  <h4>
                    <button
                      type="button"
                      id={buttonId}
                      aria-expanded={isOpen}
                      aria-controls={panelId}
                      onClick={() => setOpenFaq(isOpen ? null : i)}
                      className="flex w-full items-center justify-between gap-4 px-6 py-5 text-left transition-colors hover:bg-slate-50 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-indigo-500 dark:hover:bg-slate-800/50"
                    >
                      <span className="text-base font-semibold text-slate-900 dark:text-white">
                        {faq.q}
                      </span>
                      <span
                        className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-300"
                        style={{
                          transform: isOpen ? "rotate(180deg)" : "rotate(0deg)",
                          transition: reduce ? "none" : "transform 0.28s ease",
                        }}
                      >
                        <ChevronIcon className="h-4 w-4" />
                      </span>
                    </button>
                  </h4>
                  <AnimatePresence initial={false}>
                    {isOpen && (
                      <motion.div
                        key="content"
                        id={panelId}
                        role="region"
                        aria-labelledby={buttonId}
                        initial={reduce ? false : { height: 0, opacity: 0 }}
                        animate={{ height: "auto", opacity: 1 }}
                        exit={reduce ? { opacity: 0 } : { height: 0, opacity: 0 }}
                        transition={{ duration: reduce ? 0 : 0.3, ease: [0.22, 1, 0.36, 1] }}
                        className="overflow-hidden"
                      >
                        <p className="px-6 pb-5 text-sm leading-relaxed text-slate-600 dark:text-slate-400">
                          {faq.a}
                        </p>
                      </motion.div>
                    )}
                  </AnimatePresence>
                </div>
              );
            })}
          </motion.div>

          {/* bottom CTA */}
          <motion.div
            className="mt-10 flex flex-col items-center justify-between gap-5 rounded-2xl border border-indigo-200 bg-gradient-to-r from-indigo-50 to-violet-50 px-8 py-7 text-center sm:flex-row sm:text-left dark:border-indigo-500/30 dark:from-indigo-500/10 dark:to-violet-500/10"
            {...enter(0.1)}
          >
            <div>
              <p className="text-base font-semibold text-slate-900 dark:text-white">
                Still have questions?
              </p>
              <p className="mt-1 text-sm text-slate-600 dark:text-slate-400">
                Our team replies within one business day, no bots.
              </p>
            </div>
            <button
              type="button"
              className="shrink-0 rounded-xl bg-gradient-to-r from-indigo-600 to-violet-600 px-6 py-3 text-sm font-semibold text-white shadow-lg shadow-indigo-500/30 transition-transform duration-200 hover:-translate-y-0.5 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500"
            >
              Contact support
            </button>
          </motion.div>
        </div>
      </div>
    </section>
  );
}

Dependencies

motion

Licence

Built by Web Innoventix. Free for personal and commercial use, no attribution required.

Built by Web Innoventix

Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.

Get a free quote

Similar components

Browse all →
Simple Pricing

Simple Pricing

Original

A three-tier pricing section with a highlighted popular plan.

Single Plan Pricing Card

Single Plan Pricing Card

Original

A focused one-plan pricing card with price, trial badge, feature list, call to action and a money-back trust note, ideal when you sell a single flat-rate product.

Three Tier Pricing With Monthly Annual Toggle

Three Tier Pricing With Monthly Annual Toggle

Original

A three-tier pricing grid with a pure-CSS monthly and annual billing toggle that swaps every price with no JavaScript, using a native checkbox and Tailwind group-has state.

Plan Feature Comparison Table

Plan Feature Comparison Table

Original

A responsive, semantic feature comparison table across three plans with grouped rows, tick and dash indicators and screen-reader labels so visitors can weigh every feature side by side.

Staggered Glow Pricing Tiers

Staggered Glow Pricing Tiers

Original

A three-tier pricing section whose cards reveal in a staggered spring cascade, with a rotating conic-gradient glow on the popular plan and prices that count up smoothly when you toggle monthly and annual billing.

Spotlight Cursor Pricing Cards

Spotlight Cursor Pricing Cards

Original

Pricing cards that light up with a cursor-following radial spotlight, drift over floating background orbs and rise into view with a staggered spring entrance, plus a pulsing glow on the popular plan.

Highlight Follow Pricing Plans

Highlight Follow Pricing Plans

Original

A pricing row where an animated gradient highlight glides via shared layout animation to whichever plan you hover, a three-way billing switch slides its pill, prices recount instantly and a perks marquee scrolls beneath.

Three Tier Pricing

Three Tier Pricing

Original

three-tier pricing cards

Toggle Annual Pricing

Toggle Annual Pricing

Original

pricing with monthly/annual toggle

Single Highlight Pricing

Single Highlight Pricing

Original

single highlighted plan

Comparison Table Pricing

Comparison Table Pricing

Original

pricing comparison table

Cards Gradient Pricing

Cards Gradient Pricing

Original

gradient pricing cards