18 KiB
Implementation Plan — Design 7: The Clinical Record (v2)
Project Overview
Redesign of the Clinical Record PMR interface to achieve absolute thematic fidelity to real NHS clinical software (EMIS Web, SystmOne). The codebase has existing components from a prior iteration that are functionally complete but lack the visual density, authentic clinical system feel, and design quality described in the specification. This plan rebuilds each visual component to production-showcase quality.
Core principle: This is NOT a clinical "theme" loosely applied — it's a faithful digital clinical information system. Every element must look like it belongs in actual NHS software. Border-heavy, table-heavy, functional — zero decorative flourish.
Data files are correct and complete (src/data/*). The existing type system (src/types/pmr.ts) is sound. The phase management in App.tsx works. This plan focuses on rebuilding the visual layer to match the specification.
Quality Checks
Run ALL of these after each task. All must pass before committing.
npm run typechecknpm run lintnpm run build
Reference Files
Each task below references a specific file in Ralph/refs/ — read ONLY that file for the task context. Do NOT read goal.md directly (it's 1100+ lines and will overwhelm your context).
Tasks
-
Task 1: Design system foundation and font setup. Read
Ralph/refs/ref-design-system.md. Audit and fix the Tailwind config (tailwind.config.js) and global CSS (src/index.css) to ensure ALL PMR color tokens, typography, and spacing match the design system spec exactly. Specific fixes needed: (a) Ensure Geist Mono font is loaded via Google Fonts or local import — currently the project uses Fira Code for monospace but the spec requires Geist Mono for coded entries, timestamps, and data values. (b) Verify all PMR color tokens exist in Tailwind config: main content#F5F7FA, cards#FFFFFF, sidebar#1E293B, patient banner#334155, NHS blue#005EB8, green#22C55E, amber#F59E0B, red#EF4444, text primary#111827, text secondary#6B7280. (c) Ensure border-radius defaults to 4px for cards/inputs (not 8px or 12px — clinical systems use minimal rounding). (d) Add a.pmr-themeclass or CSS custom properties layer for PMR-specific tokens if not already present. (e) Verify Inter font is loaded and configured as the primary font family. Do NOT invoke /frontend-design for this task — it's pure configuration. -
Task 1b: Rebuild boot sequence and ECG animation. Read
Ralph/refs/ref-boot-ecg.mdandRalph/refs/ref-design-system.md. Also readECGCombined.tsxin the project root for the Remotion reference implementation of the mask-based text reveal. This task covers the full pre-login animation flow: (a) Refactor BootSequence.tsx — replace hardcoded HTML strings with a clean config-driven structure. Each line type (header, field, separator, module, ready) maps to a React component. Keep the same visual output: green-on-black terminal, Fira Code font, 220ms staggered line reveals,#00ff41bright green /#3a6b45dim green /#00e5ffcyan labels. (b) Cursor → dot transition — the blinking green cursor at the end of boot must smoothly morph into the ECG's glowing trace dot. Capture the cursor's screen position and pass it to ECGAnimation as astartPositionprop. The cursor stops blinking, transitions from block to circular glow (~300ms), then begins moving rightward as the ECG trace dot. (c) ECG start sync — ECGAnimation must start its trace from the cursor position (not the far left edge). The first beat begins after a flat gap from the cursor position. Shift the world-space origin so the trace starts where the cursor was. (d) Mask-based text reveal — adopt ECGCombined.tsx's technique where pre-rendered stroke-only text is revealed by a wipe mask following the trace head (instead of the current alpha fade approach). Keep the current character spacing (LETTER_W,LETTER_G,SPACE_W) and heartbeat waveform. Add connector lines between letters at baseline. (e) Keep: heartbeat shape, beat timing (0.3→0.55→0.85→1.0 amplitude), canvas rendering, viewport scrolling, flatline draw, scanlines, vignette, background transition to#1E293B. (f) Respectprefers-reduced-motion— with reduced motion, skip animation and show static final frame or jump to login. -
Task 2: Rebuild LoginScreen component. Read
Ralph/refs/ref-transition-login.mdandRalph/refs/ref-design-system.md. Rebuildsrc/components/LoginScreen.tsxto match the login sequence specification exactly: (a) Dark blue-gray#1E293Bbackground. (b) White card: 320px wide, 12px border-radius (exception to the 4px rule — login cards can be rounder), subtle shadow. (c) NHS-blue shield icon at top with "CareerRecord PMR" branding text. (d) Username field typesA.CHARLWOODat 30ms/char in Geist Mono font. (e) Password field fills 8 dots at 20ms/dot. (f) Blinking cursor (530ms interval) in active field. (g) "Log In" button: NHS blue#005EB8, full width, pressed state darkens to#004494. (h) After submit: card scales to 103% and fades out over 200ms. (i) Respectprefers-reduced-motion. The login must feel like actually logging into NHS software at 8am on a Monday. -
Task 3: Rebuild PatientBanner component. Read
Ralph/refs/ref-banner-sidebar.mdandRalph/refs/ref-design-system.md. Rebuildsrc/components/PatientBanner.tsxto match the specification exactly: (a) Full banner 80px: background#334155, bottom border1px solid #475569. Name in Inter 600 20px (not 18px), details in Inter 400 14px. Layout must match the ASCII art in the ref file — surname-first format "CHARLWOOD, Andrew (Mr)", DOB/NHS No/Address on second row, phone/email/buttons on third row. (b) Status: green dot + "Active" text. Badge: "Open to opportunities" as blue pill. (c) Action buttons: outlined rectangles with NHS blue text and 1px border, 4px radius. Hover fills with NHS blue bg + white text. (d) Condensed banner 48px: single line with name, NHS number, status, action buttons only. Triggers at 100px scroll via IntersectionObserver. Smooth 200ms height transition. (e) Mobile banner: minimal top barCHARLWOOD, A (Mr) | 2211810 | dotwith overflow "..." menu. NHS Number tooltip: "GPhC Registration Number". -
Task 4: Rebuild ClinicalSidebar component. Read
Ralph/refs/ref-banner-sidebar.mdandRalph/refs/ref-design-system.md. Rebuildsrc/components/ClinicalSidebar.tsxto match the specification exactly: (a) 220px fixed width,#1E293Bbackground,1px solid #334155right border. (b) Header: "CareerRecord PMR / v1.0.0" in Inter 500, 13px, white at 50% opacity. (c) Search input: "Search record..." placeholder, integrated in sidebar below header. (d) Navigation labels use CV-friendly terms: Summary, Experience, Skills, Achievements, Projects, Education, Contact (NOT clinical jargon like Consultations, Medications, etc.). Same Lucide icons as before. Items: 44px height, 16px left padding, icons 18px + labels Inter 500 14px. Exact states: default white/70%, hover white/100% +rgba(255,255,255,0.08)bg, active white/100% + 3px NHS blue left border +rgba(255,255,255,0.12)bg + Inter 600 bold. (e) Separator line between Summary and Experience. (f) Footer: "Session: A.CHARLWOOD / Logged in: [time]" in Inter 400, 11px,#64748B. Time updates on mount. (g) Tablet mode: 56px icon-only with tooltips. (h) URL hash routing (#summary,#experience,#skills,#achievements,#projects,#education,#contact). (i) Alt+1-7 keyboard shortcuts, arrow key navigation, "/" for search focus. (j) Update the ViewId type insrc/types/pmr.tsif needed to match the new labels. -
Task 5: Rebuild PMRInterface layout and add Breadcrumb. Read
Ralph/refs/ref-banner-sidebar.mdandRalph/refs/ref-design-system.md. Rebuildsrc/components/PMRInterface.tsxto ensure correct layout composition: (a) Fixed sidebar (220px) + sticky patient banner + scrollable main content area with#F5F7FAbackground. (b) Main content padding: 24px. No max-width — content fills available space. (c) Createsrc/components/Breadcrumb.tsx: displays "Patient Record > [Current View]" at the top of the main content area (using CV-friendly view names: Experience, Skills, Achievements, etc.). When a consultation/skill/achievement is expanded, the breadcrumb deepens to show the item name. Styled in Inter 400, 13px, gray-400, with chevron separators. Clickable links navigate back. (d) Interface materialization animations: patient banner slides down (200ms ease-out), sidebar slides from left (250ms ease-out, 50ms delay), content fades in (300ms, 100ms delay after sidebar). (e) View switching must be INSTANT — no crossfade or slide between views. (f) Ensure mobile layout uses bottom nav bar (56px height with safe area padding). (g) Update the view switching logic to use the new CV-friendly ViewId values (summary, experience, skills, achievements, projects, education, contact). -
Task 6: Rebuild SummaryView with Clinical Alert. Read
Ralph/refs/ref-summary-alert.mdandRalph/refs/ref-design-system.md. Rebuildsrc/components/views/SummaryView.tsxand the clinical alert: (a) Clinical Alert: amber#FEF3C7background, 4px left border#F59E0B, text#92400E. Slides down with spring animation (not ease-out — use Framer Motiontype: "spring"with appropriate damping). Acknowledge button: amber outlined. On click: warning icon cross-fades to green checkmark (200ms), holds 200ms, then alert height collapses (200ms ease-out). (b) 2-column card grid on desktop, single column on mobile. Cards have: header bar with title in Inter 600, 14px, uppercase, on#F9FAFBbackground with1px solid #E5E7EBbottom border. Card body: 16px padding,1px solid #E5E7EBborder, 4px radius. (c) Demographics card: two-column key-value layout. Labels right-aligned Inter 500 13px gray-500, values left-aligned Inter 400 14px gray-900. (d) Active Problems card: traffic light dots + problem text + date in Geist Mono 12px. (e) Quick Meds card: 4-column table with top 5 skills. "View Full List ->" link. (f) Last Consultation card: preview with "View Full Record ->" link. All navigation links must actually switch the sidebar view. -
Task 7: Rebuild ConsultationsView. Read
Ralph/refs/ref-consultations.mdandRalph/refs/ref-design-system.md. Rebuildsrc/components/views/ConsultationsView.tsx: (a) Collapsed entries: date in Geist Mono 13px gray-500, organization in Inter 400 13px NHS blue, role in Inter 600 15px gray-900, "Key:" prefix in Inter 500 gray-500 with single-line achievement. Chevron button right-aligned. (b) Status dot: green for current, gray for historical. (c) 3px left border color-coded by employer (NHS blue#005EB8or Tesco teal#00897B). (d) Expanded state: Duration line, then HISTORY / EXAMINATION / PLAN sections with headers in Inter 600, 12px, uppercase, letter-spacing 0.05em, gray-400. Plan items as bullet lists. (e) CODED ENTRIES section at bottom: Geist Mono 12px, gray-500, bracket codes. (f) Height-only expand animation, 200ms ease-out. NO opacity fade on content — content simply grows/shrinks. (g) Only one expanded at a time. (h) Implement the second clinical alert (Python switching algorithm alert) that appears on first navigation to Consultations view, dismissible with same Acknowledge pattern. -
Task 8: Rebuild MedicationsView. Read
Ralph/refs/ref-medications.mdandRalph/refs/ref-design-system.md. Rebuildsrc/components/views/MedicationsView.tsx: (a) Three category tabs: "Active Medications" (technical), "Clinical Medications" (healthcare domain), "PRN (As Required)" (strategic/leadership). Tab styling: active tab has white bg + NHS blue bottom border. (b) Full table with proper<table>markup: Drug Name | Dose | Frequency | Start | Status. Table headers: Inter 600, 13px, uppercase,#F9FAFBbg. Row height: 40px. All borders:1px solid #E5E7EB. Alternating#FFFFFF/#F9FAFBrow backgrounds. (c) Hover:#EFF6FFbackground only — no transform, no lift. (d) Sortable columns: click header to sort, arrow indicator in active column. (e) Status dots: 6px green circles + "Active" text. (f) Expandable prescribing history: Geist Mono 12px, year markers bold, descriptions regular. (g) Mobile: card layout (stacked fields per card, not table). -
Task 9: Rebuild ProblemsView. Read
Ralph/refs/ref-problems.mdandRalph/refs/ref-design-system.md. Rebuildsrc/components/views/ProblemsView.tsx: (a) Two sections: "ACTIVE PROBLEMS" and "RESOLVED PROBLEMS" with section headers in clinical style. (b) Table columns — Active: Status | Code | Problem | Since. Resolved: Status | Code | Problem | Resolved | Outcome. (c) Traffic light dots: 8px circles (green=resolved, amber=in-progress). Always paired with text labels — never the sole indicator. (d) Code column in Geist Mono. (e) Expandable rows showing full narrative + linked consultation buttons that navigate to Consultations view. (f) Row hover:#EFF6FF. (g) Mobile: card layout. -
Task 10: Rebuild InvestigationsView and DocumentsView. Read
Ralph/refs/ref-investigations-documents.mdandRalph/refs/ref-design-system.md. Rebuild both views: (a) InvestigationsView: table with Test Name | Requested | Status | Result. Status badges: green "Complete", amber "Ongoing", pulsing green "Live". Expanded view uses tree-indented monospace structure with box-drawing characters (pipe symbols). "View Results" NHS blue button for PharMetrics only. (b) DocumentsView: table with Type icon | Document | Date | Source. Lucide icons per document type (FileText, Award, GraduationCap, FlaskConical). Expanded preview uses same tree-indented structure. (c) Both views share the expandable-row pattern — maintain visual consistency. (d) Mobile: card layouts for both. -
Task 11: Rebuild ReferralsView. Read
Ralph/refs/ref-referrals.mdandRalph/refs/ref-design-system.md. Rebuildsrc/components/views/ReferralsView.tsx: (a) Form header: "New Referral" with pre-filled patient info (non-editable). (b) Priority radio buttons: Urgent (red), Routine (blue, default), Two-Week Wait (amber). Each with tongue-in-cheek tooltips. (c) Form fields: standard clinical inputs with1px solid #D1D5DBborder, 4px radius,8px 12pxpadding. Labels in Inter 500, 13px, gray-600 above inputs. Focus: NHS blue border +box-shadow: 0 0 0 3px rgba(0,94,184,0.15). (d) Contact Method radio group. (e) Submit: "Send Referral" NHS blue button. Loading spinner state. Success state with reference number (REF-YYYY-MMDD-NNN format), checkmark, "24-48 hours" response time. (f) Direct Contact table below form: Email, Phone, LinkedIn, Location with action buttons. -
Task 12: Implement fuzzy search with fuse.js. Read
Ralph/refs/ref-interactions.md. Install fuse.js (npm install fuse.js). Rebuild the search functionality in the sidebar: (a) Build a search index on mount from ALL content: consultation titles/descriptions, medication names, problem descriptions, investigation names, document titles. (b) Search options:{ keys: ['title', 'description', 'name'], threshold: 0.3, includeScore: true }. (c) Results dropdown grouped by section (Consultations, Medications, Problems, etc.) with section icon, matching text, and relevance indicator. (d) Clicking a result navigates to the section AND expands/highlights the matching item. (e) Dropdown styled: white bg,1px solid #E5E7EB, 4px radius, shadow. Items in Inter 400 14px, 36px height. (f) Escape closes dropdown. (g) Mobile: search bar at top of each view instead of sidebar. -
Task 13: Implement context menus. Read
Ralph/refs/ref-interactions.md. Add right-click/long-press context menus: (a) On consultation entries: "Expand", "Copy to clipboard", "View coded entries". (b) On medication rows: "View prescribing history", "Copy to clipboard". (c) On problem entries: "View linked consultations", "Copy to clipboard". (d) Styled: white bg,1px solid #E5E7EBborder, 4px radius,box-shadow: 0 4px 12px rgba(0,0,0,0.1). Items: Inter 400, 14px, 36px row height. (e) Escape closes menu. Focus returns to trigger element on close. (f) Use Headless UI or a custom implementation — accessible with keyboard navigation. -
Task 14: Responsive design audit and fix. Read
Ralph/refs/ref-interactions.md. Systematically test and fix all three breakpoints: (a) Desktop (>1024px): full sidebar 220px, full patient banner 80px condensing to 48px, full tables. (b) Tablet (768-1024px): sidebar collapses to 56px icon-only with tooltips on hover/tap. Patient banner always condensed. Tables may horizontally scroll. Context menus via long-press. (c) Mobile (<768px): bottom nav bar with 7 icon buttons (56px height + safe area). Minimal top bar. ALL tables convert to card layout (stacked fields). Search bar at top of views. Back arrow to Summary. Touch targets minimum 48px. (d) Runnpm run buildand verify no layout breaks. -
Task 15: Accessibility audit and final polish. Read
Ralph/refs/ref-interactions.md. Audit and fix accessibility: (a) Semantic HTML: sidebar<nav>witharia-label, main<main>, banner<header>, tables withscope="col". (b) ARIA:aria-current="page"on active sidebar item,aria-expandedon expandable items,role="alert"on clinical alerts. (c) Focus management: after login focus to sidebar, after view switch focus to first heading, after expand focus to section heading, after alert dismiss focus to main content. (d) Keyboard: Tab order, roving tabindex in sidebar, Escape closes everything. (e) Screen reader: announce view changes, table headers, alert text. (f)prefers-reduced-motion: login instant, alert no slide, expand/collapse instant, banner condensation instant. (g) Color contrast: verify all text meets WCAG 2.1 AA. Traffic lights always have text labels. (h) Final visual polish pass: ensure consistent spacing, borders, fonts across all views.