diff --git a/apps/backoffice/app/components/JobsIndicator.tsx b/apps/backoffice/app/components/JobsIndicator.tsx index 65454fa..8bd793c 100644 --- a/apps/backoffice/app/components/JobsIndicator.tsx +++ b/apps/backoffice/app/components/JobsIndicator.tsx @@ -146,15 +146,27 @@ export function JobsIndicator() { /> + {/* Backdrop mobile */} + {isOpen && ( +
setIsOpen(false)} + aria-hidden="true" + /> + )} + {/* Popin/Dropdown with glassmorphism */} {isOpen && (
diff --git a/apps/backoffice/app/components/MobileNav.tsx b/apps/backoffice/app/components/MobileNav.tsx new file mode 100644 index 0000000..0e5ffa0 --- /dev/null +++ b/apps/backoffice/app/components/MobileNav.tsx @@ -0,0 +1,93 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { createPortal } from "react-dom"; +import Link from "next/link"; +import { NavIcon } from "./ui"; + +type NavItem = { + href: "/" | "/books" | "/libraries" | "/jobs" | "/tokens" | "/settings"; + label: string; + icon: "dashboard" | "books" | "libraries" | "jobs" | "tokens" | "settings"; +}; + +const HamburgerIcon = () => ( + + + +); + +const XIcon = () => ( + + + +); + +export function MobileNav({ navItems }: { navItems: NavItem[] }) { + const [isOpen, setIsOpen] = useState(false); + const [mounted, setMounted] = useState(false); + + useEffect(() => { + setMounted(true); + }, []); + + const overlay = ( + <> + {/* Backdrop */} +
setIsOpen(false)} + aria-hidden="true" + /> + + {/* Drawer */} +
+
+ Navigation +
+ + +
+ + ); + + return ( + <> + {/* Hamburger button — reste dans le header */} + + + {/* Backdrop + Drawer portés directement sur document.body, + hors du header et de son backdrop-filter */} + {mounted && createPortal(overlay, document.body)} + + ); +} diff --git a/apps/backoffice/app/layout.tsx b/apps/backoffice/app/layout.tsx index 6cbb6dc..3d71b80 100644 --- a/apps/backoffice/app/layout.tsx +++ b/apps/backoffice/app/layout.tsx @@ -7,6 +7,7 @@ import { ThemeProvider } from "./theme-provider"; import { ThemeToggle } from "./theme-toggle"; import { JobsIndicator } from "./components/JobsIndicator"; import { NavIcon, Icon } from "./components/ui"; +import { MobileNav } from "./components/MobileNav"; export const metadata: Metadata = { title: "StripStream Backoffice", @@ -61,17 +62,17 @@ export default function RootLayout({ children }: { children: ReactNode }) {
{navItems.map((item) => ( - - - {item.label} + + + {item.label} ))}
- + {/* Actions */}
- +
@@ -95,18 +97,19 @@ export default function RootLayout({ children }: { children: ReactNode }) { } // Navigation Link Component -function NavLink({ href, children }: { href: NavItem["href"]; children: React.ReactNode }) { +function NavLink({ href, title, children }: { href: NavItem["href"]; title?: string; children: React.ReactNode }) { return ( -