Files
slp-modular-cms/frontend/src/components/layout/SidebarOverlay.tsx
T
SluijsensandClaude Haiku 4.5 76b7bfc09b feat(unit-3): Layout & Navigation — sidebar, mobile overlay, theme toggle
- Remove Topbar; move UserMenu + LanguageSwitcher to sidebar footer
- Add ThemeToggle (dark/light) with localStorage persistence
- Add useTheme hook; no-flash inline script in index.html
- Add MobileBar (hamburger + app name, mobile-only)
- Add SidebarOverlay (slide-in from left, backdrop closes it)
- Sidebar: role-filtered nav (BR-U3-01–06), onClose prop for mobile
- AppLayout: desktop sidebar-only layout, mobile bar + overlay
- i18n: theme.* and nav.openMenu/closeMenu keys (NL + EN)
- Tests: 43/43 passing (14 new — useTheme, Sidebar roles, AppLayout)

Stories: US-08, US-18, US-19

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 12:03:10 +02:00

32 lines
1006 B
TypeScript

import { useEffect, useState } from 'react';
import { Sidebar } from './Sidebar';
interface SidebarOverlayProps {
onClose: () => void;
}
export function SidebarOverlay({ onClose }: SidebarOverlayProps) {
const [visible, setVisible] = useState(false);
useEffect(() => {
// Trigger enter animation on next frame
const id = requestAnimationFrame(() => setVisible(true));
return () => cancelAnimationFrame(id);
}, []);
return (
<div className="fixed inset-0 z-40 md:hidden" data-testid="sidebar-overlay">
<div
className="absolute inset-0 bg-black/50"
onClick={onClose}
data-testid="sidebar-backdrop"
/>
<div
className={`absolute left-0 top-0 h-full w-64 shadow-xl transition-transform duration-200 ${visible ? 'translate-x-0' : '-translate-x-full'}`}
>
<Sidebar onClose={onClose} />
</div>
</div>
);
}