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
3 changes: 3 additions & 0 deletions src/components/AnalysisBanner.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default function AnalysisBanner({ page, description, onRun, loading = fal
return (
<>
<div
className="analysis-banner"
style={{
marginBottom: 24,

Expand All @@ -37,6 +38,7 @@ export default function AnalysisBanner({ page, description, onRun, loading = fal
{/* Left */}

<div
className="analysis-banner-content"
style={{
display: 'flex',
alignItems: 'center',
Expand Down Expand Up @@ -102,6 +104,7 @@ export default function AnalysisBanner({ page, description, onRun, loading = fal
{/* Right */}

<div
className="analysis-banner-actions"
style={{
display: 'flex',
alignItems: 'center',
Expand Down
127 changes: 110 additions & 17 deletions src/components/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,60 @@
import React from 'react'
import React, { useEffect, useRef, useState } from 'react'
import { NavLink, useNavigate } from 'react-router-dom'
import { FiHeart, FiSettings, FiZap } from 'react-icons/fi'
import { FiBarChart2, FiBook, FiChevronRight, FiExternalLink, FiHeart, FiHome, FiMenu, FiSettings, FiShare2, FiShield, FiSun, FiUsers, FiZap, FiX } from 'react-icons/fi'
import { useApp } from '../context/AppContext'
import ThemeToggle from './ThemeToggle'
import Logo from "../assests/og-logo.svg?react";
import { useTheme } from '../context/ThemeContext'

const LINKS = [
{ to: '/overview', label: 'Overview' },
{ to: '/repositories', label: 'Repositories' },
{ to: '/contributors', label: 'Contributors' },
{ to: '/network', label: 'Network' },
{ to: '/analytics', label: 'Analytics' },
{ to: '/governance', label: 'Governance' },
{ to: '/overview', label: 'Overview', icon: FiHome },
{ to: '/repositories', label: 'Repositories', icon: FiBook },
{ to: '/contributors', label: 'Contributors', icon: FiUsers },
{ to: '/network', label: 'Network', icon: FiShare2 },
{ to: '/analytics', label: 'Analytics', icon: FiBarChart2 },
{ to: '/governance', label: 'Governance', icon: FiShield },
]

export default function Navbar() {
const { orgs, rateLimit } = useApp()
const { theme } = useTheme();
const { rateLimit } = useApp()
const navigate = useNavigate()
const hasData = orgs.length > 0
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const [isOverflowing, setIsOverflowing] = useState(false)
const navbarRef = useRef(null)
const linksRef = useRef(null)
const menuToggleRef = useRef(null)
const lowLimit = rateLimit && rateLimit.remaining < 15

useEffect(() => {
const navbar = navbarRef.current
const links = linksRef.current
const menuToggle = menuToggleRef.current
if (!navbar || !links || !menuToggle) return

const measureOverflow = () => {
const wasOverflowing = links.classList.contains('navbar-links-overflowing')
links.classList.remove('navbar-links-overflowing')
menuToggle.classList.remove('navbar-menu-toggle-visible')
const nextOverflowing = links.scrollWidth > links.clientWidth
if (wasOverflowing) {
links.classList.add('navbar-links-overflowing')
menuToggle.classList.add('navbar-menu-toggle-visible')
}
setIsOverflowing(current => current === nextOverflowing ? current : nextOverflowing)
}

const observer = new ResizeObserver(measureOverflow)
observer.observe(navbar)
observer.observe(links)
measureOverflow()
return () => observer.disconnect()
}, [])

useEffect(() => {
if (!isOverflowing) setMobileMenuOpen(false)
}, [isOverflowing])

return (
<nav style={{
<nav ref={navbarRef} className={`app-navbar${mobileMenuOpen ? ' app-navbar-menu-open' : ''}`} style={{
position: 'sticky', top: 0, zIndex: 100,
background: 'var(--bg)',
backdropFilter: 'blur(10px)',
Expand All @@ -40,8 +71,8 @@ export default function Navbar() {
</span>

{/* Nav links — only visible when data is loaded */}
<div style={{ display: 'flex', gap: 2, flex: 1, overflowX: 'auto' }}>
{hasData && LINKS.map(({ to, label }) => (
<div ref={linksRef} className={`navbar-links${isOverflowing ? ' navbar-links-overflowing' : ''}`} style={{ display: 'flex', gap: 2, flex: 1, overflowX: 'auto' }}>
{LINKS.map(({ to, label }) => (
<NavLink
key={to} to={to}
className="navbar-link"
Expand All @@ -63,9 +94,9 @@ export default function Navbar() {
</div>

{/* Right side */}
<div style={{ display: 'flex', alignItems: 'center', gap: 14, flexShrink: 0 }}>
<div className="navbar-controls" 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)' }}>
<div className="navbar-rate-limit" 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>
Expand All @@ -86,6 +117,68 @@ export default function Navbar() {
Support Us
</button>
</div>

<button
type="button"
ref={menuToggleRef}
className={`navbar-menu-toggle${isOverflowing ? ' navbar-menu-toggle-visible' : ''}`}
aria-label="Toggle navigation"
aria-expanded={mobileMenuOpen}
aria-controls="mobile-navigation"
onClick={() => setMobileMenuOpen(open => !open)}
>
<FiMenu className="navbar-menu-icon" size={19} />
<FiX className="navbar-close-icon" size={19} />
</button>

{mobileMenuOpen && (
<div id="mobile-navigation" className="mobile-nav-menu mobile-nav-menu-visible">
<div className="mobile-nav-header">
<button
type="button"
aria-label="Close navigation"
onClick={() => setMobileMenuOpen(false)}
>
<FiX size={19} />
</button>
</div>
<div className="mobile-nav-heading">Main navigation</div>
{LINKS.map(({ to, label, icon: Icon }) => (
<NavLink
key={to}
to={to}
className="navbar-link mobile-nav-row"
onClick={() => setMobileMenuOpen(false)}
style={({ isActive }) => ({
color: isActive ? 'var(--accent)' : 'var(--text2)',
background: isActive ? 'rgba(245,197,24,.1)' : 'transparent',
borderLeft: isActive ? '2px solid var(--accent)' : '2px solid transparent',
})}
>
<Icon size={16} />
<span>{label}</span>
<FiChevronRight className="mobile-nav-arrow" size={15} />
</NavLink>
))}
<div className="mobile-nav-divider" />
<div className="mobile-nav-heading">Other controls</div>
<button className="mobile-nav-row" onClick={() => { navigate('/settings'); setMobileMenuOpen(false) }}>
<FiSettings size={16} />
<span>Settings</span>
<FiChevronRight className="mobile-nav-arrow" size={15} />
</button>
<div className="mobile-nav-row">
<FiSun size={16} />
<span>Theme</span>
<span className="mobile-nav-theme-toggle"><ThemeToggle /></span>
</div>
<button className="mobile-nav-row" onClick={() => { navigate('/support-us'); setMobileMenuOpen(false) }}>
<FiHeart size={16} />
<span>Support Us</span>
<FiExternalLink className="mobile-nav-arrow" size={15} />
</button>
</div>
)}
</nav>
)
}
13 changes: 8 additions & 5 deletions src/components/RateLimitBanner.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,28 @@ export default function RateLimitBanner() {
const Icon = crit ? FiAlertTriangle : FiZap

return (
<div style={{
<div className="rate-limit-banner" style={{
borderLeft: `3px solid ${crit ? 'var(--red)' : 'var(--accent)'}`,
background: crit ? 'rgba(239,68,68,.07)' : 'rgba(245,197,24,.06)',
padding: '9px 24px',
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
}}>
<span style={{ fontSize: 12, display: 'flex', alignItems: 'center', gap: 8 }}>
<Icon size={13} color={crit ? 'var(--red)' : 'var(--accent)'} />
API RATE LIMIT: <strong style={{ marginLeft: 2 }}>{rateLimit.remaining} / {rateLimit.limit}</strong> REQUESTS REMAINING
<span className="rate-limit-top-row" style={{ fontSize: 12, display: 'flex', alignItems: 'center', gap: 8 }}>
<span className="rate-limit-summary">
<Icon size={13} color={crit ? 'var(--red)' : 'var(--accent)'} />
API RATE LIMIT: <strong style={{ marginLeft: 2 }}>{rateLimit.remaining} / {rateLimit.limit}</strong> <span className="rate-limit-remaining-label">REQUESTS REMAINING</span>
</span>
{!pat && (
<span
className="rate-limit-pat"
onClick={() => navigate('/settings')}
style={{ color: 'var(--accent)', marginLeft: 10, cursor: 'pointer', fontWeight: 600 }}
>
Add PAT for 5,000 req/hr
</span>
)}
</span>
<span style={{ fontSize: 11, color: 'var(--text2)' }}>
<span className="rate-limit-used" style={{ fontSize: 11, color: 'var(--text2)' }}>
Used: {rateLimit.used} • Reset at{' '}
{new Date(rateLimit.reset * 1000).toLocaleTimeString()}
</span>
Expand Down
42 changes: 22 additions & 20 deletions src/components/layout/Footer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const footerLinks = [
},
{
label: "Support Us",
href:"/support-us"
href: "/support-us"
}
];

Expand Down Expand Up @@ -71,23 +71,23 @@ const socialLinks = [
export default function Footer() {
const { theme } = useTheme();
return (
<footer role="contentinfo" style={{ borderTop: "1px solid var(--border)" }}>
<div className="flex w-full flex-col gap-8 px-4 py-8 md:px-6 lg:flex-row lg:items-center lg:justify-around">
<footer className="site-footer" role="contentinfo" style={{ borderTop: "1px solid var(--border)" }}>
<div className="site-footer-inner flex w-full flex-col gap-8 px-4 py-8 md:px-6 lg:flex-row lg:items-center lg:justify-around">

{/* LEFT SECTION */}
<div className="flex items-center gap-8 justify-center">
<div className="site-footer-brand flex items-center gap-8 justify-center">
{/* Logo */}
<img
src="/aossie-logo.svg"
alt="AOSSIE"
className="h-16 w-auto"/>
className="h-16 w-auto" />

{/* Separator */}
<div className="h-20 w-px bg-zinc-700" />
<div className="site-footer-divider h-20 w-px bg-zinc-700" />

{/* Description */}
<div className="max-w-sm">
<p className="mt-2 text-sm leading-5" style={{color: "var(--text2)"}}>
<div className="site-footer-description max-w-sm">
<p className="mt-2 text-sm leading-5" style={{ color: "var(--text2)" }}>
AOSSIE is a non-profit organization dedicated to building
impactful open-source software, mentoring contributors,
and fostering innovation through global collaboration.
Expand All @@ -96,20 +96,21 @@ export default function Footer() {
</div>

{/* MIDDLE SECTION */}
<div className="flex flex-col lg:flex-row lg:gap-8 items-center">
<div className="site-footer-links flex flex-col lg:flex-row lg:gap-8 items-center">
{/* Separator */}
<div className="h-25 w-px bg-zinc-700 rotate-90 lg:rotate-180" />
<div className="flex flex-col gap-6">
<div className="site-footer-divider h-25 w-px bg-zinc-700 rotate-90 lg:rotate-180" />

<div className="site-footer-links-column flex flex-col gap-6">
{/* NAVIGATION */}
<nav
aria-label="Footer Navigation"
className="flex flex-wrap items-center gap-x-6 gap-y-3 justify-center"
className="site-footer-nav flex flex-wrap items-center gap-x-6 gap-y-3 justify-center"
>
{footerLinks.map((item) => (
<Link
key={item.label}
to={item.href}
className={item.label === "Support Us" ? "site-footer-support-link" : undefined}
style={{
color: "var(--text2)",
transition: "color 0.2s ease",
Expand All @@ -127,7 +128,7 @@ export default function Footer() {
</nav>

{/* SOCIAL LINKS */}
<div className="flex items-center gap-6 justify-center">
<div className="site-footer-socials flex items-center gap-6 justify-center">
{socialLinks.map((item) => {
const Icon = item.icon;

Expand All @@ -138,6 +139,7 @@ export default function Footer() {
target="_blank"
rel="noopener noreferrer"
aria-label={`Visit our ${item.label}`}
className="site-footer-social-link"
style={{
color: "var(--text2)",
transition: "color 0.2s ease",
Expand All @@ -156,20 +158,20 @@ export default function Footer() {
</div>
</div>
</div>

{/* RIGHT SECTION */}
<div className="flex flex-col lg:flex-row lg:gap-8 items-center">
<div className="site-footer-meta-section flex flex-col lg:flex-row lg:gap-8 items-center">
{/* Separator */}
<div className="h-25 w-px bg-zinc-700 rotate-90 lg:rotate-180" />
<div className="flex flex-col gap-2 items-end text-right">
<div className="site-footer-divider h-25 w-px bg-zinc-700 rotate-90 lg:rotate-180" />

<div className="site-footer-meta flex flex-col gap-2 items-end text-right">
<p
className=" flex items-center
text-xs tracking-[0.2em]"
>
© {new Date().getFullYear()}
<span>
<Logo className="h-15 w-auto"/>
<Logo className="h-15 w-auto" />
</span>
</p>

Expand Down
6 changes: 3 additions & 3 deletions src/pages/HomePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function HomePage() {
const orgs = targets || (chips.length ? chips : input.trim() ? [input.trim()] : [])
if (!orgs.length) return
const success = await explore(orgs)
if(success) navigate('/overview')
if (success) navigate('/overview')
}

return (
Expand Down Expand Up @@ -98,7 +98,7 @@ export default function HomePage() {
<p style={{ color: 'var(--text2)', fontSize: 13 }}>{loadMsg}</p>
</div>
)}

{/* Recent */}
{recent.length > 0 && !loading && (
<div style={{ textAlign: 'center' }}>
Expand Down Expand Up @@ -128,7 +128,7 @@ export default function HomePage() {
)}

{/* Stats bar */}
<div style={{ display: 'flex', gap: 48, padding: '20px 40px', background: 'var(--surface)', borderRadius: 'var(--radius)', border: '1px solid var(--border)' }}>
<div className="home-stats-bar" style={{ display: 'flex', gap: 48, padding: '20px 40px', background: 'var(--surface)', borderRadius: 'var(--radius)', border: '1px solid var(--border)' }}>
{[['5,000', 'req/hr with PAT', 'var(--green)'], ['1HR', 'intelligent cache', 'var(--green)'], ['ZERO', 'backend latency', 'var(--accent)']].map(([v, l, color]) => (
<div key={l} style={{ textAlign: 'center' }}>
<div style={{ fontSize: 22, fontWeight: 800, color }}>{v}</div>
Expand Down
Loading
Loading