Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 136 additions & 2 deletions components/navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
// // 'use client'

import Link from 'next/link'
import { Button } from '@/components/ui/button'
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)
}
// // import Link from 'next/link'
// // import { Button } from '@/components/ui/button'
// // import { Menu, X, Wallet } from 'lucide-react'
Expand Down Expand Up @@ -227,6 +245,8 @@ export function Navbar() {
<nav className="fixed top-0 left-0 right-0 z-50 border-b border-border/40 backdrop-blur-xl bg-background/80">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="flex h-16 items-center justify-between">

{/* Logo Section */}
{/* Logo */}
<div className="flex items-center gap-2">
<Image
Expand All @@ -241,6 +261,7 @@ export function Navbar() {
</span>
</div>

{/* Desktop Navigation Links */}
{/* Desktop Links */}
<div className="hidden md:flex items-center gap-8">
<Link href="#features" className="text-sm text-muted-foreground hover:text-foreground">
Expand All @@ -257,6 +278,78 @@ export function Navbar() {
</Link>
</div>

{/* Desktop Actions Area (Wallet Status + User Profiles) */}
<div className="hidden md:flex items-center gap-4">

{/* Wallet Status Button Component */}
<Button
variant={isConnected ? "outline" : "default"}
size="sm"
className="gap-2 rounded-full font-medium"
onClick={() => setIsConnected(!isConnected)}
>
<Wallet className="h-4 w-4" />
<span>{isConnected ? walletAddress : "Connect Wallet"}</span>
{isConnected && <span className="h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse" />}
</Button>

{/* Profile Dropdown Component */}
{isConnected && (
<div className="relative">
<Button
variant="ghost"
size="sm"
className="gap-1 rounded-full p-1 pl-2 hover:bg-muted"
onClick={() => setProfileDropdownOpen(!profileDropdownOpen)}
>
<div className="flex h-6 w-full items-center justify-center rounded-full bg-primary/20 text-xs font-bold text-primary px-2">
U
</div>
<ChevronDown className={`h-4 w-4 text-muted-foreground transition-transform duration-200 ${profileDropdownOpen ? "rotate-180" : ""}`} />
</Button>

{/* Dropdown Menu Container */}
{profileDropdownOpen && (
<div className="absolute right-0 mt-2 w-48 origin-top-right rounded-xl border border-border/60 bg-background p-1 shadow-xl ring-1 ring-black/5 animate-in fade-in slide-in-from-top-1 duration-150">
<Link
href="/profile"
className="flex items-center gap-2 rounded-lg px-3 py-2 text-sm text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
onClick={closeMenus}
>
<User className="h-4 w-4" />
<span>My Profile</span>
</Link>
<Link
href="/settings"
className="flex items-center gap-2 rounded-lg px-3 py-2 text-sm text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
onClick={closeMenus}
>
<Settings className="h-4 w-4" />
<span>Settings</span>
</Link>
<hr className="my-1 border-border/40" />
<button
onClick={() => { setIsConnected(false); closeMenus(); }}
className="flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-destructive hover:bg-destructive/10 transition-colors"
>
<LogOut className="h-4 w-4" />
<span>Disconnect</span>
</button>
</div>
)}
</div>
)}

{!isConnected && (
<Button variant="ghost" asChild>
<Link href="/login">Login</Link>
</Button>
)}

<ThemeToggle />
</div>

{/* Mobile Hamburger Trigger Toggle Button */}
{/* Desktop Actions */}
<div className="hidden md:flex items-center gap-4">
<WalletConnect />
Expand All @@ -265,9 +358,10 @@ export function Navbar() {

{/* Mobile Menu Button */}
<button
className="md:hidden p-2 text-muted-foreground hover:text-foreground"
className="md:hidden p-2 text-muted-foreground hover:text-foreground transition-transform focus:outline-none"
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
>
{mobileMenuOpen ? <X className="h-6 w-6 rotate-90 duration-200" /> : <Menu className="h-6 w-6 duration-200" />}
{mobileMenuOpen ? (
<X className="h-6 w-6" />
) : (
Expand All @@ -277,10 +371,49 @@ export function Navbar() {
</div>
</div>

{/* Mobile Popout Panel */}
{/* Mobile Menu */}
{mobileMenuOpen && (
<div className="md:hidden border-t border-border/40 bg-background/95 backdrop-blur-xl">
<div className="md:hidden border-t border-border/40 bg-background/95 backdrop-blur-xl animate-in fade-in slide-in-from-top-2 duration-200">
<div className="px-4 py-6 space-y-4">
<Link href="#features" className="block text-sm text-muted-foreground hover:text-foreground transition-colors" onClick={closeMenus}>
Features
</Link>
<Link href="#how-it-works" className="block text-sm text-muted-foreground hover:text-foreground transition-colors" onClick={closeMenus}>
How It Works
</Link>
<Link href="#benefits" className="block text-sm text-muted-foreground hover:text-foreground transition-colors" onClick={closeMenus}>
Benefits
</Link>
<Link href="#testimonials" className="block text-sm text-muted-foreground hover:text-foreground transition-colors" onClick={closeMenus}>
Testimonials
</Link>

<div className="pt-4 border-t border-border/40 space-y-3">
{/* Mobile Adaptive Wallet Module */}
<Button
variant={isConnected ? "outline" : "default"}
className="w-full gap-2 rounded-lg justify-center"
onClick={() => setIsConnected(!isConnected)}
>
<Wallet className="h-4 w-4" />
<span>{isConnected ? walletAddress : "Connect Wallet"}</span>
</Button>

{isConnected ? (
<>
<Button variant="ghost" className="w-full justify-start gap-2" asChild onClick={closeMenus}>
<Link href="/profile"><User className="h-4 w-4" /> Profile</Link>
</Button>
<Button variant="ghost" className="w-full justify-start gap-2 text-destructive hover:text-destructive hover:bg-destructive/10" onClick={() => { setIsConnected(false); closeMenus(); }}>
<LogOut className="h-4 w-4" /> Disconnect Wallet
</Button>
</>
) : (
<Button variant="ghost" className="w-full" asChild onClick={closeMenus}>
<Link href="/login">Login</Link>
</Button>
)}
<Link href="#features" onClick={() => setMobileMenuOpen(false)}>
Features
</Link>
Expand All @@ -302,5 +435,6 @@ export function Navbar() {
</div>
)}
</nav>
)
);
}
48 changes: 48 additions & 0 deletions components/ui/ThemeToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,57 @@ import {
} from "@/components/ui/dropdown-menu";

export function ThemeToggle() {
const [dark, setDark] = useState(false);
const [mounted, setMounted] = useState(false);

useEffect(() => {
const savedTheme = localStorage.getItem("theme");
const isDark =
savedTheme === "dark" ||
(!savedTheme &&
window.matchMedia("(prefers-color-scheme: dark)").matches);

// eslint-disable-next-line react-hooks/set-state-in-effect
setDark(isDark);
setMounted(true);
}, []);

// Synchronize the HTML class when state changes
useEffect(() => {
if (!mounted) return;

if (dark) {
document.documentElement.classList.add("dark");
localStorage.setItem("theme", "dark");
} else {
document.documentElement.classList.remove("dark");
localStorage.setItem("theme", "light");
}
}, [dark, mounted]);

const toggleTheme = () => {
setDark((prev) => !prev);
};
const { setTheme } = useTheme();

// Render a completely identical placeholder structure during server side compilation
if (!mounted) {
return (
<div
className="w-9 h-9 p-2 rounded-lg bg-muted/40 opacity-0"
aria-hidden="true"
/>
);
}

return (
<button
onClick={toggleTheme}
className="p-2 rounded-lg bg-muted hover:bg-muted/80 transition"
aria-label="Toggle theme"
>
{dark ? <Sun size={18} /> : <Moon size={18} />}
</button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon">
Expand Down
11 changes: 7 additions & 4 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { defineConfig, globalIgnores } from 'eslint/config'
import nextVitals from 'eslint-config-next/core-web-vitals'

export default defineConfig([
const config = [
...nextVitals,
globalIgnores(['.next/**', 'out/**', 'build/**', 'next-env.d.ts',"node_modules/**"]),
])
{
ignores: ['.next/**', 'out/**', 'build/**', 'next-env.d.ts', '.github/**'],
},
]

export default config
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading