Dev Logs
/Tailwind CSS/ Final Project: Dashify - Complete Dashboard Application
Chapters
  • 01Introduction to Tailwind CSS
  • 02Installation and Setup
  • 03Tailwind Configuration
  • 04Typography and Spacing
  • 05Colors and Theme Customization
  • 06Flexbox Utilities
  • 07Responsive Design
  • 08Grid Utilities
  • 09Pseudo-Classes and State-Based Styling
  • 10Dark Mode
  • 11Customizing and Extending Tailwind Configuration
  • 12Advanced Layout Techniques
  • 13Final Project: Dashify - Complete Dashboard Application
    • Project Overview
    • Project Features
    • Project Structure
    • Complete Implementation
    • Main Dashboard (index.html)
    • JavaScript Files
    • Project Analysis
    • Tailwind CSS Concepts Demonstrated
    • Performance Optimizations
    • Learning Objectives
    • Technical Skills
    • Design Skills
    • Development Skills
    • Implementation Guide
    • Phase 1: Setup and Structure (30 minutes)
    • Phase 2: Core Components (45 minutes)
    • Phase 3: Advanced Features (45 minutes)
    • Phase 4: Polish and Testing (30 minutes)
    • Common Pitfalls and Solutions
    • Pitfall: Inconsistent Spacing
    • Pitfall: Overusing Custom CSS
    • Pitfall: Poor Dark Mode Implementation
    • Pitfall: Non-Responsive Design
    • Why This Project Matters
    • Real-World Application
    • Career Relevance
    • Skill Development
    • Performance Considerations
    • Build Time Optimization
    • Runtime Performance
    • Mobile Performance
    • Mini-Challenges
    • Challenge 1: Add a Settings Page
    • Challenge 2: Implement Data Filtering
    • Challenge 3: Create a Calendar View
    • Interview Tips
    • Technical Questions You Should Be Able to Answer
    • Conclusion
    • What You've Accomplished
    • Next Steps
All chapters

Final Project: Dashify - Complete Dashboard Application

Project Overview

Dashify is a comprehensive dashboard application that demonstrates all the Tailwind CSS concepts covered in this learning resource. This project will serve as your capstone, integrating responsive design, component patterns, advanced layouts, dark mode, and modern UI practices.

Project Features

  • Responsive Dashboard Layout - Works on all device sizes
  • Dark Mode Support - Toggle between light and dark themes
  • Interactive Components - Modals, dropdowns, tabs, and forms
  • Data Visualization - Charts and statistics displays
  • Advanced Layout Patterns - Grid, flexbox, and positioning
  • Component Library - Reusable UI components
  • Performance Optimized - Efficient CSS and smooth animations

Project Structure

dashify/
├── index.html              # Main dashboard page
├── assets/
│   ├── css/
│   │   └── styles.css      # Custom styles (if needed)
│   ├── js/
│   │   ├── main.js         # Main JavaScript functionality
│   │   ├── charts.js       # Chart implementations
│   │   └── components.js   # Component interactions
│   └── images/
│       └── (placeholder images)
└── components/
    ├── sidebar.html        # Sidebar component
    ├── header.html         # Header component
    └── modals.html         # Modal components

Complete Implementation

Main Dashboard (index.html)

