All files / src/components/layout admin-layout.tsx

100% Statements 8/8
100% Branches 4/4
100% Functions 3/3
100% Lines 8/8

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78                  34x 34x   34x 11x     34x 5x 5x     34x                                                                                                                
import { useState, useRef, useCallback, type ReactNode } from "react";
import { Menu } from "lucide-react";
import { AdminSidebar } from "./admin-sidebar";
 
type AdminLayoutProps = {
	children: ReactNode;
};
 
export function AdminLayout({ children }: AdminLayoutProps) {
	const [sidebarOpen, setSidebarOpen] = useState(false);
	const menuButtonRef = useRef<HTMLButtonElement>(null);
 
	const openSidebar = useCallback(() => {
		setSidebarOpen(true);
	}, []);
 
	const closeSidebar = useCallback(() => {
		setSidebarOpen(false);
		menuButtonRef.current?.focus();
	}, []);
 
	return (
		<div className="flex h-screen bg-background-base">
			{/* Skip to main content link */}
			<a
				href="#main-content"
				className="sr-only focus:not-sr-only focus:absolute focus:z-50 focus:p-4 focus:bg-background-elevated focus:text-foreground-default focus:rounded-md focus:shadow-lg focus:top-4 focus:left-4"
			>
				Skip to main content
			</a>
 
			{/* Mobile sidebar overlay */}
			{sidebarOpen && (
				<button
					type="button"
					aria-label="Close sidebar overlay"
					className="fixed inset-0 z-40 bg-black/50 lg:hidden cursor-default"
					onClick={closeSidebar}
				/>
			)}
 
			{/* Sidebar */}
			<AdminSidebar
				isOpen={sidebarOpen}
				onClose={closeSidebar}
			/>
 
			{/* Main content */}
			<div
				className="flex flex-1 flex-col overflow-hidden"
				aria-hidden={sidebarOpen || undefined}
			>
				{/* Mobile header */}
				<header className="flex h-14 items-center gap-4 border-b border-border-default bg-background-elevated px-4 lg:hidden">
					<button
						ref={menuButtonRef}
						type="button"
						onClick={openSidebar}
						aria-label="Open sidebar"
						aria-expanded={sidebarOpen}
						className="p-2 -ml-2 text-foreground-muted hover:text-foreground-default hover:bg-background-muted rounded-md"
					>
						<Menu className="h-6 w-6" />
					</button>
					<span className="font-semibold text-foreground-default">
						Admin Panel
					</span>
				</header>
 
				{/* Page content */}
				<main id="main-content" className="flex-1 overflow-auto">
					<div className="p-4 sm:p-6 lg:p-8">{children}</div>
				</main>
			</div>
		</div>
	);
}