Commerce & Checkout

Product Drop Countdown

A limited-release drop board with a built-in flip countdown, a CTA that unlocks at launch, and a three-state machine ending in a restock notification form once it sells out.

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

npx webberui@latest add product-drop-countdown.en

New project or installation trouble? Start here →

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

200
Active edited usageDefault props
<ProductDropCountdown/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

Installation

npx webberui@latest add https://webberui.com/r/product-drop-countdown.en.json

Or, once registries are configured in components.json, install it as @webberui/product-drop-countdown.

Usage

import { ProductDropCountdown } from "@/components/ui/product-drop-countdown";

<ProductDropCountdown
  title="Aero Runner 3"
  subtitle="Limited collab colorway"
  price="NT$4,280"
  dropAt={Date.now() + 1000 * 60 * 60}
  totalStock={180}
  onPurchase={() => console.log("add to cart")}
  onNotify={(email) => console.log("restock notification", email)}
/>

The three states are derived automatically from dropAt and stock: reaching zero on the countdown enters the live state, and selling out of stock enters the sold-out state. To hand control to an outside state machine, pass a controlled state:

<ProductDropCountdown title="Aero Runner 3" dropAt={dropAt} state="soldout" />

Stock can be controlled too, driving the depletion bar directly through sold; when it is not provided, depletion is simulated automatically after launch:

<ProductDropCountdown title="Aero Runner 3" dropAt={dropAt} totalStock={200} sold={soldSoFar} />

Props

PropTypeDefaultDescription
titlestring—Product name
subtitlestring—Subtitle / model number and other secondary detail
pricestring—Price display string
dropAtDate | number—Release time; goes live automatically when the countdown reaches zero
totalStocknumber200Total stock units, driving the depletion bar and the sold-out determination
soldnumber—Controlled number sold; when not provided, depletion is simulated automatically after launch
state"countdown" | "live" | "soldout"—Controlled three states; when provided, the automatic derivation is ignored
ctaLabelstring"Buy now"Copy on the purchase CTA
onDrop() => void—Fires once on entering the live state
onSoldOut() => void—Fires once on selling out
onPurchase() => void—Fires when the purchase CTA is clicked
onNotify(email: string) => void—Fires when the restock notification form is submitted

How it works

  • Flip clock: every digit is its own flip card; when the value changes, the front leaf falls down around its bottom edge while the back leaf flips back around its top edge, implemented with CSS 3D rotateX and updated frame by frame.
  • Launch unlock: the moment the countdown reaches zero, the locked CTA springs in and scales up on an elastic spring (stiffness: 440, damping: 12), and the stock depletion bar starts at the same time, turning amber and then red as the remaining proportion drops below 50% and 20%.
  • Sold-out desaturation: once stock hits zero, the whole section is desaturated with a grayscale filter and its opacity is lowered, and the restock notification form slides in from below; the form itself stays in full color so it remains readable and usable.

Accessibility

  • The countdown carries role="timer" and a readable aria-label (for example "1 hour 0 minutes 12 seconds until release"), while the flip digits are hidden from assistive technology (aria-hidden).
  • Remaining stock is announced through aria-live="polite", so screen readers pick up the changes in the live state.
  • The restock form's input carries a label and an aria-label and can be submitted with Enter; the CTA and the submit button both have focus-visible outlines.
  • When the user has "reduce motion" enabled at the system level, the flip switches directly, the CTA and the form fade in instead, and the desaturation completes instantly — none of which affects the three-state logic.