All componentsdisplay
Pricing Toggle
$24/mo
Installation
$ npx shadcn@latest add https://deepmoon.dev/r/pricing-toggle.jsonProps
PricingToggleProps
| Prop | Type | Required |
|---|---|---|
| value | PricingPeriod | Yes |
| onChange | (value: PricingPeriod) => void | Yes |
| annualDiscountLabel | string | No |
| className | string | No |
Code
pricing-toggle.tsx
import * as React from "react";
import { cn } from "@/lib/utils";
export type PricingPeriod = "monthly" | "annual";
export interface PricingToggleProps {
value: PricingPeriod;
onChange: (value: PricingPeriod) => void;
annualDiscountLabel?: string;
className?: string;
}
export function PricingToggle({ value, onChange, annualDiscountLabel = "Save 20%", className }: PricingToggleProps) {
return (
<div
role="group"
aria-label="Billing period"
className={cn("inline-flex items-center gap-1 rounded-full border border-border bg-muted p-1", className)}
>
{(["monthly", "annual"] as const).map((period) => (
<button
key={period}
type="button"
aria-pressed={value === period}
onClick={() => onChange(period)}
className={cn(
"flex items-center gap-1.5 rounded-full px-3 py-1.5 text-sm font-medium outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring",
value === period ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground",
)}
>
{period === "monthly" ? "Monthly" : "Annual"}
{period === "annual" ? (
<span
className={cn(
"rounded-full px-1.5 py-0.5 text-xs font-semibold",
value === "annual" ? "bg-success/15 text-success" : "bg-muted-foreground/10 text-muted-foreground",
)}
>
{annualDiscountLabel}
</span>
) : null}
</button>
))}
</div>
);
}