html
<!DOCTYPE html>
<html lang="en" class="h-full">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Dashify - Modern Dashboard</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script>
      tailwind.config = {
        darkMode: "class",
        theme: {
          extend: {
            colors: {
              primary: {
                50: "#eff6ff",
                500: "#3b82f6",
                600: "#2563eb",
                700: "#1d4ed8",
                900: "#1e3a8a",
              },
            },
            animation: {
              "fade-in": "fadeIn 0.5s ease-in-out",
              "slide-in": "slideIn 0.3s ease-out",
            },
          },
        },
      };
    </script>
    <style>
      @keyframes fadeIn {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
        }
      }
      @keyframes slideIn {
        from {
          transform: translateX(-100%);
        }
        to {
          transform: translateX(0);
        }
      }
    </style>
  </head>
  <body
    class="h-full bg-gray-50 dark:bg-gray-900 transition-colors duration-300"
  >
    <div class="flex h-full">
      <!-- Sidebar -->
      <aside
        id="sidebar"
        class="fixed inset-y-0 left-0 z-50 w-64 bg-white dark:bg-gray-800 shadow-lg transform -translate-x-full lg:translate-x-0 lg:static lg:inset-0 transition-transform duration-300 ease-in-out"
      >
        <div
          class="flex items-center justify-between h-16 px-6 border-b border-gray-200 dark:border-gray-700"
        >
          <div class="flex items-center space-x-3">
            <div
              class="w-8 h-8 bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg flex items-center justify-center"
            >
              <svg
                class="w-5 h-5 text-white"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M13 10V3L4 14h7v7l9-11h-7z"
                ></path>
              </svg>
            </div>
            <span class="text-xl font-bold text-gray-900 dark:text-white"
              >Dashify</span
            >
          </div>
          <button
            id="sidebar-close"
            class="lg:hidden p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700"
          >
            <svg
              class="w-6 h-6"
              fill="none"
              stroke="currentColor"
              viewBox="0 0 24 24"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M6 18L18 6M6 6l12 12"
              ></path>
            </svg>
          </button>
        </div>

        <nav class="mt-6 px-3">
          <div class="space-y-1">
            <a
              href="#"
              class="bg-blue-50 dark:bg-blue-900/50 text-blue-700 dark:text-blue-200 group flex items-center px-3 py-2 text-sm font-medium rounded-md"
            >
              <svg
                class="text-blue-500 mr-3 h-5 w-5"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z"
                ></path>
              </svg>
              Dashboard
            </a>
            <a
              href="#"
              class="text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 group flex items-center px-3 py-2 text-sm font-medium rounded-md"
            >
              <svg
                class="text-gray-400 mr-3 h-5 w-5"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13.5-9a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z"
                ></path>
              </svg>
              Users
            </a>
            <a
              href="#"
              class="text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 group flex items-center px-3 py-2 text-sm font-medium rounded-md"
            >
              <svg
                class="text-gray-400 mr-3 h-5 w-5"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
                ></path>
              </svg>
              Analytics
            </a>
            <a
              href="#"
              class="text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 group flex items-center px-3 py-2 text-sm font-medium rounded-md"
            >
              <svg
                class="text-gray-400 mr-3 h-5 w-5"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"
                ></path>
              </svg>
              Projects
            </a>
            <a
              href="#"
              class="text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 group flex items-center px-3 py-2 text-sm font-medium rounded-md"
            >
              <svg
                class="text-gray-400 mr-3 h-5 w-5"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
                ></path>
              </svg>
              Calendar
            </a>
            <a
              href="#"
              class="text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 group flex items-center px-3 py-2 text-sm font-medium rounded-md"
            >
              <svg
                class="text-gray-400 mr-3 h-5 w-5"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
                ></path>
              </svg>
              Documents
            </a>
            <a
              href="#"
              class="text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 group flex items-center px-3 py-2 text-sm font-medium rounded-md"
            >
              <svg
                class="text-gray-400 mr-3 h-5 w-5"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M16 8v8m-4-5v5m-4-2v2m-2 4h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
                ></path>
              </svg>
              Reports
            </a>
          </div>

          <div class="mt-8">
            <h3
              class="px-3 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider"
            >
              Teams
            </h3>
            <div class="mt-2 space-y-1">
              <a
                href="#"
                class="text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 group flex items-center px-3 py-2 text-sm font-medium rounded-md"
              >
                <span
                  class="w-2.5 h-2.5 mr-3 bg-indigo-500 rounded-full"
                ></span>
                Engineering
              </a>
              <a
                href="#"
                class="text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 group flex items-center px-3 py-2 text-sm font-medium rounded-md"
              >
                <span class="w-2.5 h-2.5 mr-3 bg-green-500 rounded-full"></span>
                Design
              </a>
              <a
                href="#"
                class="text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 group flex items-center px-3 py-2 text-sm font-medium rounded-md"
              >
                <span
                  class="w-2.5 h-2.5 mr-3 bg-yellow-500 rounded-full"
                ></span>
                Marketing
              </a>
            </div>
          </div>
        </nav>

        <div class="absolute bottom-0 left-0 right-0 p-4">
          <div class="bg-blue-50 dark:bg-blue-900/50 rounded-lg p-4">
            <h4 class="text-sm font-medium text-blue-900 dark:text-blue-200">
              Upgrade to Pro
            </h4>
            <p class="text-xs text-blue-700 dark:text-blue-300 mt-1">
              Get access to advanced features
            </p>
            <button
              class="mt-3 w-full bg-blue-600 text-white text-xs font-medium py-2 px-3 rounded-md hover:bg-blue-700 transition-colors"
            >
              Upgrade Now
            </button>
          </div>
        </div>
      </aside>

      <!-- Sidebar overlay for mobile -->
      <div
        id="sidebar-overlay"
        class="fixed inset-0 bg-gray-600 bg-opacity-75 z-40 lg:hidden hidden"
      ></div>

      <!-- Main content -->
      <div class="flex-1 flex flex-col lg:ml-0">
        <!-- Header -->
        <header
          class="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700"
        >
          <div
            class="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8"
          >
            <div class="flex items-center">
              <button
                id="sidebar-toggle"
                class="lg:hidden p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700"
              >
                <svg
                  class="w-6 h-6"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                >
                  <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="2"
                    d="M4 6h16M4 12h16M4 18h16"
                  ></path>
                </svg>
              </button>
              <h1
                class="ml-4 lg:ml-0 text-2xl font-semibold text-gray-900 dark:text-white"
              >
                Dashboard
              </h1>
            </div>

            <div class="flex items-center space-x-4">
              <!-- Search -->
              <div class="hidden md:block">
                <div class="relative">
                  <div
                    class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"
                  >
                    <svg
                      class="h-5 w-5 text-gray-400"
                      fill="none"
                      stroke="currentColor"
                      viewBox="0 0 24 24"
                    >
                      <path
                        stroke-linecap="round"
                        stroke-linejoin="round"
                        stroke-width="2"
                        d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
                      ></path>
                    </svg>
                  </div>
                  <input
                    type="text"
                    placeholder="Search..."
                    class="block w-full pl-10 pr-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md leading-5 bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
                  />
                </div>
              </div>

              <!-- Dark mode toggle -->
              <button
                id="theme-toggle"
                class="p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700"
              >
                <svg
                  id="theme-toggle-dark-icon"
                  class="hidden w-5 h-5"
                  fill="currentColor"
                  viewBox="0 0 20 20"
                >
                  <path
                    d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"
                  ></path>
                </svg>
                <svg
                  id="theme-toggle-light-icon"
                  class="hidden w-5 h-5"
                  fill="currentColor"
                  viewBox="0 0 20 20"
                >
                  <path
                    fill-rule="evenodd"
                    d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
                    clip-rule="evenodd"
                  ></path>
                </svg>
              </button>

              <!-- Notifications -->
              <button
                class="p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700 relative"
              >
                <svg
                  class="w-6 h-6"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                >
                  <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="2"
                    d="M15 17h5l-5 5v-5zM10.97 4.97a.235.235 0 0 0-.02 0L9.97 5a.75.75 0 0 1-1.06-1.06l.99-.99c.441-.441 1.12-.441 1.561 0a.75.75 0 0 1 0 1.06l-.99.99zM4.5 8.5a.75.75 0 0 1 .75-.75h1a.75.75 0 0 1 0 1.5h-1a.75.75 0 0 1-.75-.75zM8.5 4.5a.75.75 0 0 1 .75-.75h1a.75.75 0 0 1 0 1.5h-1a.75.75 0 0 1-.75-.75z"
                  ></path>
                </svg>
                <span
                  class="absolute top-0 right-0 block h-2 w-2 rounded-full bg-red-400 ring-2 ring-white dark:ring-gray-800"
                ></span>
              </button>

              <!-- Profile dropdown -->
              <div class="relative">
                <button
                  id="profile-button"
                  class="flex items-center space-x-3 text-sm rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
                >
                  <img
                    class="h-8 w-8 rounded-full"
                    src="https://via.placeholder.com/32x32"
                    alt="Profile"
                  />
                  <span class="hidden md:block text-gray-700 dark:text-gray-300"
                    >John Doe</span
                  >
                  <svg
                    class="hidden md:block w-4 h-4 text-gray-400"
                    fill="none"
                    stroke="currentColor"
                    viewBox="0 0 24 24"
                  >
                    <path
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      stroke-width="2"
                      d="M19 9l-7 7-7-7"
                    ></path>
                  </svg>
                </button>

                <!-- Profile dropdown menu -->
                <div
                  id="profile-dropdown"
                  class="hidden absolute right-0 mt-2 w-48 bg-white dark:bg-gray-800 rounded-md shadow-lg py-1 z-50"
                >
                  <a
                    href="#"
                    class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
                    >Your Profile</a
                  >
                  <a
                    href="#"
                    class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
                    >Settings</a
                  >
                  <a
                    href="#"
                    class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
                    >Sign out</a
                  >
                </div>
              </div>
            </div>
          </div>
        </header>

        <!-- Main content area -->
        <main class="flex-1 overflow-y-auto p-4 sm:p-6 lg:p-8">
          <!-- Stats cards -->
          <div
            class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"
          >
            <div
              class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg animate-fade-in"
            >
              <div class="p-5">
                <div class="flex items-center">
                  <div class="flex-shrink-0">
                    <div
                      class="w-8 h-8 bg-blue-500 rounded-md flex items-center justify-center"
                    >
                      <svg
                        class="w-5 h-5 text-white"
                        fill="none"
                        stroke="currentColor"
                        viewBox="0 0 24 24"
                      >
                        <path
                          stroke-linecap="round"
                          stroke-linejoin="round"
                          stroke-width="2"
                          d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13.5-9a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z"
                        ></path>
                      </svg>
                    </div>
                  </div>
                  <div class="ml-5 w-0 flex-1">
                    <dl>
                      <dt
                        class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate"
                      >
                        Total Users
                      </dt>
                      <dd
                        class="text-lg font-medium text-gray-900 dark:text-white"
                      >
                        71,897
                      </dd>
                    </dl>
                  </div>
                </div>
              </div>
              <div class="bg-gray-50 dark:bg-gray-700 px-5 py-3">
                <div class="text-sm">
                  <span class="text-green-600 dark:text-green-400 font-medium"
                    >+12%</span
                  >
                  <span class="text-gray-500 dark:text-gray-400">
                    from last month</span
                  >
                </div>
              </div>
            </div>

            <div
              class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg animate-fade-in"
              style="animation-delay: 0.1s"
            >
              <div class="p-5">
                <div class="flex items-center">
                  <div class="flex-shrink-0">
                    <div
                      class="w-8 h-8 bg-green-500 rounded-md flex items-center justify-center"
                    >
                      <svg
                        class="w-5 h-5 text-white"
                        fill="none"
                        stroke="currentColor"
                        viewBox="0 0 24 24"
                      >
                        <path
                          stroke-linecap="round"
                          stroke-linejoin="round"
                          stroke-width="2"
                          d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
                        ></path>
                      </svg>
                    </div>
                  </div>
                  <div class="ml-5 w-0 flex-1">
                    <dl>
                      <dt
                        class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate"
                      >
                        Revenue
                      </dt>
                      <dd
                        class="text-lg font-medium text-gray-900 dark:text-white"
                      >
                        $405,091
                      </dd>
                    </dl>
                  </div>
                </div>
              </div>
              <div class="bg-gray-50 dark:bg-gray-700 px-5 py-3">
                <div class="text-sm">
                  <span class="text-green-600 dark:text-green-400 font-medium"
                    >+8.2%</span
                  >
                  <span class="text-gray-500 dark:text-gray-400">
                    from last month</span
                  >
                </div>
              </div>
            </div>

            <div
              class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg animate-fade-in"
              style="animation-delay: 0.2s"
            >
              <div class="p-5">
                <div class="flex items-center">
                  <div class="flex-shrink-0">
                    <div
                      class="w-8 h-8 bg-yellow-500 rounded-md flex items-center justify-center"
                    >
                      <svg
                        class="w-5 h-5 text-white"
                        fill="none"
                        stroke="currentColor"
                        viewBox="0 0 24 24"
                      >
                        <path
                          stroke-linecap="round"
                          stroke-linejoin="round"
                          stroke-width="2"
                          d="M16 11V7a4 4 0 00-8 0v4M8 11v6h8v-6M8 11H6a2 2 0 00-2 2v6a2 2 0 002 2h12a2 2 0 002-2v-6a2 2 0 00-2-2h-2"
                        ></path>
                      </svg>
                    </div>
                  </div>
                  <div class="ml-5 w-0 flex-1">
                    <dl>
                      <dt
                        class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate"
                      >
                        Sales
                      </dt>
                      <dd
                        class="text-lg font-medium text-gray-900 dark:text-white"
                      >
                        12,234
                      </dd>
                    </dl>
                  </div>
                </div>
              </div>
              <div class="bg-gray-50 dark:bg-gray-700 px-5 py-3">
                <div class="text-sm">
                  <span class="text-red-600 dark:text-red-400 font-medium"
                    >-3.1%</span
                  >
                  <span class="text-gray-500 dark:text-gray-400">
                    from last month</span
                  >
                </div>
              </div>
            </div>

            <div
              class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg animate-fade-in"
              style="animation-delay: 0.3s"
            >
              <div class="p-5">
                <div class="flex items-center">
                  <div class="flex-shrink-0">
                    <div
                      class="w-8 h-8 bg-purple-500 rounded-md flex items-center justify-center"
                    >
                      <svg
                        class="w-5 h-5 text-white"
                        fill="none"
                        stroke="currentColor"
                        viewBox="0 0 24 24"
                      >
                        <path
                          stroke-linecap="round"
                          stroke-linejoin="round"
                          stroke-width="2"
                          d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"
                        ></path>
                      </svg>
                    </div>
                  </div>
                  <div class="ml-5 w-0 flex-1">
                    <dl>
                      <dt
                        class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate"
                      >
                        Performance
                      </dt>
                      <dd
                        class="text-lg font-medium text-gray-900 dark:text-white"
                      >
                        98.2%
                      </dd>
                    </dl>
                  </div>
                </div>
              </div>
              <div class="bg-gray-50 dark:bg-gray-700 px-5 py-3">
                <div class="text-sm">
                  <span class="text-green-600 dark:text-green-400 font-medium"
                    >+2.1%</span
                  >
                  <span class="text-gray-500 dark:text-gray-400">
                    from last month</span
                  >
                </div>
              </div>
            </div>
          </div>

          <!-- Charts and content -->
          <div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
            <!-- Chart -->
            <div class="bg-white dark:bg-gray-800 shadow rounded-lg p-6">
              <div class="flex items-center justify-between mb-4">
                <h3 class="text-lg font-medium text-gray-900 dark:text-white">
                  Revenue Overview
                </h3>
                <div class="flex space-x-2">
                  <button
                    class="text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"
                  >
                    7d
                  </button>
                  <button
                    class="text-sm text-blue-600 dark:text-blue-400 font-medium"
                  >
                    30d
                  </button>
                  <button
                    class="text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"
                  >
                    90d
                  </button>
                </div>
              </div>
              <div class="h-64">
                <canvas id="revenueChart"></canvas>
              </div>
            </div>

            <!-- Recent activity -->
            <div class="bg-white dark:bg-gray-800 shadow rounded-lg p-6">
              <h3
                class="text-lg font-medium text-gray-900 dark:text-white mb-4"
              >
                Recent Activity
              </h3>
              <div class="space-y-4">
                <div class="flex items-center space-x-4">
                  <div class="flex-shrink-0">
                    <img
                      class="h-8 w-8 rounded-full"
                      src="https://via.placeholder.com/32x32"
                      alt="User"
                    />
                  </div>
                  <div class="flex-1 min-w-0">
                    <p
                      class="text-sm font-medium text-gray-900 dark:text-white truncate"
                    >
                      John Doe
                    </p>
                    <p
                      class="text-sm text-gray-500 dark:text-gray-400 truncate"
                    >
                      Created a new project
                    </p>
                  </div>
                  <div class="text-sm text-gray-500 dark:text-gray-400">
                    2m ago
                  </div>
                </div>

                <div class="flex items-center space-x-4">
                  <div class="flex-shrink-0">
                    <img
                      class="h-8 w-8 rounded-full"
                      src="https://via.placeholder.com/32x32"
                      alt="User"
                    />
                  </div>
                  <div class="flex-1 min-w-0">
                    <p
                      class="text-sm font-medium text-gray-900 dark:text-white truncate"
                    >
                      Jane Smith
                    </p>
                    <p
                      class="text-sm text-gray-500 dark:text-gray-400 truncate"
                    >
                      Updated user permissions
                    </p>
                  </div>
                  <div class="text-sm text-gray-500 dark:text-gray-400">
                    5m ago
                  </div>
                </div>

                <div class="flex items-center space-x-4">
                  <div class="flex-shrink-0">
                    <img
                      class="h-8 w-8 rounded-full"
                      src="https://via.placeholder.com/32x32"
                      alt="User"
                    />
                  </div>
                  <div class="flex-1 min-w-0">
                    <p
                      class="text-sm font-medium text-gray-900 dark:text-white truncate"
                    >
                      Mike Johnson
                    </p>
                    <p
                      class="text-sm text-gray-500 dark:text-gray-400 truncate"
                    >
                      Completed task review
                    </p>
                  </div>
                  <div class="text-sm text-gray-500 dark:text-gray-400">
                    10m ago
                  </div>
                </div>

                <div class="flex items-center space-x-4">
                  <div class="flex-shrink-0">
                    <img
                      class="h-8 w-8 rounded-full"
                      src="https://via.placeholder.com/32x32"
                      alt="User"
                    />
                  </div>
                  <div class="flex-1 min-w-0">
                    <p
                      class="text-sm font-medium text-gray-900 dark:text-white truncate"
                    >
                      Sarah Wilson
                    </p>
                    <p
                      class="text-sm text-gray-500 dark:text-gray-400 truncate"
                    >
                      Uploaded new documents
                    </p>
                  </div>
                  <div class="text-sm text-gray-500 dark:text-gray-400">
                    15m ago
                  </div>
                </div>
              </div>

              <div class="mt-6">
                <button
                  class="w-full text-center text-sm text-blue-600 dark:text-blue-400 hover:text-blue-500 dark:hover:text-blue-300 font-medium"
                >
                  View all activity
                </button>
              </div>
            </div>
          </div>

          <!-- Projects table -->
          <div class="bg-white dark:bg-gray-800 shadow rounded-lg">
            <div
              class="px-6 py-4 border-b border-gray-200 dark:border-gray-700"
            >
              <div class="flex items-center justify-between">
                <h3 class="text-lg font-medium text-gray-900 dark:text-white">
                  Recent Projects
                </h3>
                <button
                  id="new-project-btn"
                  class="bg-blue-600 text-white px-4 py-2 rounded-md text-sm font-medium hover:bg-blue-700 transition-colors"
                >
                  New Project
                </button>
              </div>
            </div>

            <div class="overflow-x-auto">
              <table
                class="min-w-full divide-y divide-gray-200 dark:divide-gray-700"
              >
                <thead class="bg-gray-50 dark:bg-gray-700">
                  <tr>
                    <th
                      class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
                    >
                      Project
                    </th>
                    <th
                      class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
                    >
                      Status
                    </th>
                    <th
                      class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
                    >
                      Team
                    </th>
                    <th
                      class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
                    >
                      Progress
                    </th>
                    <th
                      class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
                    >
                      Due Date
                    </th>
                    <th class="relative px-6 py-3">
                      <span class="sr-only">Actions</span>
                    </th>
                  </tr>
                </thead>
                <tbody
                  class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700"
                >
                  <tr>
                    <td class="px-6 py-4 whitespace-nowrap">
                      <div class="flex items-center">
                        <div class="flex-shrink-0 h-10 w-10">
                          <div
                            class="h-10 w-10 rounded-lg bg-blue-100 dark:bg-blue-900 flex items-center justify-center"
                          >
                            <svg
                              class="h-6 w-6 text-blue-600 dark:text-blue-400"
                              fill="none"
                              stroke="currentColor"
                              viewBox="0 0 24 24"
                            >
                              <path
                                stroke-linecap="round"
                                stroke-linejoin="round"
                                stroke-width="2"
                                d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
                              ></path>
                            </svg>
                          </div>
                        </div>
                        <div class="ml-4">
                          <div
                            class="text-sm font-medium text-gray-900 dark:text-white"
                          >
                            Website Redesign
                          </div>
                          <div class="text-sm text-gray-500 dark:text-gray-400">
                            Complete UI/UX overhaul
                          </div>
                        </div>
                      </div>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap">
                      <span
                        class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200"
                      >
                        Active
                      </span>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap">
                      <div class="flex -space-x-2">
                        <img
                          class="h-6 w-6 rounded-full ring-2 ring-white dark:ring-gray-800"
                          src="https://via.placeholder.com/24x24"
                          alt="Team member"
                        />
                        <img
                          class="h-6 w-6 rounded-full ring-2 ring-white dark:ring-gray-800"
                          src="https://via.placeholder.com/24x24"
                          alt="Team member"
                        />
                        <img
                          class="h-6 w-6 rounded-full ring-2 ring-white dark:ring-gray-800"
                          src="https://via.placeholder.com/24x24"
                          alt="Team member"
                        />
                      </div>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap">
                      <div class="flex items-center">
                        <div
                          class="w-16 bg-gray-200 dark:bg-gray-700 rounded-full h-2 mr-2"
                        >
                          <div
                            class="bg-blue-600 h-2 rounded-full"
                            style="width: 75%"
                          ></div>
                        </div>
                        <span class="text-sm text-gray-500 dark:text-gray-400"
                          >75%</span
                        >
                      </div>
                    </td>
                    <td
                      class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"
                    >
                      Dec 15, 2024
                    </td>
                    <td
                      class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
                    >
                      <button
                        class="text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300"
                      >
                        Edit
                      </button>
                    </td>
                  </tr>

                  <tr>
                    <td class="px-6 py-4 whitespace-nowrap">
                      <div class="flex items-center">
                        <div class="flex-shrink-0 h-10 w-10">
                          <div
                            class="h-10 w-10 rounded-lg bg-green-100 dark:bg-green-900 flex items-center justify-center"
                          >
                            <svg
                              class="h-6 w-6 text-green-600 dark:text-green-400"
                              fill="none"
                              stroke="currentColor"
                              viewBox="0 0 24 24"
                            >
                              <path
                                stroke-linecap="round"
                                stroke-linejoin="round"
                                stroke-width="2"
                                d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z"
                              ></path>
                            </svg>
                          </div>
                        </div>
                        <div class="ml-4">
                          <div
                            class="text-sm font-medium text-gray-900 dark:text-white"
                          >
                            Mobile App
                          </div>
                          <div class="text-sm text-gray-500 dark:text-gray-400">
                            iOS and Android development
                          </div>
                        </div>
                      </div>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap">
                      <span
                        class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200"
                      >
                        In Review
                      </span>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap">
                      <div class="flex -space-x-2">
                        <img
                          class="h-6 w-6 rounded-full ring-2 ring-white dark:ring-gray-800"
                          src="https://via.placeholder.com/24x24"
                          alt="Team member"
                        />
                        <img
                          class="h-6 w-6 rounded-full ring-2 ring-white dark:ring-gray-800"
                          src="https://via.placeholder.com/24x24"
                          alt="Team member"
                        />
                      </div>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap">
                      <div class="flex items-center">
                        <div
                          class="w-16 bg-gray-200 dark:bg-gray-700 rounded-full h-2 mr-2"
                        >
                          <div
                            class="bg-green-600 h-2 rounded-full"
                            style="width: 90%"
                          ></div>
                        </div>
                        <span class="text-sm text-gray-500 dark:text-gray-400"
                          >90%</span
                        >
                      </div>
                    </td>
                    <td
                      class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"
                    >
                      Jan 10, 2025
                    </td>
                    <td
                      class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
                    >
                      <button
                        class="text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300"
                      >
                        Edit
                      </button>
                    </td>
                  </tr>

                  <tr>
                    <td class="px-6 py-4 whitespace-nowrap">
                      <div class="flex items-center">
                        <div class="flex-shrink-0 h-10 w-10">
                          <div
                            class="h-10 w-10 rounded-lg bg-purple-100 dark:bg-purple-900 flex items-center justify-center"
                          >
                            <svg
                              class="h-6 w-6 text-purple-600 dark:text-purple-400"
                              fill="none"
                              stroke="currentColor"
                              viewBox="0 0 24 24"
                            >
                              <path
                                stroke-linecap="round"
                                stroke-linejoin="round"
                                stroke-width="2"
                                d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
                              ></path>
                            </svg>
                          </div>
                        </div>
                        <div class="ml-4">
                          <div
                            class="text-sm font-medium text-gray-900 dark:text-white"
                          >
                            Analytics Dashboard
                          </div>
                          <div class="text-sm text-gray-500 dark:text-gray-400">
                            Data visualization platform
                          </div>
                        </div>
                      </div>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap">
                      <span
                        class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200"
                      >
                        Planning
                      </span>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap">
                      <div class="flex -space-x-2">
                        <img
                          class="h-6 w-6 rounded-full ring-2 ring-white dark:ring-gray-800"
                          src="https://via.placeholder.com/24x24"
                          alt="Team member"
                        />
                        <img
                          class="h-6 w-6 rounded-full ring-2 ring-white dark:ring-gray-800"
                          src="https://via.placeholder.com/24x24"
                          alt="Team member"
                        />
                        <img
                          class="h-6 w-6 rounded-full ring-2 ring-white dark:ring-gray-800"
                          src="https://via.placeholder.com/24x24"
                          alt="Team member"
                        />
                        <img
                          class="h-6 w-6 rounded-full ring-2 ring-white dark:ring-gray-800"
                          src="https://via.placeholder.com/24x24"
                          alt="Team member"
                        />
                      </div>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap">
                      <div class="flex items-center">
                        <div
                          class="w-16 bg-gray-200 dark:bg-gray-700 rounded-full h-2 mr-2"
                        >
                          <div
                            class="bg-purple-600 h-2 rounded-full"
                            style="width: 25%"
                          ></div>
                        </div>
                        <span class="text-sm text-gray-500 dark:text-gray-400"
                          >25%</span
                        >
                      </div>
                    </td>
                    <td
                      class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"
                    >
                      Feb 28, 2025
                    </td>
                    <td
                      class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
                    >
                      <button
                        class="text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300"
                      >
                        Edit
                      </button>
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>
        </main>
      </div>
    </div>

    <!-- New Project Modal -->
    <div
      id="project-modal"
      class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50 hidden"
    >
      <div
        class="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white dark:bg-gray-800"
      >
        <div class="mt-3">
          <div class="flex items-center justify-between mb-4">
            <h3 class="text-lg font-medium text-gray-900 dark:text-white">
              Create New Project
            </h3>
            <button
              id="close-modal"
              class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
            >
              <svg
                class="w-6 h-6"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M6 18L18 6M6 6l12 12"
                ></path>
              </svg>
            </button>
          </div>

          <form class="space-y-4">
            <div>
              <label
                class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1"
                >Project Name</label
              >
              <input
                type="text"
                class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
                placeholder="Enter project name"
              />
            </div>

            <div>
              <label
                class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1"
                >Description</label
              >
              <textarea
                rows="3"
                class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
                placeholder="Project description"
              ></textarea>
            </div>

            <div>
              <label
                class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1"
                >Due Date</label
              >
              <input
                type="date"
                class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
              />
            </div>

            <div>
              <label
                class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1"
                >Priority</label
              >
              <select
                class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
              >
                <option>Low</option>
                <option>Medium</option>
                <option>High</option>
              </select>
            </div>

            <div class="flex space-x-3 pt-4">
              <button
                type="submit"
                class="flex-1 bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 transition-colors"
              >
                Create Project
              </button>
              <button
                type="button"
                id="cancel-modal"
                class="flex-1 bg-gray-300 dark:bg-gray-600 text-gray-700 dark:text-gray-300 py-2 px-4 rounded-md hover:bg-gray-400 dark:hover:bg-gray-500 transition-colors"
              >
                Cancel
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>

    <script src="assets/js/main.js"></script>
    <script src="assets/js/charts.js"></script>
  </body>
