Docs

Score Card

This Score-card component is designed to track and update scores for two teams in real-time with a simple animation showing which team scored.

requires interactionClick score button

Installation

Install dependencies

npm install framer-motion

Run the following command

It will create a new file called score-card.tsx inside the components/animata/card directory.

mkdir -p components/animata/card && touch components/animata/card/score-card.tsx

Paste the code

Open the newly created file and paste the following code:

import React, { useState } from "react";
import { motion } from "framer-motion";
 
interface Team {
  name: string;
  logo: string;
}
 
interface ScoreProps {
  homeTeam: Team;
  awayTeam: Team;
  homeScore: number;
  awayScore: number;
  matchTime: string;
  scorer: string;
}
 
export default function LiveScoreWidget({
  homeTeam,
  awayTeam,
  homeScore,
  awayScore,
  matchTime,
  scorer,
}: ScoreProps) {
  const [scored, setScored] = useState(false);
  const [awScore, setAwScore] = useState(awayScore);
  const [popAnimation, setPopAnimation] = useState(false);
 
  return (
    <div className="p-10">
      <motion.div
        className={`rounded-3xl ${scored ? "bg-[#09374d]" : "bg-none"} p-1`}
        animate={{ height: scored ? 160 : 100 }}
        transition={{ type: "spring", stiffness: 200, damping: 20 }}
      >
        <div className="mx-auto flex w-[440px] items-center justify-evenly rounded-3xl bg-black p-4 text-white">
          {/* Home Team */}
          <div className="flex flex-col">
            <img
              src={homeTeam.logo}
              alt={homeTeam.name}
              className="mb-2 h-[70px] w-[70px] object-contain"
            />
            {!scored && <span>{homeTeam.name}</span>}
          </div>
 
          {/* Score */}
          <div className="text-center">
            <motion.div
              className="text-4xl font-bold"
              animate={popAnimation ? { opacity: [1, 0, 1] } : { opacity: 1 }} // Popping animation
              transition={{ duration: 0.5 }} // Control animation speed
              onAnimationComplete={() => setPopAnimation(false)}
            >
              {homeScore}-{awScore}
            </motion.div>
            <div className="text-base">{matchTime}</div>
          </div>
 
          {/* Away Team */}
          <div className="flex flex-col">
            <img
              src={awayTeam.logo}
              alt={awayTeam.name}
              className="mb-2 h-[70px] w-[70px] object-contain"
            />
            {!scored && <span>{awayTeam.name}</span>}
          </div>
        </div>
        {scored && (
          <motion.div
            className="py-2"
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            transition={{ duration: 4 }}
          >
            <div className="flex items-center justify-between">
              <div className="ml-4 flex items-center text-lg text-white">
                <FootbalIcon />
                <span className="ml-2 text-white">{scorer} scores!</span>
              </div>
              <span className="mr-4 text-lg text-slate-500">now</span>
            </div>
          </motion.div>
        )}
      </motion.div>
 
      <button
        className="absolute bottom-4 right-4 rounded-full bg-white p-2"
        onClick={() => {
          setScored(true);
          setPopAnimation(true);
          setTimeout(() => {
            setAwScore(awScore + 1);
          }, 500);
          setTimeout(() => {
            setScored(false);
          }, 3000);
        }}
      >
        Score
      </button>
    </div>
  );
}
 
function FootbalIcon() {
  return (
    <svg
      fill="#ffffff"
      width="20px"
      height="20px"
      viewBox="0 0 24 24"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path d="M19.071 4.929a9.936 9.936 0 0 0-7.07-2.938 9.943 9.943 0 0 0-7.072 2.938c-3.899 3.898-3.899 10.243 0 14.142a9.94 9.94 0 0 0 7.073 2.938 9.936 9.936 0 0 0 7.07-2.937c3.899-3.898 3.899-10.243-.001-14.143zM12.181 4h-.359c.061-.001.119-.009.18-.009s.118.008.179.009zm6.062 13H16l-1.258 2.516a7.956 7.956 0 0 1-2.741.493 7.96 7.96 0 0 1-2.746-.494L8 17.01H5.765a7.96 7.96 0 0 1-1.623-3.532L6 11 4.784 8.567a7.936 7.936 0 0 1 1.559-2.224 7.994 7.994 0 0 1 3.22-1.969L12 6l2.438-1.625a8.01 8.01 0 0 1 3.22 1.968 7.94 7.94 0 0 1 1.558 2.221L18 11l1.858 2.478A7.952 7.952 0 0 1 18.243 17z" />
      <path d="m8.5 11 1.5 4h4l1.5-4L12 8.5z" />
    </svg>
  );
}

Credits

Built by Prince Yadav