Merge pull request #25 from kjannette/media-queries-2

mobile navigation
This commit is contained in:
S Jannette
2026-03-05 11:04:07 -05:00
committed by GitHub
4 changed files with 266 additions and 66 deletions

View File

@@ -8,6 +8,19 @@
border-bottom: 1px solid var(--color-border-light);
}
/* ── Left Group: Brand + Links ───────────────────────────── */
.navbar__left {
display: flex;
align-items: center;
gap: 0.5rem;
}
.navbar__brand-group {
display: flex;
align-items: center;
}
.navbar__brand {
font-weight: 700;
font-size: 1.4rem;
@@ -38,6 +51,14 @@
background-color: var(--color-bg-card);
}
/* ── Right Group: Email + Logout + Hamburger ─────────────── */
.navbar__right {
display: flex;
align-items: center;
gap: 1rem;
}
.navbar__user {
font-size: 1.275rem;
color: #777;
@@ -53,6 +74,10 @@
color: var(--color-primary-hover);
}
.navbar__user-link--mobile {
display: none;
}
.navbar__logout {
padding: 0.4rem 1rem;
font-size: 1.275rem;
@@ -65,59 +90,78 @@
transition: all 0.15s ease;
}
/* ── Navbar Responsive ───────────────────────────────────── */
/* ── Hamburger Icon (hidden on desktop) ──────────────────── */
.navbar__hamburger {
display: none;
flex-direction: column;
justify-content: center;
gap: 5px;
background: none;
border: none;
cursor: pointer;
padding: 4px;
}
.navbar__hamburger-bar {
display: block;
width: 28px;
height: 3px;
background-color: var(--color-brand);
border-radius: 2px;
}
/* ── Responsive: Tablet & below (≤ 768px) ────────────────── */
@media (max-width: 768px) {
.navbar {
flex-wrap: wrap;
gap: 0.75rem;
padding: 0.75rem 1rem;
}
.navbar__brand {
margin-right: 1rem;
font-size: 1.25rem;
}
.navbar__links {
flex-wrap: wrap;
gap: 0.2rem;
}
.navbar__link {
padding: 0.35rem 0.75rem;
font-size: 1.2rem;
}
.navbar__user {
font-size: 1.1rem;
}
.navbar__logout {
padding: 0.3rem 0.75rem;
font-size: 1.1rem;
}
}
@media (max-width: 480px) {
.navbar {
.navbar__brand-group {
flex-direction: column;
align-items: flex-start;
padding: 0.75rem;
gap: 0.5rem;
}
.navbar__links {
width: 100%;
gap: 0.15rem;
}
.navbar__link {
padding: 0.3rem 0.6rem;
font-size: 1.05rem;
}
.navbar__brand {
margin-right: 0;
font-size: 1.25rem;
}
.navbar__links {
display: none;
}
.navbar__user-link--mobile {
display: block;
font-size: 0.95rem;
}
.navbar__user-link--desktop {
display: none;
}
.navbar__logout {
display: none;
}
.navbar__hamburger {
display: flex;
}
}
/* ── Responsive: Mobile (≤ 480px) ────────────────────────── */
@media (max-width: 480px) {
.navbar {
padding: 0.75rem;
}
.navbar__brand {
font-size: 1.15rem;
}
.navbar__user-link--mobile {
font-size: 0.85rem;
}
}

View File

@@ -1,5 +1,7 @@
import { useState } from "react";
import { Link, useLocation } from "react-router-dom";
import { useAuth } from "../contexts/AuthContext";
import NavPanel from "./navPanel/NavPanel";
import "./Navbar.css";
const navLinks = [
@@ -11,13 +13,20 @@ const navLinks = [
export default function Navbar() {
const { currentUser, logout } = useAuth();
const location = useLocation();
const [isNavPanelOpen, setIsNavPanelOpen] = useState(false);
if (!currentUser) return null;
return (
<>
<nav className="navbar">
<div className="flex flex--center gap-sm">
<div className="navbar__left">
<div className="navbar__brand-group">
<span className="navbar__brand">Koin Ping</span>
<Link to="/account" className="navbar__user-link navbar__user-link--mobile">
{currentUser.email}
</Link>
</div>
<div className="navbar__links">
{navLinks.map(({ to, label }) => {
const isActive = location.pathname === to;
@@ -34,12 +43,29 @@ export default function Navbar() {
</div>
</div>
<div className="flex flex--center gap-lg">
<Link to="/account" className="navbar__user navbar__user-link">{currentUser.email}</Link>
<div className="navbar__right">
<Link to="/account" className="navbar__user navbar__user-link navbar__user-link--desktop">
{currentUser.email}
</Link>
<button onClick={logout} className="navbar__logout">
Logout
</button>
<button
className="navbar__hamburger"
onClick={() => setIsNavPanelOpen(true)}
aria-label="Open navigation menu"
>
<span className="navbar__hamburger-bar" />
<span className="navbar__hamburger-bar" />
<span className="navbar__hamburger-bar" />
</button>
</div>
</nav>
<NavPanel
isOpen={isNavPanelOpen}
onClose={() => setIsNavPanelOpen(false)}
/>
</>
);
}

View File

@@ -0,0 +1,78 @@
/* ── Overlay Backdrop ─────────────────────────────────────── */
.nav-panel__overlay {
position: fixed;
inset: 0;
background-color: rgba(0, 0, 0, 0.45);
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
z-index: 900;
}
.nav-panel__overlay--visible {
opacity: 1;
pointer-events: auto;
}
/* ── Slide-out Panel ─────────────────────────────────────── */
.nav-panel {
position: fixed;
top: 0;
left: 0;
width: 260px;
height: 100%;
background-color: var(--color-bg-elevated);
border-right: 1px solid var(--color-border);
transform: translateX(-100%);
transition: transform 0.3s ease;
z-index: 950;
display: flex;
flex-direction: column;
padding: 1.5rem 0;
}
.nav-panel--open {
transform: translateX(0);
}
/* ── Nav Links ───────────────────────────────────────────── */
.nav-panel__nav {
display: flex;
flex-direction: column;
flex: 1;
}
.nav-panel__link {
padding: 0.9rem 1.5rem;
text-decoration: none;
font-size: 1.3rem;
font-weight: 200;
color: var(--color-text-subtle);
border-left: 3px solid transparent;
transition: background-color 0.15s ease, color 0.15s ease;
}
.nav-panel__link--active {
font-weight: 600;
color: var(--color-text);
background-color: var(--color-bg-card);
border-left-color: var(--color-brand);
}
/* ── Logout Button ───────────────────────────────────────── */
.nav-panel__logout {
margin: 1rem 1.5rem;
padding: 0.5rem 1rem;
font-size: 1.15rem;
font-weight: 400;
background-color: transparent;
color: var(--color-text-subtle);
border: 1px solid var(--color-border);
border-radius: var(--radius-lg);
cursor: pointer;
transition: all 0.15s ease;
}

View File

@@ -0,0 +1,52 @@
import { Link, useLocation } from "react-router-dom";
import { useAuth } from "../../contexts/AuthContext";
import "./NavPanel.css";
const navLinks = [
{ to: "/addresses", label: "Addresses" },
{ to: "/alerts", label: "Configure Alerts" },
{ to: "/alertevents", label: "Alert Event History" },
];
export default function NavPanel({ isOpen, onClose }) {
const { logout } = useAuth();
const location = useLocation();
const handleNavClick = () => {
onClose();
};
const handleLogout = () => {
onClose();
logout();
};
return (
<>
<div
className={`nav-panel__overlay${isOpen ? " nav-panel__overlay--visible" : ""}`}
onClick={onClose}
/>
<aside className={`nav-panel${isOpen ? " nav-panel--open" : ""}`}>
<nav className="nav-panel__nav">
{navLinks.map(({ to, label }) => {
const isActive = location.pathname === to;
return (
<Link
key={to}
to={to}
className={`nav-panel__link${isActive ? " nav-panel__link--active" : ""}`}
onClick={handleNavClick}
>
{label}
</Link>
);
})}
</nav>
<button onClick={handleLogout} className="nav-panel__logout">
Logout
</button>
</aside>
</>
);
}