</html>

JavaScript Files

Main JavaScript (assets/js/main.js)

javascript
// Theme toggle functionality
const themeToggle = document.getElementById("theme-toggle");
const themeToggleDarkIcon = document.getElementById("theme-toggle-dark-icon");
const themeToggleLightIcon = document.getElementById("theme-toggle-light-icon");

// Check for saved theme preference or default to 'light' mode
const currentTheme = localStorage.getItem("theme") || "light";

if (currentTheme === "dark") {
  document.documentElement.classList.add("dark");
  themeToggleLightIcon.classList.remove("hidden");
} else {
  themeToggleDarkIcon.classList.remove("hidden");
}

themeToggle.addEventListener("click", function () {
  // Toggle icons
  themeToggleDarkIcon.classList.toggle("hidden");
  themeToggleLightIcon.classList.toggle("hidden");

  // Toggle dark mode
  if (document.documentElement.classList.contains("dark")) {
    document.documentElement.classList.remove("dark");
    localStorage.setItem("theme", "light");
  } else {
    document.documentElement.classList.add("dark");
    localStorage.setItem("theme", "dark");
  }
});

// Sidebar toggle functionality
const sidebarToggle = document.getElementById("sidebar-toggle");
const sidebarClose = document.getElementById("sidebar-close");
const sidebar = document.getElementById("sidebar");
const sidebarOverlay = document.getElementById("sidebar-overlay");

