14 KiB
PRD: Responsive Scaling & Mobile Layout
Introduction
The dashboard is built for 1080p screens. On larger displays (1440p, 4K), everything appears too small — text, spacing, and UI elements don't scale with the viewport. On mobile, the sidebar is completely inaccessible (hidden with no toggle), text doesn't wrap properly and spills off-screen, and several components are unusable at narrow widths.
This PRD addresses viewport-responsive scaling for larger screens and usability fixes for mobile, scoped to the dashboard phase only (TopBar, Sidebar, Card Grid, and all tiles).
Goals
- Scale the dashboard proportionally on larger viewports (1440p should feel ~25% larger than 1080p)
- Make the sidebar accessible on mobile via a slide-out drawer with toggle
- Ensure all text wraps properly and nothing overflows horizontally at any viewport size
- Maintain the current 1080p experience as the baseline — no changes at that resolution
- Preserve the existing visual design language (fonts, colors, spacing ratios)
User Stories
US-000: Skip Boot/Login for Dev Iteration
Description: As a developer, I want to skip the boot/ECG/login animation during this feature branch so I can iterate on the dashboard quickly.
Acceptance Criteria:
- In
App.tsx, initial Phase state changed from'boot'to'pmr' - Boot, ECG, and login code remains — only initial state changes
- App loads directly to dashboard on refresh
- Typecheck passes
- Reverted in final story (US-013)
US-001: Fluid Root Font-Size Scaling
Description: As a user on a high-resolution display, I want the dashboard to scale proportionally so that text and UI elements are comfortably sized without manual browser zoom.
Acceptance Criteria:
htmlelement uses aclamp()-based font-size that scales with viewport width- At 1920px viewport width (1080p), effective font-size remains ~15px (current baseline)
- At 2560px viewport width (1440p), effective font-size is ~18–19px (~25% increase)
- At 3840px viewport width (4K), font-size caps at a sensible maximum (~22px)
- Below 1920px, font-size does not shrink below 15px (mobile/tablet keeps baseline)
- Typecheck passes
US-002: Convert Fixed px to rem in Layout Structure
Description: As a developer, I need layout measurements to use rem so they scale with the root font-size, rather than remaining fixed at px values.
Acceptance Criteria:
- CSS custom properties
--topbar-height,--sidebar-width,--subnav-heightconverted from px to rem DashboardLayout.tsxmargin/padding/height calculations use rem-based values- Card padding converted to rem
- Grid gaps converted to rem
- Dashboard content area scales proportionally with root font-size
- At 1080p, layout looks identical to current (no visual regression)
- Typecheck passes
- Verify in browser using dev-browser skill
US-003: Convert Fixed px to rem in Typography
Description: As a user on any screen size, I want text to scale with the viewport so it's always readable without zooming.
Acceptance Criteria:
- All inline
fontSizestyles in tile components converted from px to rem (e.g.,13px→0.8125rembased on 16px root, or equivalent relative to 15px base) - TopBar text sizes converted to rem
- Sidebar text sizes converted to rem
- Card header text sizes converted to rem
- At 1080p, text sizes are visually identical to current
- At 1440p, text is proportionally larger and readable
- Typecheck passes
- Verify in browser using dev-browser skill
US-004: Convert Fixed px to rem in Spacing & Components
Description: As a developer, I need padding, margins, icon sizes, and component dimensions to scale with viewport so the UI stays proportional.
Acceptance Criteria:
- Inline padding/margin values in tiles converted from px to rem
- Badge/tag padding and sizing converted to rem
- Icon sizes (where set inline) use rem
- Border-radius values may remain in px (they don't need to scale)
- At 1080p, spacing is visually identical to current
- Typecheck passes
- Verify in browser using dev-browser skill
US-005: Mobile Sidebar Drawer
Description: As a mobile user, I want to access the sidebar content (person details, tags, alerts) via a slide-out drawer so I can see this information without it permanently taking screen space.
Acceptance Criteria:
- TopBar shows a menu/hamburger icon on screens below
lgbreakpoint (1024px) - Tapping the icon opens the sidebar as a slide-out drawer overlay from the left
- Drawer includes a semi-transparent backdrop that closes the drawer on tap
- Drawer contains the full sidebar content (PersonHeader, Tags, Alerts)
- Drawer can be closed via the backdrop tap, a close button, or pressing Escape
- Drawer uses the same animation timing as existing UI (200ms ease-out)
- Drawer respects
prefers-reduced-motion(skip to final state) - Sidebar remains inline (non-drawer) on
lg+screens — no behavior change on desktop - Typecheck passes
- Verify in browser using dev-browser skill
US-006: Fix Text Wrapping & Overflow
Description: As a mobile user, I want all text content to wrap properly within its containers so nothing is cut off or requires horizontal scrolling.
Acceptance Criteria:
- No horizontal scrollbar appears at any viewport width (320px to 3840px)
- All text in tile components wraps within its container — no off-screen overflow
- Long skill names in CoreSkillsTile truncate with ellipsis rather than breaking layout
- Career Activity entries wrap cleanly at narrow widths
- PatientSummaryTile stats grid reflows to fewer columns on narrow screens
- KPI cards in LatestResultsTile stack or reflow on mobile (no horizontal overflow)
- Education entries wrap properly
- Project entries wrap properly
overflow-x: hiddenon the main content area as a safety net (not a primary fix — actual wrapping must work)- Typecheck passes
- Verify in browser using dev-browser skill
US-007: Career Constellation Chart — Responsive Container Sizing
Description: As a user on any device, I want the D3 career constellation chart (CareerConstellation.tsx) to fit its container without overflowing, so the visualization is usable at all viewport widths.
Acceptance Criteria:
- Chart SVG width/height derived from container dimensions (not hardcoded px)
- Chart re-renders or resizes on viewport/container resize (via
ResizeObserveror equivalent) - D3 force simulation parameters (charge strength, link distance, node spacing) adapt to available width
- On mobile (<768px), chart remains visible and nodes don't overlap excessively or overflow
- Node labels remain legible at small sizes (consider hiding secondary labels on narrow viewports)
- Chart does not cause horizontal scrollbar at any viewport width
- Typecheck passes
- Verify in browser using dev-browser skill
US-008: Career Constellation Chart — Mobile Interaction
Description: As a mobile user, I want to interact with the career constellation chart using touch so I can explore roles and skills.
Acceptance Criteria:
- Nodes are tappable on touch devices (adequate touch target size, minimum ~44px)
- Tap on a role node triggers the same action as click (opens role detail)
- Tap on a skill node triggers the same action as click (opens skill detail)
- No hover-dependent information is inaccessible on touch (tooltips show on tap or info is always visible)
- Chart doesn't conflict with page scroll (vertical scroll still works when touching the chart area)
- Typecheck passes
- Verify in browser using dev-browser skill
US-009: TopBar Mobile Refinements
Description: As a mobile user, I want the TopBar to remain functional and readable at narrow viewport widths.
Acceptance Criteria:
- Hamburger/menu icon appears at the left of the TopBar below
lgbreakpoint - Brand text collapses gracefully (already mostly handled — verify no regression)
- Search trigger remains accessible on mobile (either inline icon or within command palette trigger)
- Session info collapses gracefully at narrow widths (already mostly handled — verify no regression)
- TopBar height scales with rem (from US-002)
- No horizontal overflow from TopBar content
- Typecheck passes
- Verify in browser using dev-browser skill
US-010: Verify at Key Viewport Sizes
Description: As a developer, I need to verify the dashboard renders correctly at representative viewport sizes to confirm no regressions.
Acceptance Criteria:
- 375px wide (iPhone SE) — single column, drawer sidebar, all text wraps, no overflow
- 768px wide (iPad portrait) — single column, drawer sidebar, comfortable spacing
- 1024px wide (iPad landscape / small laptop) — sidebar inline, 2-column grid
- 1920px wide (1080p) — visually identical to current production
- 2560px wide (1440p) — ~25% scaled up, proportional layout, readable
- Typecheck passes
- Verify in browser using dev-browser skill
US-011: Re-enable Boot/Login Sequence
Description: As a user, I want the full boot → ECG → login experience restored for production.
Acceptance Criteria:
- In
App.tsx, initial Phase state reverted from'pmr'back to'boot' - Full boot → ECG → login → dashboard sequence works end to end
- No other changes to
App.tsx - Typecheck passes
- Verify full sequence works via Playwright MCP
Functional Requirements
- FR-1: Set
html { font-size: clamp(...) }that scales from 15px at 1920px to ~22px at 3840px, floored at 15px below 1920px - FR-2: Convert all CSS custom properties used for layout dimensions (
--topbar-height,--sidebar-width,--subnav-height) to rem units - FR-3: Convert all inline
fontSize,padding,margin, andgapvalues in dashboard components from px to rem - FR-4: Add a mobile sidebar drawer component (slide-from-left overlay, backdrop, close on escape/backdrop-tap)
- FR-5: Add a hamburger menu button to TopBar, visible below
lgbreakpoint, that toggles the sidebar drawer - FR-6: Apply
overflow-wrap: break-wordand appropriatemin-width: 0on flex/grid children to prevent text overflow - FR-7: Ensure
overflow-x: hiddenon the main scrollable content area as a catch-all - FR-8: Tile content must reflow (fewer grid columns, stacked layout) at narrow viewports rather than overflowing
- FR-9: Career Constellation D3 chart must size to its container, re-render on resize, and adapt force simulation parameters for narrow viewports
- FR-10: D3 chart nodes must have adequate touch targets (44px minimum) and not block page scroll on touch devices
Non-Goals
- No permanent changes to Boot, ECG, or Login phases (temporarily skipped for dev, restored in final story)
- No changes to the 1080p visual appearance (it's the baseline)
- No changes to color palette, fonts, or design language
- No new responsive breakpoints beyond what Tailwind already provides (xs/sm/md/lg/xl)
- No container queries or component-level responsive logic — viewport scaling via root font-size is the mechanism
- No changes to Command Palette responsive behavior (separate concern)
- No touch gesture support (swipe to open sidebar, etc.)
Design Considerations
- The sidebar drawer on mobile should visually match the existing sidebar styling — same background (
#F7FAFA), same border, same content - The drawer should overlay content with a semi-transparent backdrop, similar to the existing detail panel pattern used for project/career detail expansion
- The hamburger icon should use
lucide-react(e.g.,Menuicon) consistent with existing icon usage - Font-size scaling should be smooth (fluid), not stepped at breakpoints, to avoid jarring jumps during window resize
Technical Considerations
- rem base calculation: Since the current design uses
15pxas the body font-size, the rem conversion should be based on15px = 1rem(set onhtml). At 1080p,1rem = 15px. At 1440p,1rem ≈ 18.75px. - Conversion formula:
px / 15 = rem(e.g.,13px = 0.867rem,48px = 3.2rem,272px = 18.133rem) - Tailwind classes: Tailwind's spacing scale uses a 16px rem base by default. Since we're changing the html font-size, Tailwind rem-based classes (
p-4,text-sm, etc.) will automatically scale. Only inlinepxstyles need manual conversion. - CSS custom properties: Convert
--topbar-height: 48px→--topbar-height: 3.2rem, etc. - Sidebar drawer state: Managed via React state in
DashboardLayout.tsx, passed down or via context. Keep it simple —useState<boolean>for open/closed. - Animations: Drawer slide uses
transform: translateX(-100%)→translateX(0)with 200ms ease-out, consistent with existing motion patterns.
Success Metrics
- At 1440p, the dashboard is comfortably readable without browser zoom adjustments
- On mobile (375px), all content is accessible, readable, and no horizontal scrolling occurs
- Sidebar content is accessible on all screen sizes
- No visual regression at 1080p
- Zero horizontal overflow at any viewport width between 320px and 3840px
Open Questions
- Should the mobile drawer have a swipe-to-close gesture? (Deferred as non-goal for now, can add later)
- Should the search bar be accessible on mobile via a dedicated icon in TopBar? (Currently hidden below md — may want a small search icon)
- At what viewport width should font scaling cap? (PRD suggests 3840px / ~22px — may need tuning)