Componentmedia0.76 KB gzipZero dependencies

Countdown Start

Match opener with auto 3-2-1 tick.

Preview

Live Preview
Match Start

Installation

Tokens guide →

Add to your project via CLI (zero dependencies, code you own):

npx bigbullui add countdown-start

Or install the full npm package:

npm install bigbullui
import { CountdownStart } from "@/components/ui/countdown-start";

<CountdownStart />

Usage guidance

Use Countdown Start when a ticket stub surface needs Match opener with auto 3-2-1 tick. Keep props minimal and prefer composition with sibling stubs.

Avoid Countdown Start for long form flows or dense data grids where a dedicated layout block fits better.

Source code

countdown-start.tsx

Zero dependencies (only React + utils). Copy and paste directly into your project:

"use client";

import * as React from "react";
import { cn } from "./lib/utils";

export interface CountdownStartProps extends React.HTMLAttributes<HTMLDivElement> {
  from?: number;
  onGo?: () => void;
}

/** Countdown start: 3-2-1-GO match opener with auto tick. */
export function CountdownStart({ from = 3, onGo, className, ...props }: CountdownStartProps) {
  const [n, setN] = React.useState(from);
  React.useEffect(() => {
    setN(from);
  }, [from]);
  React.useEffect(() => {
    if (n <= 0) {
      onGo?.();
      return;
    }
    const t = setTimeout(() => setN((v) => v - 1), 900);
    return () => clearTimeout(t);
  }, [n, onGo]);
  return (
    <div
      role="timer"
      aria-label={n > 0 ? `Match starts in ${n}` : "Go"}
      className={cn("flex min-h-11 touch-none select-none flex-col items-center gap-1 rounded-md border-2 border-foreground bg-card px-6 py-3", className)}
      style={{ touchAction: "none" }}
      {...props}
    >
      <style>{`@keyframes countZoom { 0% { transform: scale(0.6); opacity: 0; } 40% { opacity: 1; } 100% { transform: scale(1.15); } }`}</style>
      <span key={n} className="animate-[countZoom_0.85s_ease-out] font-mono text-4xl font-black tabular-nums motion-reduce:animate-none" aria-hidden="true">
        {n > 0 ? n : "GO"}
      </span>
      <span className="font-mono text-[10px] uppercase tracking-[0.25em] text-muted-foreground">Match Start</span>
    </div>
  );
}