diff --git a/frontend/src/components/Navbar.css b/frontend/src/components/Navbar.css index ce1abcd..86fbc9c 100644 --- a/frontend/src/components/Navbar.css +++ b/frontend/src/components/Navbar.css @@ -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; } } diff --git a/frontend/src/components/Navbar.jsx b/frontend/src/components/Navbar.jsx index 57396bc..0cafede 100644 --- a/frontend/src/components/Navbar.jsx +++ b/frontend/src/components/Navbar.jsx @@ -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,35 +13,59 @@ const navLinks = [ export default function Navbar() { const { currentUser, logout } = useAuth(); const location = useLocation(); + const [isNavPanelOpen, setIsNavPanelOpen] = useState(false); if (!currentUser) return null; return ( - +
+ + {currentUser.email} + + + +
+ + + setIsNavPanelOpen(false)} + /> + ); } diff --git a/frontend/src/components/navPanel/NavPanel.css b/frontend/src/components/navPanel/NavPanel.css new file mode 100644 index 0000000..0997552 --- /dev/null +++ b/frontend/src/components/navPanel/NavPanel.css @@ -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; +} diff --git a/frontend/src/components/navPanel/NavPanel.jsx b/frontend/src/components/navPanel/NavPanel.jsx new file mode 100644 index 0000000..31eabeb --- /dev/null +++ b/frontend/src/components/navPanel/NavPanel.jsx @@ -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 ( + <> +
+ + + ); +}