diff --git a/mirascope-ui/blocks/lilypad-pricing.stories.tsx b/mirascope-ui/blocks/lilypad-pricing.stories.tsx index bd3ce48..a7a80be 100644 --- a/mirascope-ui/blocks/lilypad-pricing.stories.tsx +++ b/mirascope-ui/blocks/lilypad-pricing.stories.tsx @@ -1,4 +1,5 @@ import { LilypadPricing } from "@/mirascope-ui/blocks/lilypad-pricing"; +import { ButtonLink } from "@/mirascope-ui/ui/button-link"; import type { Meta, StoryObj } from "@storybook/react"; import { createMemoryHistory, @@ -55,36 +56,48 @@ type Story = StoryObj; const defaultActions = { hosted: { free: { - buttonText: "Get Started Free", - buttonLink: "/signup", - variant: "default" as const, + button: ( + + Get Started Free + + ), }, pro: { - buttonText: "Join Waitlist", - buttonLink: "/waitlist", - variant: "outline" as const, + button: ( + + Join Waitlist + + ), }, team: { - buttonText: "Contact Sales", - buttonLink: "/contact", - variant: "outline" as const, + button: ( + + Contact Sales + + ), }, }, selfHosted: { free: { - buttonText: "Download", - buttonLink: "/download", - variant: "default" as const, + button: ( + + Download + + ), }, pro: { - buttonText: "Request Access", - buttonLink: "/request-access", - variant: "outline" as const, + button: ( + + Request Access + + ), }, team: { - buttonText: "Contact Sales", - buttonLink: "/contact", - variant: "outline" as const, + button: ( + + Contact Sales + + ), }, }, }; @@ -100,36 +113,48 @@ export const WithExternalLinks: Story = { actions: { hosted: { free: { - buttonText: "Sign Up Now", - buttonLink: "https://app.lilypad.com/signup", - variant: "default" as const, + button: ( + + Sign Up Now + + ), }, pro: { - buttonText: "Join Beta", - buttonLink: "https://forms.lilypad.com/beta", - variant: "outline" as const, + button: ( + + Join Beta + + ), }, team: { - buttonText: "Schedule Demo", - buttonLink: "https://calendly.com/lilypad-team", - variant: "outline" as const, + button: ( + + Schedule Demo + + ), }, }, selfHosted: { free: { - buttonText: "GitHub Release", - buttonLink: "https://github.com/mirascope/lilypad/releases", - variant: "default" as const, + button: ( + + GitHub Release + + ), }, pro: { - buttonText: "Enterprise Inquiry", - buttonLink: "https://forms.lilypad.com/enterprise", - variant: "outline" as const, + button: ( + + Enterprise Inquiry + + ), }, team: { - buttonText: "Book Consultation", - buttonLink: "https://calendly.com/lilypad-enterprise", - variant: "outline" as const, + button: ( + + Book Consultation + + ), }, }, }, @@ -148,36 +173,48 @@ export const AllPrimaryButtons: Story = { actions: { hosted: { free: { - buttonText: "Start Free", - buttonLink: "/start", - variant: "default" as const, + button: ( + + Start Free + + ), }, pro: { - buttonText: "Upgrade to Pro", - buttonLink: "/upgrade-pro", - variant: "default" as const, + button: ( + + Upgrade to Pro + + ), }, team: { - buttonText: "Get Team Plan", - buttonLink: "/upgrade-team", - variant: "default" as const, + button: ( + + Get Team Plan + + ), }, }, selfHosted: { free: { - buttonText: "Download Free", - buttonLink: "/download", - variant: "default" as const, + button: ( + + Download Free + + ), }, pro: { - buttonText: "Get Pro License", - buttonLink: "/license-pro", - variant: "default" as const, + button: ( + + Get Pro License + + ), }, team: { - buttonText: "Get Team License", - buttonLink: "/license-team", - variant: "default" as const, + button: ( + + Get Team License + + ), }, }, }, diff --git a/mirascope-ui/blocks/lilypad-pricing.tsx b/mirascope-ui/blocks/lilypad-pricing.tsx index 4fcef72..21dc8f8 100644 --- a/mirascope-ui/blocks/lilypad-pricing.tsx +++ b/mirascope-ui/blocks/lilypad-pricing.tsx @@ -1,20 +1,16 @@ -import { Check, X } from "lucide-react"; -import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/mirascope-ui/ui/tabs"; -import { ButtonLink } from "@/mirascope-ui/ui/button-link"; import { cn } from "@/mirascope-ui/lib/utils"; +import { ButtonLink } from "@/mirascope-ui/ui/button-link"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/mirascope-ui/ui/tabs"; +import { Check, X } from "lucide-react"; -// Feature row component for displaying features with the same value across tiers -const FeatureRow = ({ - feature, - free, - pro, - team, -}: { +interface FeatureRowProps { feature: string; free: string | boolean; pro: string | boolean; team: string | boolean; -}) => { +} +// Feature row component for displaying features with the same value across tiers +const FeatureRow = ({ feature, free, pro, team }: FeatureRowProps) => { // If all tiers have the exact same value (and it's not a boolean) const allSameNonBoolean = free === pro && pro === team && typeof free === "string" && free !== ""; @@ -85,25 +81,16 @@ const FeatureRow = ({ ); }; -// Pricing tier component -const PricingTier = ({ - name, - price, - description, - buttonText, - buttonLink, - badge, - variant = "default", -}: { +interface PricingTierProps { name: string; price: string; description: string; - buttonText: string; - buttonLink: string; + button: React.ReactNode; badge?: "Open Beta" | "Closed Beta"; - variant?: "default" | "outline"; -}) => ( -
+} +// Pricing tier component +const PricingTier = ({ name, price, description, button, badge }: PricingTierProps) => ( +

{name}

@@ -127,26 +114,15 @@ const PricingTier = ({ / month )}
- - {buttonText} - + {button}
); // Feature comparison table component -const FeatureComparisonTable = ({ - features, -}: { - features: Array<{ - feature: string; - free: string | boolean; - pro: string | boolean; - team: string | boolean; - }>; -}) => ( -
-
+export const FeatureComparisonTable = ({ features }: { features: FeatureRowProps[] }) => ( +
+

Feature Comparison

@@ -160,22 +136,14 @@ const FeatureComparisonTable = ({ {/* Table rows */} {features.map((feat, i) => ( - + ))}
); interface TierAction { - buttonText: string; - buttonLink: string; - variant?: "default" | "outline"; + button: React.ReactNode; } interface PricingActions { @@ -191,48 +159,47 @@ interface PricingActions { }; } +// Cloud hosted features +export const cloudHostedFeatures = [ + { feature: "Projects", free: "Unlimited", pro: "Unlimited", team: "Unlimited" }, + { feature: "Users", free: "2", pro: "10", team: "Unlimited" }, + { + feature: "Tracing", + free: "30k spans / month", + pro: "100k spans / month (thereafter $1 per 10k)", + team: "1M spans / month (thereafter $1 per 10k)", + }, + { feature: "Data Retention", free: "30 days", pro: "90 days", team: "180 days" }, + { feature: "Versioned Functions", free: true, pro: true, team: true }, + { feature: "Playground", free: true, pro: true, team: true }, + { feature: "Comparisons", free: true, pro: true, team: true }, + { feature: "Annotations", free: true, pro: true, team: true }, + { feature: "Support (Community)", free: true, pro: true, team: true }, + { feature: "Support (Chat / Email)", free: false, pro: true, team: true }, + { feature: "Support (Private Slack)", free: false, pro: false, team: true }, + { feature: "API Rate Limits", free: "10 / minute", pro: "100 / minute", team: "1000 / minute" }, +]; + +// Self-hosted features +export const selfHostedFeatures = [ + { feature: "Projects", free: "Unlimited", pro: "Unlimited", team: "Unlimited" }, + { feature: "Users", free: "Unlimited", pro: "As licensed", team: "As licensed" }, + { feature: "Tracing", free: "No limits", pro: "No limits", team: "No limits" }, + { feature: "Data Retention", free: "No limits", pro: "No limits", team: "No limits" }, + { feature: "Versioned Functions", free: true, pro: true, team: true }, + { feature: "Playground", free: false, pro: true, team: true }, + { feature: "Comparisons", free: false, pro: true, team: true }, + { feature: "Annotations", free: false, pro: true, team: true }, + { feature: "Support (Community)", free: true, pro: true, team: true }, + { feature: "Support (Chat / Email)", free: false, pro: true, team: true }, + { feature: "Support (Private Slack)", free: false, pro: false, team: true }, + { feature: "API Rate Limits", free: "No limits", pro: "No limits", team: "No limits" }, +]; interface LilypadPricingProps { actions: PricingActions; } export function LilypadPricing({ actions }: LilypadPricingProps) { - // Cloud hosted features - const cloudHostedFeatures = [ - { feature: "Projects", free: "Unlimited", pro: "Unlimited", team: "Unlimited" }, - { feature: "Users", free: "2", pro: "10", team: "Unlimited" }, - { - feature: "Tracing", - free: "30k spans / month", - pro: "100k spans / month (thereafter $1 per 10k)", - team: "1M spans / month (thereafter $1 per 10k)", - }, - { feature: "Data Retention", free: "30 days", pro: "90 days", team: "180 days" }, - { feature: "Versioned Functions", free: true, pro: true, team: true }, - { feature: "Playground", free: true, pro: true, team: true }, - { feature: "Comparisons", free: true, pro: true, team: true }, - { feature: "Annotations", free: true, pro: true, team: true }, - { feature: "Support (Community)", free: true, pro: true, team: true }, - { feature: "Support (Chat / Email)", free: false, pro: true, team: true }, - { feature: "Support (Private Slack)", free: false, pro: false, team: true }, - { feature: "API Rate Limits", free: "10 / minute", pro: "100 / minute", team: "1000 / minute" }, - ]; - - // Self-hosted features - const selfHostedFeatures = [ - { feature: "Projects", free: "Unlimited", pro: "Unlimited", team: "Unlimited" }, - { feature: "Users", free: "Unlimited", pro: "As licensed", team: "As licensed" }, - { feature: "Tracing", free: "No limits", pro: "No limits", team: "No limits" }, - { feature: "Data Retention", free: "No limits", pro: "No limits", team: "No limits" }, - { feature: "Versioned Functions", free: true, pro: true, team: true }, - { feature: "Playground", free: false, pro: true, team: true }, - { feature: "Comparisons", free: false, pro: true, team: true }, - { feature: "Annotations", free: false, pro: true, team: true }, - { feature: "Support (Community)", free: true, pro: true, team: true }, - { feature: "Support (Chat / Email)", free: false, pro: true, team: true }, - { feature: "Support (Private Slack)", free: false, pro: false, team: true }, - { feature: "API Rate Limits", free: "No limits", pro: "No limits", team: "No limits" }, - ]; - return (
@@ -256,35 +223,7 @@ export function LilypadPricing({ actions }: LilypadPricingProps) { {/* Hosted By Us Tab Content */} -
- - - -
+ {/* Feature comparison table */} @@ -297,28 +236,22 @@ export function LilypadPricing({ actions }: LilypadPricingProps) { name="Free" price="$0" description="For individuals just getting started" - buttonText={actions.selfHosted.free.buttonText} - buttonLink={actions.selfHosted.free.buttonLink} badge="Open Beta" - variant={actions.selfHosted.free.variant} + button={actions.selfHosted.free.button} />
@@ -328,7 +261,7 @@ export function LilypadPricing({ actions }: LilypadPricingProps) { {/* FAQ Section */} -
+

Frequently Asked Questions

@@ -338,8 +271,8 @@ export function LilypadPricing({ actions }: LilypadPricingProps) { How long will the open beta last?

- The open beta period is ongoing, and we'll provide advance notice before moving to - paid plans. + The open beta period is ongoing, and we'll provide advance notice before moving + to paid plans.

@@ -361,7 +294,7 @@ export function LilypadPricing({ actions }: LilypadPricingProps) {

Join our{" "} @@ -374,3 +307,44 @@ export function LilypadPricing({ actions }: LilypadPricingProps) {

); } + +export const LilypadCloudPricing = ({ + hostedActions, +}: { + hostedActions: { + free: TierAction; + pro: TierAction; + team: TierAction; + }; +}) => { + const pricingTiers: PricingTierProps[] = [ + { + name: "Free", + price: "$0", + description: "For individuals just getting started", + badge: "Open Beta", + button: hostedActions.free.button, + }, + { + name: "Pro", + price: "TBD", + description: "For teams with more advanced needs", + badge: "Closed Beta", + button: hostedActions.pro.button, + }, + { + name: "Team", + price: "TBD", + description: "For larger teams requiring dedicated support", + badge: "Closed Beta", + button: hostedActions.team.button, + }, + ]; + return ( +
+ {pricingTiers.map((tier) => ( + + ))} +
+ ); +};