Flip Clock
NewmotionMechanical 3D split-flap clock and dynamic counter built with Framer Motion — real-time clock, countdown, stopwatch, date-time, and counter modes with zero external animation dependencies.
$ pnpm dlx shadcn@latest add @byphongphan/flip-clock@byphongphan in components.jsonLive Interactive Stage
The Flip Clock is an authentic mechanical split-flap display built natively with Framer Motion (motion), React 19, and CSS 3D perspective transforms. It replicates physical airport departure boards, retro Solari di Udine clocks, and vintage train timetable displays with realistic flap-fold dynamics, internal lighting gradients, and zero third-party canvas engines.
Installation
Install the required dependencies:
$ pnpm add motion lucide-react@byphongphan in components.jsonCopy and paste the component into your project:
Update the import paths to match your project setup.
Usage
1. Real-time Local Clock
Displays hours, minutes, and seconds synchronized with local system time.
2. Date & Time with Weekday & Month
Shows Day of week (WED), Day of Month (17), Month (09), Year (2026), alongside hours, minutes, and seconds.
3. Countdown Timer
Counts down towards a specific target timestamp or duration with zero-time callback.
4. Stopwatch / Elapsed Time
Counts up with pause, resume, and reset capabilities.
5. Dynamic Counter
Flips arbitrary numeric or string values (e.g. live visitor counts, fundraising totals).
Engineering & Architecture
- Custom 3D Motion Physics: Powered natively by Framer Motion (
motion) and CSS 3D perspective transforms (rotateX,preserve-3d, backface culling) with realistic flap-folding dynamics, subpixel border alignment, and internal gradient shading without heavy third-party canvas engines. - SSR & Hydration Resilient: Microtask-deferred initial state calculation and declarative template reconciliation prevent hydration mismatches across static site generation (SSG) in Vite and TanStack Start.
- Synthesized Web Audio Clicks: Generates procedural mechanical split-flap click sounds via the browser's native Web Audio API oscillator synthesis — requiring zero external audio assets or third-party sound libraries.
- Container Query Scaling: Supports standard fixed scales (
sm,md,lg,xl) and a fluidsize="full"mode powered by CSS Container Queries ([container-type:inline-size]andcqw), adapting seamlessly to fill 100% of any parent container.
API Reference
FlipClock
| Prop | Type | Default | Description |
|---|---|---|---|
mode? | "clock" | "date-time" | "countdown" | "stopwatch" | "counter" | "clock" | Active operating mode |
size? | "sm" | "md" | "lg" | "xl" | "full" | "md" | Dimension scale of cards ("full" fluidly fills parent container) |
variant? | "default" | "blueprint" | "amber" | "outline" | "default" | Color and texture theme |
value? | string | number | — | Numerical or string value for "counter" mode |
label? | string | — | Text label for "counter" mode |
targetDate? | Date | string | number | — | Target deadline for "countdown" mode |
durationSeconds? | number | — | Duration in seconds for countdown timer |
isPaused? | boolean | false | Pauses clock, countdown, or stopwatch ticking |
format12h? | boolean | false | 12-hour display format |
showAmPm? | boolean | true | Renders AM/PM indicator in 12h clock mode |
showDays? | boolean | true | Renders Days group (countdown mode) |
showDayOfWeek? | boolean | true | Renders weekday (e.g. MON, TUE) in date-time mode |
showDate? | boolean | true | Renders day of month in date-time mode |
showMonth? | boolean | true | Renders month in date-time mode |
showYear? | boolean | true | Renders year in date-time mode |
showHours? | boolean | true | Renders hours unit |
showMinutes? | boolean | true | Renders minutes unit |
showSeconds? | boolean | true | Renders seconds unit |
showLabels? | boolean | true | Renders unit labels beneath cards |
showSeparators? | boolean | true | Renders separators (:, /, etc.) |
separator? | string | ":" | Custom separator character |
sound? | boolean | false | Plays procedural mechanical split-flap click sound on update |
onComplete? | () => void | — | Callback fired when countdown timer reaches zero |
className? | string | — | Additional Tailwind CSS classes |