pricing-2

PreviousNext

Modular pricing card UI kit with reusable glass-style components and typography helpers.

Docs
efferdblock

Preview

Loading preview…
@app/core/pricing-card.tsx
import { cn } from "@/lib/utils";
import type React from "react";

function Card({ className, ...props }: React.ComponentProps<"div">) {
	return (
		<div
			className={cn(
				"relative w-full max-w-xs rounded-xl border bg-card dark:bg-transparent",
				"p-1.5 shadow-xs backdrop-blur-xl",
				className
			)}
			{...props}
		/>
	);
}

function Header({
	className,
	children,
	glassEffect = true,
	...props
}: React.ComponentProps<"div"> & {
	glassEffect?: boolean;
}) {
	return (
		<div
			className={cn(
				"relative mb-4 rounded-xl border bg-muted/50 p-4 shadow-sm",
				className
			)}
			{...props}
		>
			{/* Top glass gradient */}
			{glassEffect && (
				<div
					aria-hidden="true"
					className="-z-10 absolute inset-x-0 top-0 h-48 rounded-[inherit]"
					style={{
						background:
							"linear-gradient(180deg, rgba(255,255,255,0.07) 0%, rgba(255,255,255,0.03) 40%, rgba(0,0,0,0) 100%)",
					}}
				/>
			)}
			{children}
		</div>
	);
}

function Plan({ className, ...props }: React.ComponentProps<"div">) {
	return (
		<div
			className={cn("mb-8 flex items-center justify-between", className)}
			{...props}
		/>
	);
}

function Description({ className, ...props }: React.ComponentProps<"p">) {
	return (
		<p className={cn("text-muted-foreground text-xs", className)} {...props} />
	);
}

function PlanName({ className, ...props }: React.ComponentProps<"div">) {
	return (
		<div
			className={cn(
				"flex items-center gap-2 font-medium text-muted-foreground text-sm [&_svg:not([class*='size-'])]:size-4",
				className
			)}
			{...props}
		/>
	);
}

function Badge({ className, ...props }: React.ComponentProps<"span">) {
	return (
		<span
			className={cn(
				"rounded-full border border-foreground/20 px-2 py-0.5 text-foreground/80 text-xs",
				className
			)}
			{...props}
		/>
	);
}

function Price({ className, ...props }: React.ComponentProps<"div">) {
	return (
		<div className={cn("mb-3 flex items-end gap-1", className)} {...props} />
	);
}

function MainPrice({ className, ...props }: React.ComponentProps<"span">) {
	return (
		<span
			className={cn("font-extrabold text-3xl tracking-tight", className)}
			{...props}
		/>
	);
}

function Period({ className, ...props }: React.ComponentProps<"span">) {
	return (
		<span
			className={cn("pb-1 text-foreground/80 text-sm", className)}
			{...props}
		/>
	);
}

function OriginalPrice({ className, ...props }: React.ComponentProps<"span">) {
	return (
		<span
			className={cn(
				"mr-1 ml-auto text-lg text-muted-foreground line-through",
				className
			)}
			{...props}
		/>
	);
}

function Body({ className, ...props }: React.ComponentProps<"div">) {
	return <div className={cn("space-y-6 p-3", className)} {...props} />;
}

function List({ className, ...props }: React.ComponentProps<"ul">) {
	return <ul className={cn("space-y-3", className)} {...props} />;
}

function ListItem({ className, ...props }: React.ComponentProps<"li">) {
	return (
		<li
			className={cn(
				"flex items-start gap-3 text-muted-foreground text-sm",
				className
			)}
			{...props}
		/>
	);
}

function Separator({
	children = "Upgrade to access",
	className,
	...props
}: React.ComponentProps<"div"> & {
	children?: string;
	className?: string;
}) {
	return (
		<div
			className={cn(
				"flex items-center gap-3 text-muted-foreground text-sm",
				className
			)}
			{...props}
		>
			<span className="h-[1px] flex-1 bg-muted-foreground/40" />
			<span className="shrink-0 text-muted-foreground">{children}</span>
			<span className="h-[1px] flex-1 bg-muted-foreground/40" />
		</div>
	);
}

export {
	Card,
	Header,
	Description,
	Plan,
	PlanName,
	Badge,
	Price,
	MainPrice,
	Period,
	OriginalPrice,
	Body,
	List,
	ListItem,
	Separator,
};

Installation

npx shadcn@latest add @efferd/pricing-2

Usage

import { Pricing2 } from "@/components/pricing-2"
<Pricing2 />