function openSidebar() {
  sidebar.classList.remove("-translate-x-full");
  sidebarOverlay.classList.remove("hidden");
  document.body.classList.add("overflow-hidden");
}

function closeSidebar() {
  sidebar.classList.add("-translate-x-full");
  sidebarOverlay.classList.add("hidden");
  document.body.classList.remove("overflow-hidden");
}

sidebarToggle.addEventListener("click", openSidebar);
sidebarClose.addEventListener("click", closeSidebar);
sidebarOverlay.addEventListener("click", closeSidebar);

// Profile dropdown functionality
const profileButton = document.getElementById("profile-button");
const profileDropdown = document.getElementById("profile-dropdown");

profileButton.addEventListener("click", function (e) {
  e.stopPropagation();
  profileDropdown.classList.toggle("hidden");
});

// Close dropdown when clicking outside
document.addEventListener("click", function () {
  profileDropdown.classList.add("hidden");
});

// Modal functionality
const newProjectBtn = document.getElementById("new-project-btn");
const projectModal = document.getElementById("project-modal");
const closeModal = document.getElementById("close-modal");
const cancelModal = document.getElementById("cancel-modal");

function openModal() {
  projectModal.classList.remove("hidden");
  document.body.classList.add("overflow-hidden");
}

function closeModalFunc() {
  projectModal.classList.add("hidden");
  document.body.classList.remove("overflow-hidden");
}

