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 (
-