ComponentsCountdown Timer

Credit goes to alberduris for re-creating this ShipFast component.

Table of Contents:

A countdown timer showing days, hours, minutes, and seconds left. Can be used for counting down till Product Hunt launch.

Countdown Timer Component

Code

/components/CountdownTimer.tsx

1"use client";
2
3import React from "react";
4
5type CountdownTimerProps = {
6  days: number | string;
7  hours: number | string;
8  minutes: number | string;
9  seconds: number | string;
10};
11
12const CountdownTimer = ({
13  initialTimeLeft,
14}: {
15  initialTimeLeft: CountdownTimerProps;
16}) => {
17  const [timeLeft, setTimeLeft] = React.useState(initialTimeLeft);
18
19  const calculateTimeLeft = () => {
20    const difference = +new Date("2024-02-01") - +new Date();
21    let timeLeft = { days: 0, hours: 0, minutes: 0, seconds: 0 };
22
23    if (difference > 0) {
24      timeLeft = {
25        days: Math.floor(difference / (1000 * 60 * 60 * 24)),
26        hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
27        minutes: Math.floor((difference / 1000 / 60) % 60),
28        seconds: Math.floor((difference / 1000) % 60), // Calculate seconds
29      };
30    }
31
32    return timeLeft;
33  };
34
35  React.useEffect(() => {
36    const timer = setTimeout(() => {
37      setTimeLeft(calculateTimeLeft());
38    }, 1000); // Update every second
39    return () => clearTimeout(timer); // Clear the timer on component unmount
40  }, [timeLeft]);
41
42  return (
43    <div className="flex items-center justify-center gap-4 text-center">
44      <div>
45        <p className="mb-2 text-base text-gray-600 dark:text-gray-400">
46          The Starter Kit is launching soon...
47        </p>
48        <div className="flex gap-4 rounded-lg bg-white p-3 text-center shadow-lg md:p-4 dark:bg-primary">
49          <div>
50            <p className="text-lg font-extrabold text-gray-900 dark:text-gray-100">
51              {timeLeft.days}
52            </p>
53            <p className="text-gray-900 dark:text-gray-100">Days</p>
54          </div>
55          <div>
56            <p className="text-lg font-extrabold text-gray-900 dark:text-gray-100">
57              {timeLeft.hours}
58            </p>
59            <p className="text-gray-900 dark:text-gray-100">Hours</p>
60          </div>
61          <div>
62            <p className="text-lg font-extrabold text-gray-900 dark:text-gray-100">
63              {timeLeft.minutes}
64            </p>
65            <p className="text-gray-900 dark:text-gray-100">Minutes</p>
66          </div>
67          <div>
68            <p className="text-lg font-extrabold text-gray-900 dark:text-gray-100">
69              {timeLeft.seconds}
70            </p>
71            <p className="text-gray-900 dark:text-gray-100">Seconds</p>
72          </div>
73        </div>
74      </div>
75    </div>
76  );
77};
78
79export default CountdownTimer;

Usage

/components/Pricing.tsx

1import CountdownTimer from "./CountdownTimer";
2
3const Pricing = () => {
4  return (
5    <>
6      <section>
7        ...
8        <CountdownTimer initialTimeLeft={10} />
9        ...
10      </section>
11    </>
12  );
13};
14
15export default Pricing;