Skip to content
Open
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
204 changes: 140 additions & 64 deletions src/components/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react'
import React, { useState } from 'react'
import { NavLink, useNavigate } from 'react-router-dom'
import { FiHeart, FiSettings, FiZap } from 'react-icons/fi'
import { FiHeart, FiSettings, FiZap, FiMenu, FiX } from 'react-icons/fi'
import { useApp } from '../context/AppContext'
import ThemeToggle from './ThemeToggle'
import Logo from "../assests/og-logo.svg?react";
import Logo from "../assests/og-logo.svg?react"
import { useTheme } from '../context/ThemeContext'

const LINKS = [
Expand All @@ -17,75 +17,151 @@ const LINKS = [

export default function Navbar() {
const { orgs, rateLimit } = useApp()
const { theme } = useTheme();
const { theme } = useTheme()
const navigate = useNavigate()

const hasData = orgs.length > 0
const lowLimit = rateLimit && rateLimit.remaining < 15
const [menuOpen, setMenuOpen] = useState(false)

return (
<nav style={{
position: 'sticky', top: 0, zIndex: 100,
background: 'var(--bg)',
backdropFilter: 'blur(10px)',
borderBottom: '1px solid var(--border)',
padding: '0 24px',
display: 'flex', alignItems: 'center', gap: 24, height: 56,
justifyContent: 'space-between',
}}>
{/* Wordmark */}
<span
onClick={() => navigate('/')}
<>
{/* Mobile navigation menu */}
{menuOpen && hasData && (
<div className="navbar-mobile-menu">
{LINKS.map(({ to, label }) => (
<NavLink
key={to}
to={to}
className="navbar-mobile-link"
onClick={() => setMenuOpen(false)}
style={({ isActive }) => ({
padding: '10px 12px',
textDecoration: 'none',
color: isActive ? 'var(--accent)' : 'var(--text)',
fontWeight: isActive ? 600 : 400,
borderRadius: 6,
background: isActive ? 'var(--surface)' : 'transparent',
})}
>
{label}
</NavLink>
))}
</div>
)}

<nav
style={{
position: 'sticky',
top: 0,
zIndex: 100,
background: 'var(--bg)',
backdropFilter: 'blur(10px)',
borderBottom: '1px solid var(--border)',
padding: '0 24px',
display: 'flex',
alignItems: 'center',
gap: 24,
height: 56,
justifyContent: 'space-between',
}}
>
<Logo className="h-15 w-auto" />
</span>
{/* Wordmark */}
<NavLink
to="/"
aria-label="Go to home"
style={{ cursor: 'pointer', flexShrink: 0 }}
>
<Logo className="h-15 w-auto" />
</NavLink>

{/* Desktop Nav links */}
<div className="navbar-desktop-links">
{hasData &&
LINKS.map(({ to, label }) => (
<NavLink
key={to}
to={to}
className="navbar-link"
style={({ isActive }) => ({
display: 'block',
padding: '6px 10px',
fontSize: 13,
whiteSpace: 'nowrap',
textDecoration: 'none',
fontWeight: isActive ? 600 : 400,
color: isActive ? 'var(--accent)' : 'var(--text2)',
borderBottom: isActive
? '2px solid var(--accent)'
: '2px solid transparent',
transition: 'color 0.2s ease',
})}
>
{label}
</NavLink>
))}
</div>

{/* Right side */}
<div className="navbar-right">
{rateLimit && (
<div
style={{
display: 'flex',
alignItems: 'center',
gap: 5,
fontSize: 11,
color: lowLimit ? 'var(--red)' : 'var(--text2)',
}}
>
<FiZap size={12} />
{rateLimit.remaining.toLocaleString()} /{' '}
{rateLimit.limit.toLocaleString()}
</div>
)}

<ThemeToggle />

{/* Nav links — only visible when data is loaded */}
<div style={{ display: 'flex', gap: 2, flex: 1, overflowX: 'auto' }}>
{hasData && LINKS.map(({ to, label }) => (
<NavLink
key={to} to={to}
className="navbar-link"
style={({ isActive }) => ({
display: 'block',
padding: '6px 10px',
fontSize: 13,
whiteSpace: 'nowrap',
textDecoration: 'none',
fontWeight: isActive ? 600 : 400,
color: isActive ? 'var(--accent)' : 'var(--text2)',
borderBottom: isActive ? '2px solid var(--accent)' : '2px solid transparent',
transition: 'color 0.2s ease',
})}
<button
onClick={() => navigate('/settings')}
style={{
background: 'none',
border: '1px solid var(--border)',
color: 'var(--text2)',
borderRadius: 6,
padding: '5px 10px',
fontSize: 12,
display: 'flex',
alignItems: 'center',
gap: 5,
}}
>
{label}
</NavLink>
))}
</div>
<FiSettings size={13} />
Settings
</button>

{/* Right side */}
<div style={{ display: 'flex', alignItems: 'center', gap: 14, flexShrink: 0 }}>
{rateLimit && (
<div style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 11, color: lowLimit ? 'var(--red)' : 'var(--text2)' }}>
<FiZap size={12} />
{rateLimit.remaining.toLocaleString()} / {rateLimit.limit.toLocaleString()}
</div>
<button
onClick={() => navigate('/support-us')}
className="flex items-center gap-2 rounded-md bg-emerald-500 px-4 py-2 text-sm font-medium text-white shadow transition-all duration-200 hover:bg-emerald-600 hover:shadow-lg active:scale-95"
>
<FiHeart size={13} fill="white" />
Support Us
</button>
</div>

{/* Mobile menu button */}
{hasData && (
<button
className="navbar-menu-button"
onClick={() => setMenuOpen((prev) => !prev)}
aria-label={
menuOpen ? 'Close navigation menu' : 'Open navigation menu'
}
>
{menuOpen ? <FiX size={22} /> : <FiMenu size={22} />}
</button>
)}
<ThemeToggle />
<button
onClick={() => navigate('/settings')}
style={{ background: 'none', border: '1px solid var(--border)', color: 'var(--text2)', borderRadius: 6, padding: '5px 10px', fontSize: 12, display: 'flex', alignItems: 'center', gap: 5 }}
className='h-[-webkit-fill-available]'
>
<FiSettings size={13} /> Settings
</button>
<button
onClick={() => navigate('/support-us')}
className="flex items-center gap-2 rounded-md bg-emerald-500 px-4 py-2 text-sm font-medium text-white shadow transition-all duration-200 hover:bg-emerald-600 hover:shadow-lg active:scale-95"
>
<FiHeart size={13} fill='white' />
Support Us
</button>
</div>
</nav>
</nav>
</>
)
}
}
120 changes: 120 additions & 0 deletions src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,124 @@ input[type="date"]::-webkit-calendar-picker-indicator {

.navbar-link:hover {
color: var(--accent) !important;
}

/* Yeh classes missing hain - add karni hain */

.navbar-desktop-links {
display: flex;
gap: 2px;
flex: 1;
overflow-x: auto;
}

.navbar-right {
display: flex;
align-items: center;
gap: 14px;
flex-shrink: 0;
}

.navbar-menu-button {
display: none; /* Hide by default, show on mobile */
background: none;
border: 1px solid var(--border);
color: var(--text);
border-radius: 6px;
padding: 6px;
align-items: center;
justify-content: center;
cursor: pointer;
}

.navbar-mobile-menu {
display: none; /* Hidden by default, shown via JS */
}

.navbar-mobile-link {
display: block;
color: var(--text2);
text-decoration: none;
}

.navbar-mobile-link:hover {
color: var(--accent);
background: var(--surface);
}

/* === RESPONSIVE NAVBAR - Add at the end === */

@media (max-width: 690px) {
.navbar-desktop-links {
display: none;
}

.navbar-menu-button {
display: flex;
flex-shrink: 0;
}

.navbar-mobile-menu {
display: flex;
flex-direction: column;
position: fixed;
top: 56px;
left: 0;
right: 0;
z-index: 99;
background: var(--bg);
border-bottom: 1px solid var(--border);
padding: 12px 24px;
gap: 8px;
}
}
@media (max-width: 480px) {
.navbar-right {
gap: 6px;
min-width: 0;
flex-shrink: 1;
}

/* Rate limit text ko chhota karo */
.navbar-right > div:first-child {
font-size: 10px !important;
gap: 3px !important;
}

/* Settings button - icon only */
.navbar-right button:first-of-type {
padding: 6px 8px;
font-size: 0;
}

.navbar-right button:first-of-type svg {
margin: 0;
font-size: 14px;
}

/* Support Us button - icon only */
.navbar-right button:last-child {
padding: 6px 8px;
font-size: 0;
background: transparent !important;
color: var(--text) !important;
box-shadow: none !important;
border: 1px solid var(--border);
border-radius: 6px;
}

.navbar-right button:last-child:hover {
background: var(--surface) !important;
}

.navbar-right button:last-child svg {
margin: 0;
font-size: 16px;
fill: currentcolor;
}

.navbar-menu-button {
display: flex;
flex-shrink: 0;
}
}
Loading