From 10fa81f3def71a583318970218841da5a8c5508f Mon Sep 17 00:00:00 2001 From: emmanuel iheanacho Date: Fri, 29 May 2026 14:08:29 +0100 Subject: [PATCH 1/2] feat(ui): implement responsive navbar with wallet status --- components/navbar.tsx | 135 +++++++++++++++++++++++++++++----- components/ui/ThemeToggle.tsx | 50 +++++++++---- 2 files changed, 150 insertions(+), 35 deletions(-) diff --git a/components/navbar.tsx b/components/navbar.tsx index e9edc75..2041220 100644 --- a/components/navbar.tsx +++ b/components/navbar.tsx @@ -2,22 +2,35 @@ import Link from 'next/link' import { Button } from '@/components/ui/button' -import { Menu, X } from 'lucide-react' +import { Menu, X, Wallet, User, Settings, LogOut, ChevronDown } from 'lucide-react' import { useState } from 'react' import { ThemeToggle } from './ui/ThemeToggle' export function Navbar() { const [mobileMenuOpen, setMobileMenuOpen] = useState(false) + const [profileDropdownOpen, setProfileDropdownOpen] = useState(false) + + // ⚡ Wallet Connection states (Wire these up to your Stellar/Wallet adapter hooks later) + const [isConnected, setIsConnected] = useState(true) + const walletAddress = "GBXW...4Y2T" + + const closeMenus = () => { + setMobileMenuOpen(false) + setProfileDropdownOpen(false) + } return ( ) -} +} \ No newline at end of file diff --git a/components/ui/ThemeToggle.tsx b/components/ui/ThemeToggle.tsx index acc816d..66b4c3f 100644 --- a/components/ui/ThemeToggle.tsx +++ b/components/ui/ThemeToggle.tsx @@ -4,37 +4,57 @@ import { useEffect, useState } from "react"; import { Sun, Moon } from "lucide-react"; export function ThemeToggle() { - // 1. Initialize state properly to avoid cascading renders - const [dark, setDark] = useState(() => { - if (typeof window !== "undefined") { - return localStorage.getItem("theme") === "dark"; - } - return false; - }); + const [dark, setDark] = useState(false); + const [mounted, setMounted] = useState(false); - // 2. Synchronize the HTML class with the state + // 1. Run only on the client after hydration completes useEffect(() => { + setMounted(true); + const savedTheme = localStorage.getItem("theme"); + + // Check if user has a saved preference, otherwise default to system preferences + const isDark = + savedTheme === "dark" || + (!savedTheme && + window.matchMedia("(prefers-color-scheme: dark)").matches); + + setDark(isDark); + }, []); + + // 2. Synchronize the HTML class when state changes + useEffect(() => { + if (!mounted) return; // Skip during initial load setup + if (dark) { document.documentElement.classList.add("dark"); + localStorage.setItem("theme", "dark"); } else { document.documentElement.classList.remove("dark"); + localStorage.setItem("theme", "light"); } - }, [dark]); + }, [dark, mounted]); const toggleTheme = () => { - setDark((prev) => { - const newDark = !prev; - localStorage.setItem("theme", newDark ? "dark" : "light"); - return newDark; - }); + setDark((prev) => !prev); }; + // 3. Render a completely identical placeholder structure during server side compilation + if (!mounted) { + return ( +