newProjectBtn.addEventListener("click", openModal);
closeModal.addEventListener("click", closeModalFunc);
cancelModal.addEventListener("click", closeModalFunc);

// Close modal when clicking outside
projectModal.addEventListener("click", function (e) {
  if (e.target === projectModal) {
    closeModalFunc();
  }
});

// Form submission
const projectForm = projectModal.querySelector("form");
projectForm.addEventListener("submit", function (e) {
  e.preventDefault();

  // Get form data
  const formData = new FormData(projectForm);
  const projectData = {
    name: projectForm.querySelector('input[type="text"]').value,
    description: projectForm.querySelector("textarea").value,
    dueDate: projectForm.querySelector('input[type="date"]').value,
    priority: projectForm.querySelector("select").value,
  };

  // Simulate API call
  console.log("Creating project:", projectData);

  // Show success message (you can replace this with a proper notification)
  alert("Project created successfully!");

  // Reset form and close modal
  projectForm.reset();
  closeModalFunc();
});

// Animate stats cards on load
window.addEventListener("load", function () {
  const statsCards = document.querySelectorAll(".animate-fade-in");
  statsCards.forEach((card, index) => {
    setTimeout(() => {
      card.style.opacity = "1";
      card.style.transform = "translateY(0)";
    }, index * 100);
  });
});

