Price
Tabular price with compare-at strike, sale color, savings chip, and per-unit or per-serving pricing.
ui
$
npx shadcn@latest add @storekit/priceprice
Live and interactive. Switch the brand in the frame header to see the same source under another token file.
Installation
$
npx shadcn@latest add @storekit/price$
pnpm dlx shadcn@latest add @storekit/price$
yarn dlx shadcn@latest add @storekit/price$
bunx --bun shadcn@latest add @storekit/priceSource
components/storekit/ui/price.tsx
46 lines
"use client"
import { cn, money } from "@/components/storekit/lib/cn"
/* Price with optional compare-at and savings. Tabular numerals so prices in a
grid line up. The amount is in integer cents. `per` adds unit economics in
muted text, e.g. { amount: 112, unit: "serving" } renders "$1.12 / serving". */
export function Price({
amount,
compareAt,
className,
size = "md",
showSavings = false,
suffix,
per,
}: {
amount: number
compareAt?: number
className?: string
size?: "sm" | "md" | "lg" | "xl"
showSavings?: boolean
suffix?: string
/** Unit economics: amount in integer cents per one unit ("serving", "day", "each"). */
per?: { amount: number; unit: string }
}) {
const onSale = typeof compareAt === "number" && compareAt > amount
const sizes = { sm: "text-sm", md: "text-base", lg: "text-xl", xl: "text-3xl" }[size]
const pct = onSale ? Math.round((1 - amount / compareAt) * 100) : 0
return (
<span className={cn("inline-flex flex-wrap items-baseline gap-x-2 gap-y-0.5 tabular-nums", sizes, className)}>
<span className={cn("font-semibold", onSale ? "text-sk-sale" : "text-sk-price")}>{money(amount)}</span>
{onSale ? <s className="text-[0.8em] text-sk-muted decoration-sk-muted/60">{money(compareAt)}</s> : null}
{onSale && showSavings ? (
<span className="rounded-sk-chip bg-sk-savings/[0.12] px-1.5 py-0.5 text-[0.7em] font-semibold text-sk-savings">Save {pct}%</span>
) : null}
{suffix ? <span className="text-[0.75em] text-sk-muted">{suffix}</span> : null}
{per ? (
<span className="text-[0.75em] font-normal text-sk-muted">
{money(per.amount)} / {per.unit}
</span>
) : null}
</span>
)
}
Usage
Import from "@/components/storekit/ui/price" and pass your product data. The demo above exercises the full prop surface with sample values.