docs(unit-3): Complete functional design based on user answers

All Q1-Q5 answered A:
- Topbar removed; LanguageSwitcher + UserMenu move to sidebar footer
- Mobile: slide-over overlay with hamburger button
- Theme toggle in sidebar footer
- No-flash init via inline script in index.html
- Role-filtered sidebar items client-side

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 11:51:24 +02:00
co-authored by Claude Haiku 4.5
parent 037332e52f
commit 6760257e49
5 changed files with 364 additions and 6 deletions
@@ -0,0 +1,56 @@
# Business Rules — Unit 3: Layout & Navigation
## Navigation Visibility Rules (BR-U3-01 BR-U3-06)
| Route / Item | Owner | Administrator | User | Rule ID |
|---|---|---|---|---|
| Dashboard (`/dashboard`) | ✅ visible | ✅ visible | ✅ visible | BR-U3-01 |
| User Management (`/users`) | ✅ visible | ✅ visible | ❌ hidden | BR-U3-02 |
| System Settings (`/settings`) | ✅ visible | ❌ hidden | ❌ hidden | BR-U3-03 |
| CMS Management (`/cms`) | ✅ visible | ❌ hidden | ❌ hidden | BR-U3-04 |
| Profile (`/profile`) | ✅ visible | ✅ visible | ✅ visible | BR-U3-05 |
| Logout | ✅ visible | ✅ visible | ✅ visible | BR-U3-06 |
Sidebar items are filtered client-side based on `user.role` from `AuthContext`. The backend is the authoritative enforcement point; sidebar filtering is defence-in-depth UX only.
---
## Active Route Highlighting (BR-U3-07)
The sidebar highlights the nav item whose `to` path matches the current route via TanStack Router `activeProps`. Exact match for leaf routes; prefix match for section roots.
---
## Responsive Behaviour (BR-U3-08)
- **≥ 768px (md)**: sidebar always visible at fixed width (`w-64`), no top bar.
- **< 768px**: sidebar hidden by default. A slim mobile bar (hamburger + app name) is shown. Tapping the hamburger opens the sidebar as a slide-over overlay.
- The overlay closes when: the user taps the backdrop, taps the close button in the sidebar, or navigates to a new route.
---
## Topbar Removal (BR-U3-09)
The `Topbar` component is removed entirely. No top bar exists on desktop. A slim mobile-only bar replaces it solely for the hamburger button. All functionality previously in the Topbar (`LanguageSwitcher`, `UserMenu`) moves to the sidebar footer.
---
## Theme Toggle (BR-U3-10 BR-U3-13)
| Rule | Description |
|---|---|
| BR-U3-10 | Toggle switches between `light` and `dark` class on `<html>` immediately |
| BR-U3-11 | Chosen theme persisted in `localStorage` under key `cms-theme` |
| BR-U3-12 | On app load, persisted preference applied before first React render via inline script in `index.html` (no flash) |
| BR-U3-13 | If no preference is stored, OS preference (`prefers-color-scheme`) is used as default |
Only `cms-theme` is stored in localStorage — no auth data.
---
## Sidebar Footer (BR-U3-14)
The sidebar footer contains three controls in a fixed bottom section:
1. `LanguageSwitcher` (moved from Topbar)
2. `ThemeToggle` (new)
3. `UserMenu` (moved from Topbar) — shows name, email, logout action