Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pricing page updates #2580

Closed
wants to merge 14 commits into from
86 changes: 86 additions & 0 deletions bifrost/app/components/templates/pricing/AddOnsTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { Col } from "@/components/common/col";
import PlansTable, { FeatureRowProps } from "./PlansTable";
import { Row } from "@/components/common/row";
import { XMarkIcon } from "@heroicons/react/24/outline";

const rows: FeatureRowProps[] = [
{
title: "Prompts + Experiments",
description:
"Version prompts, create templates, and run experiments to improve LLM outputs.",
free: (
<>
<XMarkIcon className="w-6 h-6 text-red-500" />
<p className="text-center text-sm font-light text-slate-500">
Upgrade to Pro to enable Prompts + Experiments.
</p>
</>
),
pro: (
<>
<Row className="items-center gap-[4px]">
<h3 className="font-bold text-xl">$30</h3>
<p className="text-slate-500">/mo</p>
</Row>
<p className="text-center text-sm font-light text-slate-500">
Unlimited prompts and versions.
</p>
</>
),
enterprise: (
<>
<h3 className="font-bold text-xl">Included</h3>
<p className="text-center text-sm font-light text-slate-500">
Unlimited prompts and versions.
</p>
</>
),
},
{
title: "Alerts (Slack + Email)",
description:
"Receive real-time alerts to Slack or email and stay on top of critical issues.",
free: (
<>
<XMarkIcon className="w-6 h-6 text-red-500" />
<p className="text-center text-sm font-light text-slate-500">
Upgrade to Pro to enable Alerts.
</p>
</>
),
pro: (
<>
<Row className="items-center gap-[4px]">
<h3 className="font-bold text-xl">$15</h3>
<p className="text-slate-500">/mo</p>
</Row>
<p className="text-center text-sm font-light text-slate-500">
Unlimited alerts.
</p>
</>
),
enterprise: (
<>
<h3 className="font-bold text-xl">Included</h3>
<p className="text-center text-sm font-light text-slate-500">
Unlimited alerts.
</p>
</>
),
},
];

export default function AddOnsTable() {
return (
<div className="flex flex-col max-w-6xl mx-auto pt-8 w-full">
<Col>
<h4 className="text-[24px] font-bold text-slate-900">Add-ons</h4>
<p className="text-slate-700">
Specialized features are now available as add-ons, so you never pay
what you don’t need.
</p>
</Col>
<PlansTable rows={rows} />
</div>
);
}
57 changes: 57 additions & 0 deletions bifrost/app/components/templates/pricing/BaseCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from "react";
import Link from "next/link";
import { CheckCircleIcon, XCircleIcon } from "@heroicons/react/16/solid";

interface BaseCardProps {
name: string;

price: React.ReactNode;
features: { name: string; included: boolean }[];
ctaText: string;
ctaLink: string;
ctaClassName?: string;
children?: React.ReactNode;
}

const BaseCard: React.FC<BaseCardProps> = ({
name,

price,
features,
ctaText,
ctaLink,
ctaClassName,
children,
}) => {
return (
<div className="w-full h-full border border-gray-300 rounded-xl flex flex-col space-y-4 p-8 bg-white">
<h2 className="text-sm font-semibold">{name}</h2>

<div className="flex items-baseline space-x-1">{price}</div>
{children}
<ul className="text-gray-500 text-sm">
{features.map((feature) => (
<li key={feature.name} className="flex items-center gap-4 py-2">
{feature.included ? (
<CheckCircleIcon className="h-5 w-5 text-sky-500" />
) : (
<XCircleIcon className="h-5 w-5 text-gray-300" />
)}
<span>{feature.name}</span>
</li>
))}
</ul>
<Link
href={ctaLink}
className={
ctaClassName ||
"bg-white hover:bg-gray-100 ease-in-out duration-500 text-black border-[3px] border-gray-300 rounded-lg px-4 py-2 text-sm font-bold shadow-lg flex w-full justify-center text-center items-center gap-1"
}
>
{ctaText}
</Link>
</div>
);
};

export default BaseCard;
41 changes: 41 additions & 0 deletions bifrost/app/components/templates/pricing/EnterpriseCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Card } from "@/components/ui/card";
import { Col } from "@/components/common/col";
import { Row } from "@/components/common/row";
import { CheckIcon } from "@heroicons/react/24/outline";
import { FeatureItem } from "./FeaturedItem";

const EnterpriseCard: React.FC = () => {
return (
<Card className="p-[24px] bg-slate-50 h-[500px] border-none shadow-none">
<Col className="h-full justify-between">
<Col className="gap-[24px]">
<div className="px-[12px] py-[6px] border-2 border-slate-200 text-slate-900 w-fit rounded-[4px] font-medium">
Enterprise
</div>
<Col className="gap-[8px]">
<h3 className="text-[36px] font-bold text-slate-900">Contact us</h3>
<Col>
<h4 className="text-[16px] text-slate-700 font-light">
For companies{" "}
<span className="font-semibold">looking to scale.</span>
</h4>
<h4 className="text-[14px] text-slate-700">
Everything in Pro, plus:
</h4>
</Col>
</Col>
</Col>
<Col className="gap-[16px]">
<FeatureItem title="Training and Optimization" />
<FeatureItem title="SOC-2 Compliance" />
<FeatureItem title="Dedicated support" />
</Col>
<button className="bg-[#FFFFFF] text-slate-900 py-[12px] border border-slate-200 rounded-[4px] mt-[8px] text-[16px]">
Contact sales
</button>
</Col>
</Card>
);
};