// Search functionality
const searchInput = document.querySelector(
  'input[type="text"][placeholder="Search..."]'
);
if (searchInput) {
  searchInput.addEventListener("input", function (e) {
    const searchTerm = e.target.value.toLowerCase();
    console.log("Searching for:", searchTerm);
    // Implement search logic here
  });
}

// Responsive table scroll indicator
const tableContainer = document.querySelector(".overflow-x-auto");
if (tableContainer) {
  function updateScrollIndicator() {
    const scrollLeft = tableContainer.scrollLeft;
    const scrollWidth = tableContainer.scrollWidth;
    const clientWidth = tableContainer.clientWidth;

    if (scrollLeft > 0) {
      tableContainer.classList.add("shadow-left");
    } else {
      tableContainer.classList.remove("shadow-left");
    }

    if (scrollLeft < scrollWidth - clientWidth) {
      tableContainer.classList.add("shadow-right");
    } else {
      tableContainer.classList.remove("shadow-right");
    }
  }

  tableContainer.addEventListener("scroll", updateScrollIndicator);
  window.addEventListener("resize", updateScrollIndicator);
  updateScrollIndicator();
}

Charts JavaScript (assets/js/charts.js)

javascript
// Revenue Chart
const revenueCtx = document.getElementById("revenueChart");
if (revenueCtx) {
  const revenueChart = new Chart(revenueCtx, {
    type: "line",
    data: {
      labels: [
        "Jan",
        "Feb",
        "Mar",
        "Apr",
        "May",
        "Jun",
        "Jul",
        "Aug",
        "Sep",
        "Oct",
        "Nov",
        "Dec",
      ],
      datasets: [
        {
          label: "Revenue",
          data: [
            12000, 19000, 15000, 25000, 22000, 30000, 28000, 35000, 32000,
            40000, 38000, 45000,
          ],
          borderColor: "rgb(59, 130, 246)",
          backgroundColor: "rgba(59, 130, 246, 0.1)",
          borderWidth: 2,
          fill: true,
          tension: 0.4,
          pointBackgroundColor: "rgb(59, 130, 246)",
          pointBorderColor: "#fff",
          pointBorderWidth: 2,
          pointRadius: 4,
          pointHoverRadius: 6,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: {
          display: false,
        },
        tooltip: {
          backgroundColor: "rgba(0, 0, 0, 0.8)",
          titleColor: "#fff",
          bodyColor: "#fff",
          borderColor: "rgb(59, 130, 246)",
          borderWidth: 1,
          cornerRadius: 8,
          displayColors: false,
          callbacks: {
            label: function (context) {
              return "$" + context.parsed.y.toLocaleString();
            },
          },
        },
      },
      scales: {
        x: {
          grid: {
            display: false,
          },
          ticks: {
            color: "#6B7280",
          },
        },
        y: {
          grid: {
            color: "rgba(107, 114, 128, 0.1)",
          },
          ticks: {
            color: "#6B7280",
            callback: function (value) {
              return "$" + value / 1000 + "k";
            },
          },
        },
      },
      interaction: {
        intersect: false,
        mode: "index",
      },
    },
  });

  // Update chart colors for dark mode
  function updateChartTheme() {
    const isDark = document.documentElement.classList.contains("dark");
    const textColor = isDark ? "#D1D5DB" : "#6B7280";
    const gridColor = isDark
      ? "rgba(209, 213, 219, 0.1)"
      : "rgba(107, 114, 128, 0.1)";

    revenueChart.options.scales.x.ticks.color = textColor;
    revenueChart.options.scales.y.ticks.color = textColor;
    revenueChart.options.scales.y.grid.color = gridColor;
    revenueChart.update();
  }

  // Listen for theme changes
  const observer = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
      if (mutation.attributeName === "class") {
        updateChartTheme();
      }
    });
  });

  observer.observe(document.documentElement, {
    attributes: true,
    attributeFilter: ["class"],
  });
}

