Low stock line
Exact count from real inventory, hidden above the threshold and at zero. Plain ink, no urgency color.
componentstockanyinventory
$
npx shadcn@latest add @storekit/pdp-low-stockpdp-low-stock
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/pdp-low-stock$
pnpm dlx shadcn@latest add @storekit/pdp-low-stock$
yarn dlx shadcn@latest add @storekit/pdp-low-stock$
bunx --bun shadcn@latest add @storekit/pdp-low-stockSource
components/storekit/pdp/pdp-low-stock.tsx
63 lines
"use client"
import { AnimatePresence, motion, useReducedMotion } from "motion/react"
import { cn } from "@/components/storekit/lib/cn"
/* Exact low-stock line. Reads the real inventory count and renders nothing
above the threshold or at zero (sold out is its own state). The copy is
the number, not a nudge: no accent, no red, no timer. An optional meter
shows the count against the threshold in plain ink. */
export function PdpLowStock({
inventory,
threshold = 10,
variantLabel,
restockNote,
showMeter = true,
className,
}: {
/** Real units on hand for the selected variant. */
inventory: number
/** Show the line only at or below this count. */
threshold?: number
variantLabel?: string
/** Optional honest follow up, e.g. "More arriving Nov 4". */
restockNote?: string
showMeter?: boolean
className?: string
}) {
const reduce = useReducedMotion()
const visible = Number.isFinite(inventory) && inventory > 0 && inventory <= threshold
const n = Math.floor(inventory)
const copy = `${n} left${variantLabel ? ` in ${variantLabel}` : " in stock"}`
const segments = Math.min(threshold, 10)
const filled = Math.max(1, Math.round((n / threshold) * segments))
return (
<div data-sk-section="pdp" data-sk-variant="pdp-low-stock" className={cn("w-full", className)} aria-live="polite">
<AnimatePresence initial={false} mode="popLayout">
{visible ? (
<motion.p
key={copy}
initial={{ opacity: 0, y: reduce ? 0 : 6 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: reduce ? 0 : -6 }}
transition={{ duration: reduce ? 0 : 0.3, ease: [0.16, 1, 0.3, 1] }}
className="flex flex-wrap items-center gap-x-3 gap-y-1.5 text-sm"
>
{showMeter ? (
<span aria-hidden className="flex gap-[3px]">
{Array.from({ length: segments }).map((_, i) => (
<span key={i} className={cn("h-2.5 w-1.5 rounded-[1px]", i < filled ? "bg-sk-ink" : "bg-sk-ink/15")} />
))}
</span>
) : null}
<span className="font-medium tabular-nums text-sk-ink">{copy}</span>
{restockNote ? <span className="text-sk-muted">{restockNote}</span> : null}
</motion.p>
) : null}
</AnimatePresence>
</div>
)
}
Usage
Pass the live inventory count of the selected variant. Never pass a made up number.