DEV Community

Cover image for Building a Dynamic Game Leaderboard Modal with React and Tailwind CSS
Johnny Santamaria
Johnny Santamaria

Posted on

Building a Dynamic Game Leaderboard Modal with React and Tailwind CSS

Explore the steps to create a sleek and adaptive leaderboard modal using React and Tailwind CSS.

“In a world that’s changing really quickly, the only strategy that is guaranteed to fail is not taking risks.” – Mark Zuckerberg

  • Mark Zuckerberg is the co-founder and CEO of Facebook, who has seen firsthand how competitive elements in social platforms, including gaming, drive user engagement and innovation. The quote is from an October 2011 interview at Y Combinator’s Startup School in Palo Alto, California.

If you want to see yesterday's challenge: Analytics in React

If you're going to try the challenge yourself: DailyUI

So I missed a total of two challenges, life happens…

So I came up with a prompt combining the idea of creating a leaderboard with the idea of creating a popup overlay screen

Prompt: Create a popup of a leaderboard

  • Is it a for a game? politics? movies? How would the overlay be closed?

So today, we're designing a game leaderboard popup, combining engaging competitive elements with smooth user interaction. I've created an interactive popup that displays player rankings while maintaining performance and accessibility.

The interface should include:

  • Animated popup overlay with a backdrop

  • Player rankings with scores

  • Visual indicators for top positions

  • Player avatars and status

  • Smooth transitions

  • Close button functionality

  • Responsive design

The solution 💡

Here's the React component that brings together these requirements using Tailwind CSS and Lucide icons:

{/* LeaderBoardPopup.js */}

import React, { useState } from 'react';
import { X, Trophy, Medal } from 'lucide-react';

const LeaderboardPopup = () => {
  const [isOpen, setIsOpen] = useState(true);

  const leaderboardData = [
    { rank: 1, username: "ProGamer123", score: 25000, wins: 48 },
    { rank: 2, username: "NinjaWarrior", score: 23450, wins: 45 },
    { rank: 3, username: "PixelMaster", score: 22100, wins: 42 },
    { rank: 4, username: "GameKing99", score: 21000, wins: 39 },
    { rank: 5, username: "StarPlayer", score: 20500, wins: 37 }
  ];

  const getMedalColor = (rank) => { {/* Use CSS to edit the color */}
    switch(rank) {
      case 1: return "text-yellow-500";
      case 2: return "text-gray-400";
      case 3: return "text-amber-600";
      default: return "text-gray-600";
    }
  };

  if (!isOpen) return null;

  return (
    <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
      <div className="bg-white rounded-lg shadow-xl w-full max-w-md mx-4 relative overflow-hidden">
        {/* Header */}
        <div className="bg-indigo-600 p-4 flex justify-between items-center">
          <div className="flex items-center space-x-2">
            <Trophy className="text-white" size={24} />
            <h2 className="text-xl font-bold text-white">Top Players</h2>
          </div>
          <button 
            onClick={() => setIsOpen(false)}
            className="text-white hover:text-gray-200 transition-colors"
          >
            <X size={24} />
          </button>
        </div>

        {/* Leaderboard Content */}
        <div className="p-6">
          {leaderboardData.map((player) => (
            <div 
              key={player.rank}
              className="flex items-center justify-between mb-4 p-3 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors"
            >
              <div className="flex items-center space-x-4">
                <div className="flex items-center justify-center w-8">
                  {player.rank <= 3 ? (
                    <Medal className={getMedalColor(player.rank)} size={24} />
                  ) : (
                    <span className="text-gray-600 font-medium">{player.rank}</span>
                  )}
                </div>
                <div>
                  <p className="font-semibold text-gray-800">{player.username}</p>
                  <p className="text-sm text-gray-500">{player.wins} wins</p>
                </div>
              </div>
              <div className="text-right">
                <p className="font-bold text-indigo-600">{player.score.toLocaleString()}</p>
                <p className="text-xs text-gray-500">points</p>
              </div>
            </div>
          ))}
        </div>

        {/* Footer */}
        <div className="bg-gray-50 p-4 border-t">
          <p className="text-center text-sm text-gray-600">
            Rankings update every hour
          </p>
        </div>
      </div>
    </div>
  );
};