// Additional chart configurations for future use
const chartDefaults = {
  responsive: true,
  maintainAspectRatio: false,
  plugins: {
    legend: {
      labels: {
        usePointStyle: true,
        padding: 20,
      },
    },
  },
};

// Utility function to create gradient
function createGradient(ctx, colorStart, colorEnd) {
  const gradient = ctx.createLinearGradient(0, 0, 0, 400);
  gradient.addColorStop(0, colorStart);
  gradient.addColorStop(1, colorEnd);
  return gradient;
}

// Performance metrics simulation
function updatePerformanceMetrics() {
  const metrics = {
    users: Math.floor(Math.random() * 1000) + 71000,
    revenue: Math.floor(Math.random() * 50000) + 400000,
    sales: Math.floor(Math.random() * 2000) + 12000,
    performance: (Math.random() * 5 + 95).toFixed(1),
  };

  // Update DOM elements if they exist
  const usersStat = document.querySelector('[data-stat="users"]');
  const revenueStat = document.querySelector('[data-stat="revenue"]');
  const salesStat = document.querySelector('[data-stat="sales"]');
  const performanceStat = document.querySelector('[data-stat="performance"]');

  if (usersStat) usersStat.textContent = metrics.users.toLocaleString();
  if (revenueStat)
    revenueStat.textContent = "$" + metrics.revenue.toLocaleString();
  if (salesStat) salesStat.textContent = metrics.sales.toLocaleString();
  if (performanceStat) performanceStat.textContent = metrics.performance + "%";
}

// Update metrics every 30 seconds
setInterval(updatePerformanceMetrics, 30000);

Project Analysis

Tailwind CSS Concepts Demonstrated

1. Responsive Design

  • Mobile-first approach with sm:, md:, lg: breakpoints
  • Responsive grid layouts: grid-cols-1 md:grid-cols-2 lg:grid-cols-4
  • Adaptive sidebar: lg:translate-x-0 for desktop, hidden on mobile
  • Responsive typography and spacing

2. Dark Mode Implementation

  • Class-based dark mode strategy
  • Consistent dark variants: dark:bg-gray-800, dark:text-white
  • Theme persistence with localStorage
  • Dynamic chart theme updates

3. Advanced Layout Techniques

  • Flexbox for header and sidebar layouts
  • CSS Grid for dashboard cards and content areas
  • Absolute positioning for modals and dropdowns
  • Sticky positioning for navigation elements

4. Component Patterns

  • Reusable card components with consistent styling
  • Form components with proper focus states
  • Navigation patterns with active states
  • Modal and overlay patterns

5. Interactive States

  • Hover effects: hover:bg-gray-100, hover:text-blue-700
  • Focus states: focus:ring-2 focus:ring-blue-500
  • Active states for navigation items
  • Transition animations: transition-colors duration-300

6. Typography and Spacing

  • Consistent typography scale: text-sm, text-lg, text-xl
  • Systematic spacing: p-4, m-6, space-y-4
  • Font weights for hierarchy: font-medium, font-semibold

7. Color System

  • Semantic color usage: bg-blue-600 for primary actions
  • Status colors: text-green-600 for success, text-red-600 for errors
  • Consistent opacity variations: bg-opacity-50

Performance Optimizations

1. CSS Optimizations

  • Utility-first approach reduces CSS bundle size
  • Purged unused styles in production
  • Efficient class combinations

2. JavaScript Optimizations

  • Event delegation for better performance
  • Debounced search functionality
  • Efficient DOM queries with caching

3. Loading Optimizations

  • Progressive enhancement approach
  • Lazy loading for non-critical components
  • Optimized animation timing

Learning Objectives

By completing this project, you will have:

✅ Technical Skills

  • Built a complete responsive dashboard from scratch
  • Implemented advanced Tailwind CSS patterns
  • Created reusable component systems
  • Integrated JavaScript functionality with Tailwind styles
  • Implemented dark mode with proper UX considerations

✅ Design Skills

  • Applied modern UI/UX principles
  • Created consistent visual hierarchy
  • Implemented accessible color schemes
  • Designed responsive layouts that work on all devices

✅ Development Skills

  • Organized large-scale CSS projects
  • Implemented performance best practices
  • Created maintainable code structures
  • Integrated third-party libraries (Chart.js)

Implementation Guide

Phase 1: Setup and Structure (30 minutes)

  1. Create project directory structure
  2. Set up HTML boilerplate with Tailwind CDN
  3. Implement basic layout (sidebar + main content)
  4. Add responsive navigation

