Redesign CVMIS system
This commit is contained in:
@@ -4,12 +4,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## Project Overview
|
||||
|
||||
Interactive CV/portfolio for Andy Charlwood, presented as a premium clinical information system. The concept: *what if a GP surgery's patient record system were redesigned by a luxury product studio?* The structure and metaphor of a real clinical system (patient banner, sidebar navigation, record sections) — but elevated with refined typography, considered motion, and atmospheric depth.
|
||||
Interactive CV/portfolio for Andy Charlwood, presented as a GP clinical record system. The concept: *what if a GP surgery's patient record system were redesigned by a luxury product studio?* The structure and metaphor of a real clinical system (tiles as record sections, status indicators, medication-style skill entries, alerts) — but elevated with refined typography, considered motion, and a modern light aesthetic.
|
||||
|
||||
**This is NOT a faithful NHS system clone.** It's a showcase portfolio that *evokes* the feel of clinical software while being distinctly beautiful. The clinical metaphor is the creative conceit; the execution should feel premium and elegant.
|
||||
**This is NOT a faithful NHS system clone.** It's a showcase portfolio that *evokes* the feel of clinical software while being distinctly beautiful. The clinical metaphor is the creative conceit; the execution should feel premium and contemporary.
|
||||
|
||||
Built as a React SPA with TypeScript and Vite.
|
||||
|
||||
**Reference design:** `References/GPSystemconcept.html` — the visual and structural target for the dashboard.
|
||||
|
||||
## Commands
|
||||
|
||||
- `npm run dev` — Start dev server (localhost:5173)
|
||||
@@ -24,22 +26,54 @@ No test framework is configured.
|
||||
|
||||
### Four-Phase UI Flow
|
||||
|
||||
`App.tsx` manages a `Phase` state (`'boot'` → `'ecg'` → `'login'` → `'pmr'`). Each phase renders exclusively:
|
||||
`App.tsx` manages a `Phase` state (`'boot'` → `'ecg'` → `'login'` → `'dashboard'`). Each phase renders exclusively:
|
||||
|
||||
1. **BootSequence** — Terminal typing animation (~4s), green-on-black aesthetic. Fira Code font, matrix-green palette. **Locked — do not change.**
|
||||
2. **ECGAnimation** — Canvas-based heartbeat animation with mask-based letter tracing. Background transitions from black to `#1E293B`. **Locked — do not change.**
|
||||
3. **LoginScreen** — Animated login card on dark background. Types credentials at a natural pace, then presents an interactive "Log In" button for the user to click. This phase onward is open to design evolution.
|
||||
4. **PMRInterface** — The main portfolio experience: patient banner + clinical sidebar + scrollable content views.
|
||||
3. **LoginScreen** — Animated login card on dark background. Types credentials at a natural pace, then presents an interactive "Log In" button for the user to click. Login transitions to the dashboard.
|
||||
4. **DashboardLayout** — The main portfolio experience: TopBar + Sidebar + scrollable tile-based dashboard.
|
||||
|
||||
### Dashboard Layout (Post-Login)
|
||||
|
||||
The dashboard uses a three-zone layout:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ TopBar (fixed, 48px) — brand, search, session │
|
||||
├──────────┬──────────────────────────────────────────┤
|
||||
│ │ │
|
||||
│ Sidebar │ Card Grid (scrollable) │
|
||||
│ (272px) │ ┌─────────────────────────────────┐ │
|
||||
│ │ │ Patient Summary (full width) │ │
|
||||
│ Person │ ├────────────────┬────────────────┤ │
|
||||
│ Header │ │ Latest Results │ Repeat Meds │ │
|
||||
│ │ │ (KPIs) │ (Core Skills) │ │
|
||||
│ Tags │ ├────────────────┴────────────────┤ │
|
||||
│ │ │ Last Consultation (full width) │ │
|
||||
│ Alerts │ ├─────────────────────────────────┤ │
|
||||
│ │ │ Career Activity (full width) │ │
|
||||
│ │ ├─────────────────────────────────┤ │
|
||||
│ │ │ Education (full width) │ │
|
||||
│ │ ├─────────────────────────────────┤ │
|
||||
│ │ │ Projects (full width) │ │
|
||||
│ │ └─────────────────────────────────┘ │
|
||||
└──────────┴──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**No view switching.** The dashboard is a single scrollable page of tiles. Users scroll to see all sections. Detail drill-down happens by expanding tiles in-place (accordion pattern).
|
||||
|
||||
### Key Patterns
|
||||
|
||||
- **Canvas ECG**: `ECGAnimation.tsx` does imperative canvas drawing with requestAnimationFrame — flatline → 3 heartbeats (40px→60px→100px) → mask-based letter tracing → exit.
|
||||
- **Clinical sidebar navigation**: `ClinicalSidebar.tsx` provides hash-routed view switching with keyboard shortcuts (Alt+1-7, arrow keys, "/" for search).
|
||||
- **Patient banner condensation**: `PatientBanner.tsx` uses IntersectionObserver via `useScrollCondensation` hook — full banner (80px) condenses to 48px on scroll.
|
||||
- **Staggered entrance animations**: Framer Motion variants with sequenced delays (banner → sidebar → content).
|
||||
- **View switching**: Instant — no crossfade or slide between views. Content fades in once on initial load only.
|
||||
- **Expandable rows**: Consultation entries, medication rows, and problem entries expand in-place with height animation.
|
||||
- **Responsive breakpoints**: Desktop (full sidebar + banner), Tablet (icon-only sidebar), Mobile (bottom nav bar).
|
||||
- **Canvas ECG**: `ECGAnimation.tsx` does imperative canvas drawing with requestAnimationFrame — flatline → 3 heartbeats (40px→60px→100px) → mask-based letter tracing → exit. **Locked — do not change.**
|
||||
- **TopBar**: `TopBar.tsx` — fixed at top, brand + search trigger + session info. Search bar triggers Command Palette on click/Ctrl+K.
|
||||
- **Sidebar**: `Sidebar.tsx` — light background, contains PersonHeader (avatar, name, title, status, details), Tags, and Alerts only. Skills, Projects, Education are in the main content tiles.
|
||||
- **Card Grid**: CSS Grid, 2 columns on desktop (gap 16px), 1 column on mobile. Tiles use a reusable `Card` component with consistent styling.
|
||||
- **Tile Expansion**: Career Activity items, Project items, and Skill items expand in-place with height-only animation (200ms, ease-out). Single-expand accordion — only one item open at a time.
|
||||
- **KPI Flip Cards**: Latest Results metrics flip on click to show explanation text. CSS perspective transform, 400ms.
|
||||
- **Command Palette**: Ctrl+K opens a Spotlight-style search overlay. Fuzzy search via fuse.js. Keyboard navigation (arrow keys, Enter, Escape).
|
||||
- **Staggered entrance**: TopBar slides down → Sidebar slides from left → Content fades in. Quick (200-300ms).
|
||||
- **Expandable content**: Height-only animation, 200ms ease-out. Content grows/shrinks — no opacity fade.
|
||||
- **Responsive breakpoints**: Desktop (full sidebar + 2-col grid), Tablet (collapsed/hidden sidebar + 1-col), Mobile (no sidebar, stacked tiles).
|
||||
|
||||
### Path Aliases
|
||||
|
||||
@@ -49,14 +83,14 @@ No test framework is configured.
|
||||
|
||||
All data types live in `src/types/index.ts` and `src/types/pmr.ts`. Strict TypeScript — no `any` types. One component per file with typed props interfaces.
|
||||
|
||||
## Design Direction: Clinical Luxury
|
||||
## Design Direction: GP System Dashboard
|
||||
|
||||
The aesthetic direction is **"Clinical Luxury"** — the precision and information density of a medical records system, married to the refinement of high-end product design. Think Bloomberg Terminal redesigned by a Swiss design house.
|
||||
The aesthetic direction is a **modern GP system dashboard** — the precision and information density of a medical records system, but with a light, contemporary, premium feel. Think: a healthcare SaaS product redesigned by a Swiss product studio.
|
||||
|
||||
### Tone
|
||||
|
||||
- **Precise, not cold.** Every element has a reason. Spacing is generous but intentional.
|
||||
- **Structured, not rigid.** The grid and hierarchy of clinical software, but with room to breathe.
|
||||
- **Light, not washed out.** Warm sage background, clean white surfaces, deliberate color accents.
|
||||
- **Technical, not sterile.** Monospace data, status indicators, and coded entries create authentic texture.
|
||||
- **Elegant, not decorative.** No gratuitous ornament. Beauty comes from proportion, contrast, and type.
|
||||
|
||||
@@ -64,100 +98,121 @@ The aesthetic direction is **"Clinical Luxury"** — the precision and informati
|
||||
|
||||
Typography is the primary vehicle for premium feel. Avoid generic system fonts.
|
||||
|
||||
- **UI / Body — two candidates to evaluate (build with both, then choose):**
|
||||
- **Elvaro Grotesque** (by TabojaStudio) — Modern grotesque sans-serif. 7 weights: Light (300), Regular (400), Medium (500), SemiBold (600), Bold (700), ExtraBold (800), Black (900). Also available as variable font. The "grotesque" classification carries institutional credibility (Helvetica/Akzidenz-Grotesk lineage) while feeling distinctly premium. Slightly condensed proportions suit data-dense UI.
|
||||
- **Blumir** (by VisualCreativeStd) — Geometric-humanist hybrid, "blends geometric precision." 7 weights: Thin (100), ExtraLight (200), Light (300), Regular (400), Medium (500), SemiBold (600), Bold (700) — plus oblique variants for each. Also available as variable font. More refined/luxurious feel than Elvaro.
|
||||
- Both fonts are sourced from Envato (licensed), stored locally in `Fonts/`. Web font files (WOFF/WOFF2) are available for both. **Do not use Inter, Roboto, or system defaults** — these read as generic.
|
||||
- Font files for web:
|
||||
- Elvaro: `Fonts/Elvaro Grotesque Sans Family/WOFF/TBJElvaro-*.woff2`
|
||||
- Blumir: `Fonts/blumir-font-family/WOFF/Blumir-VF.woff2` (variable font)
|
||||
- **Monospace / Data**: Geist Mono for timestamps, coded entries, registration numbers, and tabular data. This creates the "technical texture" that sells the clinical metaphor.
|
||||
- **UI / Body:**
|
||||
- **Elvaro Grotesque** (primary, `font-ui`) — Modern grotesque sans-serif. 7 weights (300-900). Institutional credibility with premium feel. Slightly condensed proportions suit data-dense UI.
|
||||
- **Blumir** (alternative, `font-ui-alt`) — Geometric-humanist hybrid. Variable font (100-700). More refined/luxurious feel.
|
||||
- Both fonts sourced from Envato (licensed), stored in `Fonts/`. **Do not use Inter, Roboto, DM Sans, or system defaults.**
|
||||
- Font files: Elvaro `Fonts/Elvaro Grotesque Sans Family/WOFF/TBJElvaro-*.woff2`, Blumir `Fonts/blumir-font-family/WOFF/Blumir-VF.woff2`
|
||||
- **Monospace / Data**: Geist Mono for timestamps, session info, GPhC number, dates, coded entries. Creates "technical texture."
|
||||
- **Terminal phase**: Fira Code — locked, do not change.
|
||||
- **Type scale**: Keep it tight. Clinical systems use small text. Headings 15-18px, body 13-14px, labels 11-12px. Precision over drama.
|
||||
- **Weight hierarchy**: Use weight (400/500/600/700) rather than size to establish hierarchy. Bold section headers, medium labels, regular body.
|
||||
- **Type scale**: Tight. Headings 15-18px, body 12.5-14px, labels 10-12px. Precision over drama.
|
||||
- **Weight hierarchy**: Use weight (400/500/600/700) rather than size to establish hierarchy.
|
||||
|
||||
### Color Palette
|
||||
|
||||
The palette anchors on NHS Blue as the institutional accent, with a predominantly dark sidebar + light content split that creates natural drama.
|
||||
The palette anchors on teal as the primary accent, with a light sidebar + warm content background.
|
||||
|
||||
- **NHS Blue `#005EB8`** — The single strong accent color. Used for active states, links, buttons, interactive elements. This IS the brand color of the clinical metaphor.
|
||||
- **Dark sidebar `#1E293B`** — Creates gravitas. The "serious software" feel comes from this dark chrome.
|
||||
- **Patient banner `#334155`** — Slightly lighter than sidebar. The information-dense header bar.
|
||||
- **Content background** — Not flat gray. Consider a very subtle warm tint, or a faint noise/grain texture overlay on `#F5F7FA` to add depth. The content area should feel like paper, not a spreadsheet.
|
||||
- **Cards `#FFFFFF`** — Clean white with refined shadows (layered, not single-value). Cards should feel like they float slightly above the content surface.
|
||||
- **Status colors**: Green `#22C55E`, Amber `#F59E0B`, Red `#EF4444` — used sparingly for traffic-light indicators. Always paired with text labels, never as sole signifier.
|
||||
- **Text**: Primary `#111827`, Secondary `#6B7280`, Muted `#94A3B8`. Use the full range for hierarchy.
|
||||
- **Teal `#0D6E6E`** — Primary accent. Active states, links, avatar gradient, interactive elements. Hover: `#0A8080`. Light: `rgba(10,128,128,0.08)`.
|
||||
- **Background `#F0F5F4`** — Warm sage. The content area feels organic, not flat gray.
|
||||
- **Sidebar `#F7FAFA`** — Very light. Right border `#D4E0DE` separates from content.
|
||||
- **TopBar `#FFFFFF`** — White surface. Bottom border `#D4E0DE`.
|
||||
- **Cards `#FFFFFF`** — White with shadow-sm and border-light. Hover deepens to shadow-md.
|
||||
- **Status colors**: Success `#059669`, Amber `#D97706`, Alert `#DC2626`, Purple `#7C3AED` — each with light bg and border variants. Always paired with text labels.
|
||||
- **Text**: Primary `#1A2B2A`, Secondary `#5B7A78`, Tertiary `#8DA8A5`. Use full range for hierarchy.
|
||||
- **Borders**: Structural `#D4E0DE`, Cards/inner `#E4EDEB`.
|
||||
|
||||
### Shadows & Depth
|
||||
|
||||
Real clinical software is flat and border-heavy. This project should use shadows to create subtle layered depth:
|
||||
Three-tier shadow system for layered depth:
|
||||
|
||||
- **Cards**: Multi-layered shadow — e.g., `0 1px 2px rgba(0,0,0,0.04), 0 4px 12px rgba(0,0,0,0.03)`. Gentle, not Material Design dramatic.
|
||||
- **Sidebar**: Optional very subtle inner shadow or glow at the right edge where it meets content.
|
||||
- **Patient banner**: Subtle drop shadow below to separate from content.
|
||||
- **Hover states**: Cards may lift very slightly on hover (1-2px translate + shadow deepen). Keep it restrained.
|
||||
- **Cards (resting)**: `0 1px 2px rgba(26,43,42,0.05)` — gentle, always present.
|
||||
- **Cards (hover/interactive)**: `0 2px 8px rgba(26,43,42,0.08)` — slightly lifted.
|
||||
- **Overlays (command palette, modals)**: `0 8px 32px rgba(26,43,42,0.12)` — clearly elevated.
|
||||
- **Hover states**: Shadow deepens + border color strengthens. Subtle, not dramatic.
|
||||
|
||||
### Motion
|
||||
|
||||
Motion should feel considered and premium, never flashy:
|
||||
|
||||
- **Entrance animations**: The PMR interface materializes in sequence — banner slides down → sidebar slides from left → content fades in. Quick (200-300ms) with easing.
|
||||
- **Entrance animations**: Dashboard materializes in sequence — TopBar slides down → Sidebar slides from left → Content fades in. Quick (200-300ms) with easing.
|
||||
- **Login typing**: 80ms/char for username, 60ms/dot for password. Natural, readable pace. After typing completes, "Log In" button becomes interactive — user clicks to proceed.
|
||||
- **Login transition**: On button click, card scales slightly and fades. Background carries over to PMR (both are `#1E293B`-derived).
|
||||
- **View switching**: Instant, no transition between views. This preserves the "software application" feel.
|
||||
- **Expandable content**: Height-only animation, 200ms ease-out. Content grows/shrinks — no opacity fade.
|
||||
- **Hover states**: Subtle, immediate. Background color shifts, not transforms. Think: OS-level responsiveness.
|
||||
- **Clinical alert**: Spring animation for entrance (Framer Motion `type: "spring"`). Dismiss: icon crossfade → height collapse.
|
||||
- **Login transition**: On button click, card scales slightly and fades. Transition to dashboard layout.
|
||||
- **Tile expansion**: Height-only animation, 200ms ease-out. Content grows/shrinks — no opacity fade.
|
||||
- **KPI flip**: CSS perspective rotateY, 400ms ease-in-out. Click to flip, click to flip back.
|
||||
- **Command palette**: Scale 0.97→1.0 + translateY entrance, 200ms. Backdrop fade.
|
||||
- **Hover states**: Subtle, immediate. Border color shifts, shadow deepens. Think: OS-level responsiveness.
|
||||
- **`prefers-reduced-motion`**: All animations skip to final state. No exceptions.
|
||||
|
||||
### Spatial Composition
|
||||
|
||||
- **Generous but structured.** More whitespace than a real clinical system. Cards have 16-24px padding. Sections breathe.
|
||||
- **Clear visual hierarchy.** Section headers (uppercase, small, tracked-out) → content. No ambiguity about what's a label vs. data.
|
||||
- **Two-column summary grid** on desktop, single column on mobile. Cards span full width or half width — no orphan columns.
|
||||
- **Tables** use proper `<table>` markup with styled headers on a light gray background. Alternating row colors. This is where the clinical authenticity lives.
|
||||
- **Generous but structured.** Cards have 20px padding. Tile grid has 16px gap. Sections breathe.
|
||||
- **Clear visual hierarchy.** Card headers: uppercase, small (12px), tracked-out, secondary color with colored dot indicator.
|
||||
- **Two-column grid** on desktop, single column on mobile. Full-width tiles span both columns.
|
||||
- **Sidebar sections** separated by thin divider titles (10px, uppercase, tertiary, with line extending right).
|
||||
|
||||
### What Makes It Memorable
|
||||
|
||||
The distinctiveness comes from the *contrast between structure and polish*:
|
||||
- A dark, serious sidebar next to warm, airy content
|
||||
- Small, precise monospace data in a field of generous whitespace
|
||||
- NHS blue punching through an otherwise muted palette
|
||||
- The clinical metaphor itself — "Patient Record" for a CV is unexpected and charming
|
||||
The distinctiveness comes from the *clinical metaphor applied to a modern interface*:
|
||||
- A light, professional sidebar with clinical-style person header and alert flags
|
||||
- Skills presented as "Repeat Medications" with frequency dosing (twice daily, when required)
|
||||
- KPI metrics that flip to reveal explanations, like interactive test results
|
||||
- Career history as a clinical timeline with color-coded entry types
|
||||
- The boot sequence → ECG → login flow is theatrical in a way that real clinical software never is
|
||||
- Command palette (Ctrl+K) for searching records, like a clinical search tool
|
||||
|
||||
## Styling
|
||||
|
||||
Tailwind CSS with custom design tokens in `tailwind.config.js`:
|
||||
- **Color tokens**: All PMR-prefixed tokens in Tailwind config (`pmr-sidebar`, `pmr-banner`, `pmr-nhsblue`, etc.)
|
||||
- **Fonts**: Configured as `font-inter`, `font-geist` (monospace) in Tailwind — these need updating when the primary UI font changes.
|
||||
- **Color tokens**: PMR-prefixed tokens (`pmr-accent`, `pmr-bg`, `pmr-surface`, `pmr-sidebar`, `pmr-text-primary`, etc.)
|
||||
- **Fonts**: `font-ui` (Elvaro Grotesque), `font-ui-alt` (Blumir), `font-geist` (Geist Mono), `font-mono` (Fira Code for terminal)
|
||||
- **Breakpoints**: xs 480px, sm 640px, md 768px, lg 1024px, xl 1280px
|
||||
- **Border radius**: 4px default for cards/inputs (clinical precision). 12px exception for login card only.
|
||||
- **Border radius**: 8px default for cards/tiles (`var(--radius)`). 6px for inner elements (`var(--radius-sm)`). 12px exception for login card and command palette.
|
||||
- **Shadows**: `shadow-sm`, `shadow-md`, `shadow-lg` tokens matching three-tier system.
|
||||
- CSS custom properties in `index.css` for both boot/ECG phase tokens and dashboard phase tokens.
|
||||
- Inline styles only for dynamic values that Tailwind can't express.
|
||||
- CSS custom properties in `index.css` for both boot/ECG phase tokens and PMR phase tokens.
|
||||
|
||||
## Guardrails
|
||||
|
||||
- **Boot sequence**: Text, colors, and timing must match `References/concept.html` exactly. **Do not modify.**
|
||||
- **ECG animation**: Timing, amplitudes, color transitions, and mask-based text reveal must match the concept reference. **Do not modify.**
|
||||
- **Reference design**: `References/GPSystemconcept.html` is the visual and structural target for the dashboard.
|
||||
- **CV content**: Sourced from `References/CV_v4.md` — roles, dates, and achievement numbers must be accurate.
|
||||
- **Icons**: Via `lucide-react`, not unicode symbols.
|
||||
- **Accessibility**: WCAG 2.1 AA compliance. Semantic HTML, ARIA attributes, keyboard navigation, `prefers-reduced-motion` support throughout.
|
||||
- **Accessibility**: WCAG 2.1 AA compliance. Semantic HTML, ARIA attributes, keyboard navigation, `prefers-reduced-motion` support throughout. Status indicators always paired with text labels.
|
||||
- **No generic aesthetics**: Every design decision should feel intentional. If a component could appear in any random SaaS template, it needs more character.
|
||||
- **Fonts**: Elvaro Grotesque (primary) or Blumir (alt). Never Inter, Roboto, DM Sans, or system defaults. DM Sans appears in the concept HTML as a placeholder only.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── components/ # One component per file (PascalCase)
|
||||
│ └── views/ # PMR content views (SummaryView, ConsultationsView, etc.)
|
||||
│ ├── tiles/ # Dashboard tile components (PatientSummaryTile, LatestResultsTile, etc.)
|
||||
│ ├── views/ # Legacy PMR views (being replaced by tiles — may be referenced during transition)
|
||||
│ ├── TopBar.tsx # Fixed top bar (brand, search trigger, session)
|
||||
│ ├── Sidebar.tsx # Light sidebar (person header, tags, alerts)
|
||||
│ ├── DashboardLayout.tsx # Main layout (topbar + sidebar + card grid)
|
||||
│ ├── Card.tsx # Reusable card component with header
|
||||
│ ├── CommandPalette.tsx # Ctrl+K search overlay
|
||||
│ └── ... # Boot, ECG, Login (unchanged)
|
||||
├── contexts/ # React contexts (AccessibilityContext)
|
||||
├── data/ # Static data files (patient, consultations, medications, etc.)
|
||||
├── data/ # Static data files
|
||||
│ ├── patient.ts # Person details
|
||||
│ ├── consultations.ts # Career roles (used in Last Consultation + Career Activity)
|
||||
│ ├── medications.ts # Legacy skill data
|
||||
│ ├── problems.ts # Achievements
|
||||
│ ├── investigations.ts # Projects
|
||||
│ ├── documents.ts # Education entries
|
||||
│ ├── profile.ts # Personal statement
|
||||
│ ├── tags.ts # Sidebar tags
|
||||
│ ├── alerts.ts # Sidebar alert flags
|
||||
│ ├── kpis.ts # KPI metrics for Latest Results
|
||||
│ └── skills.ts # Skills with frequency/years (medication metaphor)
|
||||
├── hooks/ # Custom hooks (camelCase, use* prefix)
|
||||
├── lib/ # Utility functions
|
||||
├── lib/ # Utility functions (search.ts for fuse.js)
|
||||
├── types/ # TypeScript interfaces (index.ts, pmr.ts)
|
||||
├── App.tsx # Phase manager (root component)
|
||||
└── index.css # Global styles + Tailwind directives
|
||||
Ralph/ # Implementation plan, guardrails, progress tracking
|
||||
References/ # Source content (concept.html, CV_v4.md, ECGVideo/)
|
||||
References/ # Source content (concept.html, GPSystemconcept.html, CV_v4.md)
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user