Blocks

Pricing 35

Pricing
1 ColumnText Align LeftTabsPricing Section
Pricing 35

Code

relume-pricing35.tsx
import { Check } from "relume-icons";

import { Button, type ButtonProps } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";

type Billing = "monthly" | "yearly";

type ImageProps = {
  src: string;
  alt?: string;
};

type PricingPlan = {
  planName: string;
  description: string;
  price: string;
  discount?: string;
  features: string[];
  button: ButtonProps;
};

type Tab = {
  value: Billing;
  tabName: string;
  plan: PricingPlan;
};

type Props = {
  tagline: string;
  heading: string;
  description: string;
  logos: ImageProps[];
  logoHeading: string;
  defaultTabValue: Billing;
  tabs: Tab[];
};

export type Pricing35Props = React.ComponentPropsWithoutRef<"section"> & Partial<Props>;

export const Pricing35 = (props: Pricing35Props) => {
  const { tagline, heading, description, logos, logoHeading, defaultTabValue, tabs } = {
    ...Pricing35Defaults,
    ...props,
  };
  return (
    <section className="px-[5%] py-16 md:py-24 lg:py-28">
      <div className="container">
        <div className="grid grid-cols-1 gap-y-12 md:grid-flow-row md:gap-y-16 lg:grid-cols-2 lg:gap-x-20">
          <div>
            <p className="mb-3 font-semibold md:mb-4">{tagline}</p>
            <h2 className="mb-5 text-h2 font-bold md:mb-6">{heading}</h2>
            <p className="mb-8 text-medium md:mb-10 lg:mb-12">{description}</p>
            <h3 className="mb-2 text-h6 font-bold">{logoHeading}</h3>
            <div className="flex flex-wrap items-center gap-x-8 gap-y-6 py-2">
              {logos.map((logo, index) => (
                <img key={index} src={logo.src} className="max-h-12" alt={logo.alt} />
              ))}
            </div>
          </div>
          <Tabs defaultValue={defaultTabValue}>
            <TabsList className="mb-12 w-fit items-center rounded-button border bg-scheme-foreground p-1 group-data-[slot=card-flat]:border-transparent lg:justify-self-end">
              {tabs.map((tab, index) => (
                <TabsTrigger
                  key={index}
                  value={tab.value}
                  className="rounded-button data-[state=active]:bg-scheme-background data-[state=active]:font-medium data-[state=inactive]:bg-transparent"
                >
                  {tab.tabName}
                </TabsTrigger>
              ))}
            </TabsList>
            {tabs.map((tab, index) => (
              <TabsContent
                key={index}
                value={tab.value}
                className="data-[state=active]:animate-tabs"
              >
                <PricingPlan plan={tab.plan} billing={tab.value} />
              </TabsContent>
            ))}
          </Tabs>
        </div>
      </div>
    </section>
  );
};
const PricingPlan = ({ plan, billing }: { plan: PricingPlan; billing: Billing }) => (
  <Card className="h-full px-6 py-8 md:p-8">
    <div className="flex items-start justify-between">
      <div>
        <h4 className="mb-2 text-h5 font-bold">{plan.planName}</h4>
        <p>{plan.description}</p>
      </div>
      <h5 className="text-h1 font-bold">
        {plan.price}
        <span className="text-h4 font-bold">{billing === "monthly" ? "/mo" : "/yr"}</span>
      </h5>
    </div>
    {billing === "yearly" && plan.discount && (
      <p className="mt-2 text-right font-medium">{plan.discount}</p>
    )}
    <div className="my-6 h-px w-full shrink-0 bg-scheme-border md:my-8" />
    <p>Includes:</p>
    <div className="mt-3 grid grid-cols-1 gap-y-4 py-2 md:mt-4 md:grid-cols-2 md:gap-x-6">
      {plan.features.map((feature, index) => (
        <div key={index} className="flex self-start">
          <div className="mr-4 flex-none self-start">
            <Check className="size-6 text-scheme-text" />
          </div>
          <p>{feature}</p>
        </div>
      ))}
    </div>
    <div className="my-6 h-px w-full shrink-0 bg-scheme-border md:my-8" />
    <div>
      <Button {...plan.button} className="w-full">
        {plan.button.title}
      </Button>
    </div>
  </Card>
);

export const Pricing35Defaults: Props = {
  tagline: "Tagline",
  heading: "Pricing plan",
  description:
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
  logoHeading: "Used by the world's leading companies",
  logos: [
    { src: "https://d22po4pjz3o32e.cloudfront.net/webflow-logo.svg", alt: "Webflow logo 1" },
    { src: "https://d22po4pjz3o32e.cloudfront.net/relume-logo.svg", alt: "Relume logo 1" },
    { src: "https://d22po4pjz3o32e.cloudfront.net/webflow-logo.svg", alt: "Webflow logo 2" },
    { src: "https://d22po4pjz3o32e.cloudfront.net/relume-logo.svg", alt: "Relume logo 2" },
  ],
  defaultTabValue: "monthly",
  tabs: [
    {
      value: "monthly",
      tabName: "Monthly",
      plan: {
        planName: "Basic plan",
        description: "Lorem ipsum dolor sit amet",
        price: "$19",
        features: [
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
        ],
        button: { title: "Get started" },
      },
    },
    {
      value: "yearly",
      tabName: "Yearly",
      plan: {
        planName: "Basic plan",
        description: "Lorem ipsum dolor sit amet",
        price: "$180",
        discount: "Save 20%",
        features: [
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
          "Feature text goes here",
        ],
        button: { title: "Get started" },
      },
    },
  ],
};

npm i @radix-ui/react-slot @radix-ui/react-tabs class-variance-authority@0.7.1 clsx@^2.1.1 relume-icons@1.3.0 tailwind-merge@^2.2.2