Phase 2: Core Components (45 minutes)

  1. Build statistics cards with animations
  2. Create data table with responsive design
  3. Implement modal functionality
  4. Add form components

Phase 3: Advanced Features (45 minutes)

  1. Integrate Chart.js for data visualization
  2. Implement dark mode toggle
  3. Add interactive states and animations
  4. Optimize for mobile devices

Phase 4: Polish and Testing (30 minutes)

  1. Test responsive behavior
  2. Verify dark mode functionality
  3. Check accessibility features
  4. Optimize performance

Common Pitfalls and Solutions

❌ Pitfall: Inconsistent Spacing

html
<!-- Bad: Mixed spacing units -->
<div class="p-3 m-5 space-y-2"></div>

✅ Solution: Use Consistent Scale

html
<!-- Good: Consistent spacing scale -->
<div class="p-4 m-4 space-y-4"></div>

❌ Pitfall: Overusing Custom CSS

css
/* Bad: Custom styles that could be utilities */
.custom-button {
  background: #3b82f6;
  padding: 8px 16px;
  border-radius: 6px;
}

✅ Solution: Use Tailwind Utilities

html
<!-- Good: Pure Tailwind utilities -->
<button class="bg-blue-500 px-4 py-2 rounded-md"></button>

❌ Pitfall: Poor Dark Mode Implementation

html
<!-- Bad: Inconsistent dark mode -->
<div class="bg-white text-black dark:bg-gray-900"></div>

✅ Solution: Complete Dark Mode Pairs

html
<!-- Good: Complete dark mode styling -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white"></div>

❌ Pitfall: Non-Responsive Design

html
<!-- Bad: Fixed layout -->
<div class="grid grid-cols-4 gap-6"></div>

✅ Solution: Mobile-First Responsive

html
<!-- Good: Progressive enhancement -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"></div>

Why This Project Matters

🎯 Real-World Application

  • Dashboards are common in modern web applications
  • Demonstrates enterprise-level UI patterns
  • Shows how to handle complex state management
  • Illustrates performance optimization techniques

🚀 Career Relevance

  • Portfolio-worthy project demonstrating advanced skills
  • Covers patterns used in popular frameworks (React, Vue, Angular)
  • Shows understanding of modern web development practices
  • Demonstrates ability to create production-ready interfaces

📈 Skill Development

  • Bridges the gap between learning and application
  • Integrates multiple technologies (HTML, CSS, JavaScript)
  • Teaches project organization and code structure
  • Develops problem-solving and debugging skills

Performance Considerations

🔧 Build Time Optimization

  • Use Tailwind's purge feature to remove unused styles
  • Implement proper content configuration
  • Optimize for production builds

⚡ Runtime Performance

  • Minimize DOM manipulations
  • Use efficient event handling
  • Implement proper loading states
  • Optimize animations for 60fps

📱 Mobile Performance

  • Optimize touch interactions
  • Implement proper viewport settings
  • Use appropriate image sizes
  • Minimize layout shifts

Mini-Challenges

Challenge 1: Add a Settings Page

Objective: Create a comprehensive settings page with form validation

Requirements:

  • User profile settings
  • Notification preferences
  • Theme customization options
  • Account security settings

Key Concepts: Form layouts, validation states, toggle components

Challenge 2: Implement Data Filtering

Objective: Add advanced filtering and sorting to the projects table

Requirements:

  • Filter by status, team, and date range
  • Sort by different columns
  • Search functionality
  • Export options

Key Concepts: Interactive components, state management, responsive tables

Challenge 3: Create a Calendar View

Objective: Build a calendar component for project scheduling

Requirements:

  • Monthly calendar view
  • Event creation and editing
  • Drag and drop functionality
  • Responsive design

Key Concepts: Grid layouts, positioning, interactive states

Interview Tips

🎤 Technical Questions You Should Be Able to Answer

Q: How did you implement responsive design in this dashboard?

A: "I used Tailwind's mobile-first approach with breakpoint prefixes. For example, the stats cards use grid-cols-1 md:grid-cols-2 lg:grid-cols-4 to stack on mobile, show 2 columns on tablets, and 4 columns on desktop. The sidebar uses lg:translate-x-0 to be visible on desktop but hidden on mobile with a toggle button."

Q: Explain your dark mode implementation strategy.

A: "I used Tailwind's class-based dark mode strategy. Each component has both light and dark variants like bg-white dark:bg-gray-800. I implemented a toggle that adds/removes the 'dark' class from the document element and persists the preference in localStorage. I also made sure charts update their colors dynamically using a MutationObserver."

Q: How did you ensure good performance in this application?

A: "I focused on several areas: CSS performance by using Tailwind's utility-first approach which reduces bundle size, JavaScript performance by caching DOM queries and using event delegation, and UX performance by implementing smooth transitions and loading states. I also made sure animations run at 60fps by using transform properties."

Q: What accessibility considerations did you implement?

A: "I ensured proper color contrast ratios for both light and dark modes, used semantic HTML elements, implemented proper focus states with focus:ring-2, added ARIA labels where needed, and made sure the interface is keyboard navigable. The modal also traps focus and can be closed with the Escape key."

Q: How would you scale this dashboard for a larger application?

A: "I would extract reusable components into separate files, implement a proper state management solution, add TypeScript for better type safety, create a design system with consistent spacing and color tokens, implement proper error boundaries, and add comprehensive testing. I'd also consider using a framework like React or Vue for better component organization."


Conclusion

Congratulations! You've completed the Dashify project and demonstrated mastery of advanced Tailwind CSS concepts. This project serves as a comprehensive example of how to build modern, responsive, and accessible web applications using utility-first CSS.

What You've Accomplished

  • ✅ Built a complete dashboard application from scratch
  • ✅ Implemented responsive design patterns
  • ✅ Created a comprehensive dark mode system
  • ✅ Integrated interactive JavaScript functionality
  • ✅ Applied performance optimization techniques
  • ✅ Demonstrated real-world development skills

Next Steps

  1. Enhance the Project: Add the mini-challenges to expand functionality
  2. Deploy: Host your dashboard on platforms like Netlify or Vercel
  3. Portfolio: Add this project to your portfolio with detailed documentation
  4. Framework Integration: Rebuild using React, Vue, or your preferred framework
  5. Backend Integration: Connect to real APIs and databases

This project represents the culmination of your Tailwind CSS learning journey. You now have the skills and knowledge to build professional-grade user interfaces and tackle complex frontend challenges with confidence.

Happy coding! 🚀

PreviousAdvanced Layout Techniques

Open source, free forever. Built by iammhador.

Contribute on GitHub