# Frontend Components — Unit 3: Layout & Navigation ## Modified Components ### `AppLayout.tsx` (modify existing) **Path**: `frontend/src/components/layout/AppLayout.tsx` Remove `Topbar` import and render. Add `MobileBar`. Layout becomes: ```tsx
{/* desktop only */} {/* mobile only */}
``` Mobile open/close state lives here (or in `MobileBar`). --- ### `Sidebar.tsx` (modify existing) **Path**: `frontend/src/components/layout/Sidebar.tsx` Changes: - Add `roles?: Role[]` to `NavItem` interface - Filter `NAV_ITEMS` by `user.role` before rendering - Add `SidebarFooter` section at bottom with `LanguageSwitcher`, `ThemeToggle`, `UserMenu` - Accept optional `onClose?: () => void` prop for mobile overlay close button - `data-testid="app-sidebar"` retained Nav items: | Label key | Route | Roles | Icon | |---|---|---|---| | `nav.dashboard` | `/dashboard` | all | `LayoutDashboard` | | `nav.users` | `/users` | Owner, Administrator | `Users` | | `nav.settings` | `/settings` | Owner | `Settings` | | `nav.cms` | `/cms` | Owner | `FileText` | | `nav.profile` | `/profile` | all | `User` | --- ## New Components ### `MobileBar.tsx` **Path**: `frontend/src/components/layout/MobileBar.tsx` Slim bar, visible only on `< md`. Contains hamburger button (`Menu` icon) and app name. ```tsx
{t('common.appName')}
``` Props: `onMenuOpen: () => void` --- ### `SidebarOverlay.tsx` **Path**: `frontend/src/components/layout/SidebarOverlay.tsx` Wraps `` in a backdrop overlay for mobile: ```tsx
``` Only rendered when mobile menu is open. --- ### `ThemeToggle.tsx` **Path**: `frontend/src/components/layout/ThemeToggle.tsx` Button that reads/writes `cms-theme` in localStorage and toggles `dark` class on ``. ```tsx ``` Uses `useTheme()` hook (see below). --- ### `useTheme.ts` **Path**: `frontend/src/hooks/useTheme.ts` ```ts function useTheme(): { theme: Theme; toggleTheme: () => void } ``` - Reads initial value from `localStorage['cms-theme']` or `prefers-color-scheme` - On toggle: flips theme, writes to localStorage, applies class to `document.documentElement` --- ## Removed Components ### `Topbar.tsx` Deleted. Functionality moved to Sidebar footer (`LanguageSwitcher`, `UserMenu`). `data-testid="app-topbar"` removed from the DOM. --- ## i18n Keys (additions to `translation.json`) ```json { "nav": { "settings": "Instellingen" }, "theme": { "switchToLight": "Overschakelen naar licht thema", "switchToDark": "Overschakelen naar donker thema" } } ``` (English equivalents added to `en/translation.json`) --- ## Test IDs Summary | Element | `data-testid` | |---|---| | Sidebar (desktop) | `app-sidebar` | | Mobile bar | `app-mobile-bar` | | Hamburger button | `mobile-menu-button` | | Sidebar backdrop | `sidebar-backdrop` | | Theme toggle button | `theme-toggle` | | Nav: dashboard | `nav-dashboard` | | Nav: users | `nav-users` | | Nav: settings | `nav-settings` | | Nav: cms | `nav-cms` | | Nav: profile | `nav-profile` | | Main content area | `app-main` |