The plan step of a signup flow in a narrow column: the cards become a swipe row and the button names the plan that fits.
registry/demos/plan-fit-signup-demo.tsx
"use client";
import * as React from "react";
import { PlanFit, type PlanFitPlan } from "@/components/ui/plan-fit";
// The plan step of a signup flow, in a narrow column: the cards become a
// swipe row, and the button under it always names the plan that fits.
const PLANS: PlanFitPlan[] = [
{
id: "hobby",
name: "Hobby",
pitch: "Side projects and weekend experiments.",
price: 0,
included: 200,
caption: "Watermarked",
features: ["Standard queue", "1024px renders"],
},
{
id: "studio",
name: "Studio",
pitch: "For a designer generating every day.",
price: 18,
included: 2000,
overage: { price: 5, per: 500 },
caption: "Billed monthly",
features: ["Fast queue", "4K upscales", "Commercial license"],
},
{
id: "team",
name: "Team",
pitch: "Shared styles for a whole studio.",
price: 90,
included: 15000,
overage: { price: 20, per: 2500 },
caption: "Billed monthly",
features: ["Shared style library", "Ten seats", "Usage by member"],
},
];
export function PlanFitSignupDemo() {
const [plan, setPlan] = React.useState("studio");
const name = PLANS.find((p) => p.id === plan)?.name;
return (
<div className="w-full max-w-sm rounded-[1.75rem] bg-white p-6 shadow-[0_0_0_1px_rgb(9_9_11/0.08),0_24px_48px_-24px_rgb(9_9_11/0.25)] dark:bg-zinc-900 dark:shadow-[0_0_0_1px_rgb(255_255_255/0.08)]">
<p className="text-xs font-medium text-zinc-500 dark:text-zinc-400">Step 2 of 3</p>
<h3 className="mt-1 text-lg font-semibold tracking-[-0.02em] text-zinc-950 dark:text-white">
How many images a month?
</h3>
<PlanFit
plans={PLANS}
unit="images"
readoutLabel="images generated per month"
defaultValue={900}
max={40000}
onFitChange={setPlan}
className="mt-6 [--plan-fit-accent-ink:#0a0a0a] [--plan-fit-accent:#ff2e88] [--plan-fit-surface:#ffffff] dark:[--plan-fit-surface:#18181b]"
/>
<button
type="button"
className="mt-6 h-11 w-full rounded-full bg-zinc-950 text-sm font-semibold text-white transition-[background-color,scale] duration-150 active:scale-[0.98] hover:bg-zinc-800 dark:bg-white dark:text-zinc-950 dark:hover:bg-zinc-200"
>
Continue with {name}
</button>
</div>
);
}
Live preview, examples and props: https://keyframeui.com/components/plan-fit#plan-fit-signup-demo