export default EnterpriseCard;
24 changes: 24 additions & 0 deletions bifrost/app/components/templates/pricing/FeaturedItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Col } from "@/components/common/col";
import { Row } from "@/components/common/row";
import { CheckIcon } from "@heroicons/react/24/outline";

export const FeatureItem: React.FC<{
title: string;
description?: string | React.ReactNode;
}> = ({ title, description }) => (
<Row className="gap-[12px] items-start">
<CheckIcon
className="w-[18px] h-[18px] text-[#6AA84F] stroke-[3px] mt-[2px]"
width={18}
height={18}
/>
<Col className="gap-[4px]">
<h3 className="text-[16px] font-medium text-slate-700 font-medium">
{title}
</h3>
{description && (
<h4 className="text-[14px] font-light text-slate-700">{description}</h4>
)}
</Col>
</Row>
);
45 changes: 45 additions & 0 deletions bifrost/app/components/templates/pricing/FreeCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Card } from "@/components/ui/card";
import { Col } from "@/components/common/col";
import { Row } from "@/components/common/row";
import { CheckIcon } from "@heroicons/react/24/outline";
import { FeatureItem } from "./FeaturedItem";

const FreeCard: React.FC = () => {
return (
<Card className="p-[24px] bg-slate-50 h-[500px] border-none shadow-none">
<Col className="h-full justify-between">
<Col className="gap-[24px]">
<div className="px-[12px] py-[6px] border-2 border-slate-200 w-fit rounded-[4px] bg-slate-50 text-slate-900 font-medium">
Free
</div>
<Col className="gap-[8px]">
<h3 className="text-[36px] font-bold">Free</h3>
<h4 className="text-[16px] text-slate-700 font-light">
Everything to{" "}
<span className="font-semibold">kickstart your AI project</span>.
</h4>
</Col>
</Col>
<Col className="gap-[16px] ">
<FeatureItem
title="Generous free monthly tier"
description="10k free requests/month."
/>
<FeatureItem
title="Access to Dashboard"
description="Watch your AI app improve."
/>
<FeatureItem
title="Free, truly."
description="No credit card required."
/>
</Col>
<button className="bg-[#FFFFFF] text-slate-900 py-[12px] border border-slate-200 rounded-[4px] mt-[8px] text-[16px]">
Get started
</button>
</Col>
</Card>
);
};

export default FreeCard;
90 changes: 90 additions & 0 deletions bifrost/app/components/templates/pricing/PlansTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Col } from "@/components/common/col";
import { Card } from "@/components/ui/card";
import { clsx } from "@/utils/clsx";

export interface FeatureRowProps {
title: string;
description: string | React.ReactNode;
free: React.ReactNode;
pro: React.ReactNode;
enterprise: React.ReactNode;
}

const FeatureRow: React.FC<FeatureRowProps> = ({
title,
description,
free,
pro,
enterprise,
}) => (
<>
<Col
className={clsx(
"p-[24px] gap-[12px]",
title === "SOC-2 Type II Compliance" ||
title === "Alerts (Slack + Email)"
? "rounded-bl-lg"
: ""
)}
>
<Col className="gap-[4px]">
<h3 className="text-lg font-semibold gap-[12px] items-center">
{title}
</h3>
{title === "Requests" || title === "API access" ? ( // doing this check to avoid hydration errors (div inside p)
description
) : (
<p className="text-slate-500">{description}</p>
)}
</Col>
</Col>
<div className="p-[24px] max-w-[360px] items-center justify-center flex flex-col gap-[4px]">
{free}
</div>
<div className="p-[24px] max-w-[360px] items-center justify-center flex flex-col gap-[4px] bg-[rgba(12,165,234,0.05)]">
{pro}
</div>
<div className="p-[24px] max-w-[360px] items-center justify-center flex flex-col gap-[4px]">
{enterprise}
</div>
</>
);

export default function PlansTable({
rows,
isMain = false,
}: {
rows: FeatureRowProps[];
isMain?: boolean;
}) {
return (
<div className="w-full pt-10 overflow-x-auto">
<div className="w-full overflow-visible">
<div className="min-w-[800px] overflow-visible">
<div className="grid grid-cols-[2fr,1fr,1fr,1fr] divide-x divide-y divide-slate-200 border-b border-r rounded-lg overflow-visible text-slate-900 border-slate-200">
<div className="border-l border-t rounded-tl-lg bg-slate-50 border-slate-200"></div>
<div className="p-[24px] bg-slate-50 font-semibold text-xl text-center">
Free
</div>
<div className="relative p-[24px] bg-brand text-white font-semibold text-xl text-center overflow-visible border-brand">
Pro
{isMain && (
<Card className="absolute top-0 right-1/2 bg-[#F3FAFE] translate-x-1/2 -translate-y-[24px] rotate-[10.2deg] px-[12px] py-[6px] border-brand border-[2px] rounded-[4px] overflow-visible">
<h3 className="text-[16px] font-semibold text-brand">
Recommended
</h3>
</Card>
)}
</div>
<div className="p-[24px] bg-slate-50 font-semibold text-xl text-center rounded-tr-lg">
Enterprise
</div>
{rows.map((row) => (
<FeatureRow key={row.title} {...row} />
))}
</div>
</div>
</div>
</div>
);
}
Loading
Loading