# Reference: Task 7 — DashboardLayout ## Overview Create the main layout component that replaces `PMRInterface.tsx`. This is the container that houses TopBar, Sidebar, and the scrollable card grid of tiles. ## File: `src/components/DashboardLayout.tsx` ### Layout Structure ``` ┌────────────────────────────────────────────────────┐ │ TopBar (fixed, z-100, height: 48px) │ ├──────────┬─────────────────────────────────────────┤ │ │ │ │ Sidebar │
— scrollable card grid │ │ (272px) │ padding: 24px 28px 40px │ │ fixed │ │ │ │ grid: 1fr 1fr, gap: 16px │ │ │ │ │ │ [PatientSummary — full] │ │ │ [LatestResults] [CoreSkills] │ │ │ [LastConsultation — full] │ │ │ [CareerActivity — full] │ │ │ [Education — full] │ │ │ [Projects — full] │ │ │ │ └──────────┴─────────────────────────────────────────┘ ``` ### CSS Layout ``` .layout { display: flex; margin-top: var(--topbar-height); /* 48px */ height: calc(100vh - var(--topbar-height)); } .sidebar { /* See ref-03-topbar-sidebar.md for sidebar specs */ width: var(--sidebar-width); min-width: var(--sidebar-width); /* ... */ } .main { flex: 1; overflow-y: auto; padding: 24px 28px 40px; } .card-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; } @media (max-width: 900px) { .card-grid { grid-template-columns: 1fr; } } ``` Use Tailwind classes for all of this — the CSS above is for reference only. ### Framer Motion Entrance Animations Staggered entrance when dashboard first renders (after login): 1. **TopBar**: slides down from `-48px`, 200ms ease-out 2. **Sidebar**: slides from `-272px` left, 250ms ease-out, 50ms delay 3. **Main content**: fades in (opacity 0→1), 300ms, 150ms delay ```typescript const topbarVariants = { hidden: { y: -48, opacity: 0 }, visible: { y: 0, opacity: 1, transition: { duration: 0.2, ease: 'easeOut' } } } const sidebarVariants = { hidden: { x: -272, opacity: 0 }, visible: { x: 0, opacity: 1, transition: { duration: 0.25, ease: 'easeOut', delay: 0.05 } } } const contentVariants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { duration: 0.3, delay: 0.15 } } } ``` With `prefers-reduced-motion`: all durations → 0, no delays. ### Tile Ordering in Grid The card grid renders tiles in this order: 1. `PatientSummaryTile` — `grid-column: 1 / -1` (full width) 2. `LatestResultsTile` — single column (left) 3. `CoreSkillsTile` — single column (right) 4. `LastConsultationTile` — `grid-column: 1 / -1` (full width) 5. `CareerActivityTile` — `grid-column: 1 / -1` (full width) 6. `EducationTile` — `grid-column: 1 / -1` (full width) 7. `ProjectsTile` — `grid-column: 1 / -1` (full width) ### App.tsx Wiring In `src/App.tsx`, the PMR phase currently renders ``. Change it to render ``. ```typescript // In App.tsx phase switch: case 'pmr': return ``` Keep all other phases (boot, ecg, login) unchanged. The SkipButton that skips to login should still work. ### Scrollbar Styling Main content area scrollbar (matches concept): - Width: 6px - Track: transparent - Thumb: var(--border) (#D4E0DE), border-radius 3px ### Command Palette Integration The DashboardLayout should render the `CommandPalette` component (from Task 18) at the layout level, so it overlays the entire dashboard when triggered. For now (Task 7), just add a placeholder comment or empty div where it will go. The TopBar search bar's click handler should be wired to open the palette (but the palette itself comes in Task 18). ### Background Color Transition The login screen has background `#1E293B`. The dashboard has background `#F0F5F4`. This transition should happen smoothly. Options: 1. The DashboardLayout entrance animation covers the transition (content fades in over the dark background, replacing it) 2. A brief CSS transition on the body/root background color 3. Handle it in App.tsx with a state-based background The simplest approach is option 1 — the dashboard's entrance animation effectively replaces the dark login background with the light dashboard.