export default LeaderboardPopup;
Enter fullscreen mode Exit fullscreen mode

Note: This code looked like HTML didn’t it?

  • React uses a syntax called JSX (JavaScript XML), which allows you to write HTML-like code within JavaScript. Although it looks like HTML, it's actually a syntactic sugar over JavaScript and isn't pure HTML. JSX is compiled into JavaScript at runtime, where React elements are created.

To use this component in your application:

{/* app.js */}

import LeaderboardPopup from './LeaderboardPopup';

function App() {
  return (
    <div className="min-h-screen bg-gray-100">
      <LeaderboardPopup />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Run the code using Github codespaces:

1. Create a Repository on GitHub

  • Go to GitHub and create a new repository (e.g., leaderboard-app).

  • Initialize it with a README, or leave it empty.

2. Open GitHub Codespaces

  • Once your repository is created, go to the repository’s page on GitHub.

  • Click on the "Code" button and then select "Open with Codespaces"

  • Click on "New codespace" to open a fresh Codespace instance

3. Set up Your React App in Codespaces

  • In the terminal within GitHub Codespaces, run the following commands to set up a new React app:

    npx create-react-app leaderboard-app
    cd leaderboard-app
    
  • This will create a new React application and navigate into the leaderboard-app directory

4. Install Dependencies

  • Install any required dependencies, like lucide-react for the icons:

    npm install lucide-react
    

5. Add Your Code

  • In the Codespaces editor, go to the src folder and create a new file called LeaderboardPopup.js

  • Paste your LeaderboardPopup component code into this file

  • Open src/App.js and import the LeaderboardPopup component:

    import LeaderboardPopup from './LeaderboardPopup';
    
  • Then, add <LeaderboardPopup /> within the App component’s JSX.

6. Run Your App

  • In the Codespaces terminal, start your React development server:

    npm start
    
  • GitHub Codespaces will automatically open a preview window for your app, where you can see the LeaderboardPopup in action.

Some Notes:

  • Dependencies: Make sure all necessary dependencies (like lucide-react) are installed in the Codespace.

  • React app initialization: By running npx create-react-app leaderboard-app, you're initializing a new React app, so ensure the folder structure is correct (the app should be created in the leaderboard-app directory).

  • Preview: GitHub Codespaces automatically sets up a preview for your React app, so you'll be able to see your changes live.

Sample

Daily UI day 16 and 19

The component leverages several key features:

  • Tailwind CSS for responsive and modern styling

  • Lucide icons for consistent visual elements

  • React hooks for state management

  • Modal overlay for focused user attention

  • Responsive design that works on all devices

Key features implemented:

  • Clean, modern interface with a clear, visual hierarchy

  • Medal indicators for the top 3 players

  • Score and win statistics display

  • Interactive close functionality

  • Hover states for enhanced user feedback

  • Consistent spacing and typography

  • Responsive layout that adapts to screen size

To enhance this component further, consider:

  • Adding entrance/exit animations

  • Implementing sorting options

  • Including player avatars

  • Adding filtering capabilities

  • Supporting real-time updates

  • Including player progression tracking

Conclusion

Building an effective game leaderboard requires balancing visual appeal with functionality. This implementation demonstrates how modern React features and Tailwind CSS can be combined to create an engaging and responsive leaderboard interface. The modal approach ensures focused attention on the rankings while maintaining accessibility and user experience.

For future development, this approach offers several advantages. The component structure allows for easy feature expansion, while Tailwind CSS ensures consistent styling and responsiveness. The clear visual hierarchy helps players quickly understand their standing and encourages healthy competition.

Remember that a great leaderboard is more than just a list of scores – it's a tool for driving engagement and creating community within your game. This implementation provides the foundation for building an engaging competitive feature that can enhance player retention and satisfaction.

Top comments (0)