Completed login screen transition, and started the spec work on design file info

This commit is contained in:
2026-02-11 22:15:29 +00:00
parent 1a1f1f1938
commit 192d629125
22 changed files with 2357 additions and 390 deletions
+145
View File
@@ -0,0 +1,145 @@
# Reference: Patient Banner + Sidebar + Navigation
> Extracted from goal.md — Patient Banner, Left Sidebar, and Navigation sections. These are the persistent UI chrome that defines the clinical system feel.
---
## Patient Banner (Persistent Top Chrome)
The patient banner is the most recognizable element of any PMR system. It spans the full viewport width above the main content area and provides constant demographic context.
### Full Banner (80px height, visible at top of page)
```
+---------------------------------------------------------------------------+
| CHARLWOOD, Andrew (Mr) Active (green dot) Open to opps. |
| DOB: 14/02/1993 | NHS No: 2211810 | Norwich, NR1 |
| 07795553088 | andy@charlwood.xyz [Download CV] [Email] [LinkedIn] |
+---------------------------------------------------------------------------+
```
### Content Mapping
| PMR Field | Actual Content | Notes |
|-----------|---------------|-------|
| Patient name | CHARLWOOD, Andrew (Mr) | Surname first, comma-separated — exactly as in clinical systems |
| DOB | 14/02/1993 | DD/MM/YYYY format (UK clinical standard) |
| NHS Number | 221 181 0 | Andy's GPhC registration number formatted like an NHS number (with spaces). Hover tooltip: "GPhC Registration Number" |
| GP Practice | Self-Referred | Tongue-in-cheek — Andy referred himself to this record |
| Address | Norwich, NR1 | Abbreviated postcode area |
| Phone | 07795553088 | Clickable (tel: link) |
| Email | andy@charlwood.xyz | Clickable (mailto: link) |
| Status | Active (green dot) | Like the "registered" status in a PMR |
| Badge | Open to opportunities | Styled as a clinical banner tag (blue background, white text, small pill shape) |
### Action Buttons (top right of banner)
| Button | PMR Equivalent | Action |
|--------|---------------|--------|
| Download CV | Print Summary | Downloads PDF version of CV |
| Email | Send Letter | Opens mailto: link |
| LinkedIn | External Link | Opens LinkedIn profile in new tab |
Buttons are styled as small outlined rectangles with NHS blue text and 1px NHS blue border, 4px radius. On hover: filled NHS blue background with white text.
### Condensed Banner (48px, sticky after scroll)
When the user scrolls past 100px of content, the banner smoothly condenses to show only the essential information on a single line:
```
CHARLWOOD, Andrew (Mr) | NHS No: 2211810 | Active (green dot) [Download CV] [Email]
```
The condensed banner sticks to the top of the viewport (`position: sticky`) with a `z-index` above the content area but below modals/alerts.
---
## Left Sidebar — Clinical Navigation
The sidebar replicates the dark navigation panel found in EMIS Web and similar clinical systems. It provides category-based access to different "record views."
**Width:** 220px (desktop), dark blue-gray (`#1E293B`) background.
### Navigation Items
**IMPORTANT:** Sidebar labels use CV-friendly terms, NOT clinical jargon. The clinical metaphor lives in the LAYOUT of each view, not the labels.
| Icon | Label | View Layout Style | Description |
|------|-------|-------------------|-------------|
| `ClipboardList` | Summary | Patient summary screen | Demographics, active items, current skills, recent role |
| `FileText` | Experience | Consultation journal layout | Reverse-chronological journal of roles with H/E/P format |
| `Pill` | Skills | Medications table layout | Skills table with proficiency dosages and frequency |
| `AlertTriangle` | Achievements | Problems list layout | Challenges resolved and ongoing, with traffic lights |
| `FlaskConical` | Projects | Investigation results layout | Project outcomes with status badges |
| `FolderOpen` | Education | Attached documents layout | Certificates and qualifications |
| `Send` | Contact | Referral form layout | Contact/message form styled as clinical referral |
### Styling
- Each item: 44px height, 16px left padding, icon (18px, `lucide-react`) + label in Inter 500, 14px
- Default state: white text at 70% opacity, transparent background
- Hover state: white text at 100% opacity, background `rgba(255,255,255,0.08)`
- Active state: white text at 100%, NHS blue left border (3px), background `rgba(255,255,255,0.12)`, label in Inter 600
- A thin horizontal separator line (`1px solid rgba(255,255,255,0.1)`) appears between "Summary" and "Consultations" (separating the overview from the detail views)
### Sidebar Footer
At the bottom of the sidebar, in small text (Inter 400, 11px, `#64748B`):
```
Session: A.CHARLWOOD
Logged in: [current time]
```
This updates with the actual current time on mount, reinforcing the "logged in" metaphor.
### Sidebar Header
At the top, above the navigation items, a small logo or system name:
```
CareerRecord PMR
v1.0.0
```
In Inter 500, 13px, white at 50% opacity. Styled like the "EMIS Web" branding that appears in the top-left of the real system.
---
## Navigation
### Primary Navigation: Left Sidebar
The sidebar is always visible on desktop — this is how clinical systems work. There is no floating nav, no hamburger menu on desktop, and no scroll-based navigation. The sidebar provides persistent, direct access to any record section.
### Keyboard Shortcuts
| Sidebar Item | View Layout | Shortcut |
|-------------|-------------|----------|
| Summary | Patient summary | `Alt+1` |
| Experience | Consultation journal | `Alt+2` |
| Skills | Medications table | `Alt+3` |
| Achievements | Problems list | `Alt+4` |
| Projects | Investigation results | `Alt+5` |
| Education | Attached documents | `Alt+6` |
| Contact | Referral form | `Alt+7` |
### URL Hash Routing
Each sidebar item updates the URL hash (`#summary`, `#experience`, `#skills`, `#achievements`, `#projects`, `#education`, `#contact`) for direct linking. On page load, the app reads the hash and navigates to the corresponding view.
### Breadcrumb
A breadcrumb appears at the top of the main content area:
```
Patient Record > Consultations > Interim Head, Population Health
```
The breadcrumb updates as the user navigates deeper (e.g., expanding a consultation). Clicking "Patient Record" returns to Summary. Clicking "Consultations" collapses any expanded entries and shows the full journal list. The breadcrumb is styled in Inter 400, 13px, gray-400, with chevron separators.
### Secondary Navigation: Within-View Interactions
- **Summary:** Clicking "View Full List" or "View Full Record" links navigates to the corresponding sidebar section.
- **Consultations:** Expand/collapse individual entries. "Linked consultations" in Problems view can deep-link to specific consultation entries.
- **Medications:** Category tabs (Active, Clinical, PRN) within the view. Click to expand prescribing history.
- **Problems:** Click to expand. "Linked consultations" navigate to Consultations view.
- **Investigations:** Click to expand results.
- **Documents:** Click to expand preview.
- **Referrals:** No sub-navigation.
+359
View File
@@ -0,0 +1,359 @@
# Reference: Boot Sequence + ECG Animation
> Covers the full pre-login flow: terminal boot → cursor transition → ECG heartbeat → name reveal → flatline. The flatline→login transition is covered in `ref-transition-login.md`.
---
## Current Architecture
Two components manage the pre-login flow:
- `src/components/BootSequence.tsx` → terminal text animation, ends with blinking cursor
- `src/components/ECGAnimation.tsx` → canvas-based heartbeat + name tracing + flatline + bg transition
- `App.tsx` phases: `boot → ecg → login → pmr`
## What Needs to Change
### 1. Boot Sequence — Clean Up for Easy Config
**Problem:** Boot text lines are hardcoded as HTML strings with inline Tailwind classes. Adding/removing/reordering lines requires editing raw HTML. The `dangerouslySetInnerHTML` approach is fragile.
**Fix:** Refactor to a clean config-driven structure:
```typescript
// Example config structure — easy to customize
const BOOT_CONFIG = {
header: { text: 'CLINICAL TERMINAL v3.2.1', style: 'bright' },
lines: [
{ type: 'status', text: 'Initialising pharmacist profile...' },
{ type: 'separator' },
{ type: 'field', label: 'SYSTEM', value: 'NHS Norfolk & Waveney ICB' },
{ type: 'field', label: 'USER', value: 'Andy Charlwood' },
{ type: 'field', label: 'ROLE', value: 'Deputy Head of Population Health & Data Analysis' },
{ type: 'field', label: 'LOCATION', value: 'Norwich, UK' },
{ type: 'separator' },
{ type: 'status', text: 'Loading modules...' },
{ type: 'module', name: 'pharmacist_core.sys' },
{ type: 'module', name: 'population_health.mod' },
{ type: 'module', name: 'data_analytics.eng' },
{ type: 'separator' },
{ type: 'ready', text: 'READY — Rendering CV..' },
],
timing: { lineDelay: 220, holdAfterComplete: 400, fadeOutDuration: 800 },
}
```
- Each line type maps to a React component (not raw HTML)
- Colors remain: bright green `#00ff41`, dim green `#3a6b45`, cyan labels `#00e5ff`
- Staggered reveal timing stays the same (220ms per line)
- Font: Fira Code (this is the terminal phase, NOT the PMR — Fira Code is correct here)
### 2. Cursor → Dot Transition
**Problem:** The boot sequence ends with a blinking green block cursor (`.animate-blink`). The ECG animation starts with a glowing dot that appears at the far left of the screen. There's a visual disconnect — the cursor and dot don't connect.
**Fix:** The blinking cursor at the end of boot should smoothly transition INTO the ECG's glowing trace dot:
- At end of boot, capture the cursor's screen position (x, y)
- Pass this position to ECGAnimation via props
- ECGAnimation starts with its glowing dot AT the cursor position
- The cursor stops blinking and morphs: block cursor → circular glow (scale down width, increase glow, ~300ms)
- The dot then begins moving rightward, drawing the flatline/heartbeat trace behind it
- This means the ECG trace starts at the cursor position, NOT the far left edge
### 3. ECG Start Position
**Problem:** Currently the ECG trace starts at x=0 (far left of viewport). The cursor ends somewhere in the middle-left of the screen. This means the dot "teleports" from cursor position to the left edge.
**Fix:** The ECG animation should:
- Accept a `startPosition: { x: number, y: number }` prop from the boot sequence
- Begin the trace from that position
- The first section of trace is a flat line from the cursor position rightward
- Heartbeats begin after the first flat gap (same timing as now, just offset)
- The viewport scroll logic already handles the "head" position — just shift the world-space origin
### 4. Text Reveal — Mask Technique
**Problem:** The current ECGAnimation.tsx reveals letters by stroking them with progressive alpha (`letterProgress > 0.3` → fade in). This looks like letters fading in, not like the ECG line IS the letter shape.
**Reference:** `ECGCombined.tsx` (Remotion version at project root) uses a superior technique:
- The actual text characters are pre-rendered on the canvas (stroke-only, no fill)
- A wipe mask follows the ECG trace head, revealing the text underneath
- The ECG trace line IS the path that forms each letter shape (via the `getYAtX` function which returns letter Y values when in text region)
- Connector lines between letters sit at the baseline
- The neon glow filter applies to both the trace and revealed text
**What to adopt from ECGCombined.tsx:**
- The mask-based text reveal approach (the trace unveils pre-rendered text)
- The connector lines between letters at baseline
- The neon glow SVG filters (or canvas equivalents)
- The text mask brush that follows the trace head
**What to KEEP from current ECGAnimation.tsx:**
- The character spacing (current `LETTER_W`, `LETTER_G`, `SPACE_W` values — preferred over ECGCombined.tsx spacing)
- The heartbeat waveform shape (`generateHeartbeatPoints`)
- The beat timing and amplitude escalation (0.3 → 0.55 → 0.85 → 1.0)
- The canvas rendering approach (not SVG — canvas is correct for this performance-sensitive animation)
- The viewport scrolling/camera logic
- The flatline draw phase
- The scanline and vignette effects
- The background color transition to `#1E293B`
### 5. Text Rendering
- The name is still "ANDREW CHARLWOOD"
- Letters are stroke-only (no fill) in neon green `#00ff41`
- Each letter shape is defined by the `ECG_LETTERS` point arrays (keep these)
- The trace line passes through each letter's shape points, making the ECG waveform form recognizable letter shapes
- Between letters, the trace returns to baseline with short connector segments
- Neon glow effect on both trace and revealed text
## Transition to Login
After the text is fully revealed and the flatline extends to the right edge, the flow continues as described in `ref-transition-login.md`:
1. Name holds with glow (300ms)
2. Glow fades, flatline extends right
3. Canvas fades to black (200ms)
4. Background transitions to dark blue-gray `#1E293B` (200ms)
5. Login card materializes
## prefers-reduced-motion
With reduced motion enabled:
- Boot text appears instantly (no stagger)
- Cursor appears immediately
- ECG animation is skipped entirely — transition straight from boot to login
- Or: show the final frame (name fully revealed, flatline) as a static image for 1 second, then proceed to login
## Testing Checklist
- [ ] Boot text renders correctly with all lines
- [ ] Blinking cursor visible at end of boot
- [ ] Cursor smoothly transitions to ECG dot (no teleport)
- [ ] ECG trace starts from cursor position
- [ ] Heartbeats render with increasing amplitude
- [ ] Name letters revealed via mask technique (not alpha fade)
- [ ] Connector lines between letters
- [ ] Neon glow on trace and text
- [ ] Flatline extends to right edge after name
- [ ] Background transitions to `#1E293B`
- [ ] Scanlines and vignette present
- [ ] Reduced motion: instant/static
- [ ] Mobile: scales correctly
---
## Design Guidance (from /frontend-design)
> Pre-baked design direction. Do NOT invoke `/frontend-design` at runtime — this section contains the output.
### Aesthetic Direction: Authentic Clinical Terminal → Medical Monitor Realism
This isn't "medical-themed" design — this IS medical equipment interfaces. Two distinct phases:
1. **Boot Terminal**: Authentic 1990s clinical system boot sequence (think legacy pharmacy dispensing systems, hospital terminal logins). CRT monitor aesthetic with phosphor green, scanlines, slight text glow.
2. **ECG Monitor**: Hospital bedside cardiac monitor realism. The heartbeat isn't decorative — it's a functioning waveform that becomes letterforms through technical precision.
**Visual Signature**: The cursor-to-dot morphing transition. Most animations have discrete phases; this creates continuous material transformation — the blinking terminal cursor literally becomes the ECG trace point. It's the moment where "loading system" becomes "reading vital signs."
### Boot Sequence — Type-Safe Config
```typescript
type BootLineType = 'header' | 'status' | 'separator' | 'field' | 'module' | 'ready'
interface BootLine {
type: BootLineType
text: string
label?: string
value?: string
style?: 'bright' | 'dim' | 'cyan'
}
interface BootConfig {
header: string
lines: BootLine[]
timing: {
lineDelay: number
cursorBlinkInterval: number
holdAfterComplete: number
fadeOutDuration: number
}
colors: {
bright: string
dim: string
cyan: string
}
}
```
Component architecture:
- `<BootLine>` — renders individual line types with appropriate styling
- `<BootCursor>` — separate component for cursor with ref exposure for position capture
- Config-driven rendering replaces hardcoded HTML
Example config:
```typescript
const BOOT_CONFIG: BootConfig = {
header: 'CLINICAL TERMINAL v3.2.1',
lines: [
{ type: 'status', text: 'Initialising pharmacist profile...', style: 'dim' },
{ type: 'separator', text: '---', style: 'dim' },
{ type: 'field', label: 'SYSTEM', value: 'NHS Norfolk & Waveney ICB', style: 'cyan' },
{ type: 'field', label: 'USER', value: 'Andy Charlwood', style: 'bright' },
// ... etc
],
timing: { lineDelay: 220, cursorBlinkInterval: 530, holdAfterComplete: 400, fadeOutDuration: 800 },
colors: { bright: '#00ff41', dim: '#3a6b45', cyan: '#00e5ff' }
}
```
Example BootLine component:
```typescript
function BootLine({ line }: { line: BootLine }) {
const colors = BOOT_CONFIG.colors
const color = line.style ? colors[line.style] : colors.dim
if (line.type === 'field') {
return (
<div className="font-mono text-sm leading-relaxed">
<span style={{ color: colors.cyan }}>{line.label?.padEnd(9)}</span>
<span style={{ color }}>{line.value}</span>
</div>
)
}
if (line.type === 'module') {
return (
<div className="font-mono text-sm leading-relaxed">
<span className="font-bold" style={{ color: colors.bright }}>[OK]</span>
{' '}
<span style={{ color: colors.dim }}>{line.text}</span>
</div>
)
}
// ... other types
}
```
### Cursor → Dot Transition — Implementation
```typescript
const [cursorPosition, setCursorPosition] = useState<{x: number, y: number} | null>(null)
const cursorRef = useRef<HTMLDivElement>(null)
useEffect(() => {
if (cursorRef.current) {
const rect = cursorRef.current.getBoundingClientRect()
setCursorPosition({
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
})
}
}, [/* trigger when boot completes */])
// Pass to ECG:
<ECGAnimation startPosition={cursorPosition} onComplete={...} />
```
Morph animation: width 8px→0px, height 16px→6px, border-radius 0→50% (300ms ease-out). Simultaneously fade in ECG dot at same position. After morph complete, begin trace movement.
### Canvas Mask Reveal — Implementation
```javascript
// Pre-render text to offscreen canvas
const textCanvas = document.createElement('canvas')
const textCtx = textCanvas.getContext('2d')
textCtx.strokeStyle = lineColor
textCtx.lineWidth = 1.5
textCtx.font = `bold ${fontSize}px Arial`
textLayout.forEach(item => {
textCtx.strokeText(item.char, item.centerX, baselineY)
})
// During animation loop:
ctx.save()
// Create clipping path following trace head
ctx.beginPath()
ctx.rect(0, 0, headSX + 20, vh) // reveal up to head position + lead
ctx.clip()
// Draw pre-rendered text through clip
ctx.drawImage(textCanvas, -viewOff, 0)
ctx.restore()
// Feathered leading edge:
const gradient = ctx.createLinearGradient(headSX - 30, 0, headSX, 0)
gradient.addColorStop(0, 'rgba(0,255,65,0)')
gradient.addColorStop(1, 'rgba(0,255,65,1)')
```
### Connector Lines Between Letters
```javascript
const connectors: {startX: number, endX: number}[] = []
for (let i = 0; i < textLayout.length - 1; i++) {
const curr = textLayout[i]
const next = textLayout[i + 1]
const endInset = CONNECTOR_INSETS[curr.char] || 0
const startInset = CONNECTOR_INSETS[next.char] || 0
connectors.push({
startX: curr.endX - endInset,
endX: next.startX + startInset
})
}
// During draw:
connectors.forEach(conn => {
if (headWX > conn.startX) {
const connectorEndX = Math.min(conn.endX, headWX)
ctx.beginPath()
ctx.moveTo(conn.startX - viewOff, baselineY)
ctx.lineTo(connectorEndX - viewOff, baselineY)
ctx.stroke()
}
})
```
### Visual Enhancement Details
**CRT Scanlines** (boot phase):
```css
.boot-scanlines {
position: absolute;
inset: 0;
background: repeating-linear-gradient(
0deg,
rgba(0, 0, 0, 0.15) 0px,
transparent 1px,
transparent 2px,
rgba(0, 0, 0, 0.15) 3px
);
pointer-events: none;
animation: scanline-drift 8s linear infinite;
}
```
**Phosphor Glow** (terminal text):
```css
.terminal-text {
text-shadow:
0 0 4px currentColor,
0 0 8px currentColor,
0 0 12px rgba(0, 255, 65, 0.3);
}
```
**ECG Neon Glow** (canvas — multi-layer):
- Primary trace: 2px solid line
- Glow layer 1: 6px @ 25% opacity + shadowBlur 14px
- Glow layer 2: Inner 3px core for sharpness
- Text: Same multi-layer glow approach
**Background Transition** (smooth RGB interpolation):
```javascript
const bgProgress = (elapsed - flatlineStartTime) / BG_TRANSITION
ctx.fillStyle = `rgb(
${Math.round(0 + (30 * bgProgress))},
${Math.round(0 + (41 * bgProgress))},
${Math.round(0 + (59 * bgProgress))}
)` // black → #1E293B
ctx.fillRect(0, 0, vw, vh)
```
+109
View File
@@ -0,0 +1,109 @@
# Reference: Consultations View (= Experience)
> Extracted from goal.md — Consultations View section. Each role is a "consultation entry" in a reverse-chronological journal.
---
## Overview
This is the core content view and the most detailed section. Each role is a "consultation entry" in a reverse-chronological journal.
## Journal List Layout
Entries are stacked vertically, most recent at top. Each entry has a collapsed state and an expanded state.
### Collapsed Entry
```
+------------------------------------------------------------------+
| (green dot) 14 May 2025 | NHS Norfolk & Waveney ICB |
| Interim Head, Population Health & Data Analysis |
| Key: 14.6M efficiency programme identified and delivered |
| [v Expand] |
+------------------------------------------------------------------+
```
- Date in Geist Mono, 13px, gray-500 (left-aligned)
- Organization in Inter 400, 13px, NHS blue
- Role title in Inter 600, 15px, gray-900
- Key coded entry: a single-line summary of the most notable achievement, prefixed with "Key:" in Inter 500, gray-500
- Expand chevron button (right-aligned)
- Status dot: green for current roles, gray for historical
### Expanded Entry (click to expand)
```
+------------------------------------------------------------------+
| (green dot) 14 May 2025 | NHS Norfolk & Waveney ICB [^ Close] |
| Interim Head, Population Health & Data Analysis |
| Duration: May 2025 - Nov 2025 |
| |
| HISTORY |
| Returned to substantive Deputy Head role following |
| commencement of ICB-wide organisational consultation. |
| Led strategic delivery of population health initiatives |
| and data-driven medicines optimisation across Norfolk & |
| Waveney ICS, reporting to Associate Director of Pharmacy. |
| |
| EXAMINATION |
| - Identified 14.6M efficiency programme through |
| comprehensive data analysis |
| - Built Python-based switching algorithm: 14,000 patients |
| identified, 2.6M annual savings |
| - Automated incentive scheme analysis: 50% reduction |
| in targeted prescribing within 2 months |
| |
| PLAN |
| - Achieved over-target performance by October 2025 |
| - 2M on target for delivery this financial year |
| - Presented to CMO bimonthly with evidence-based |
| recommendations |
| - Led transformation to patient-level SQL analytics |
| |
| CODED ENTRIES |
| [EFF001] Efficiency programme: 14.6M identified |
| [ALG001] Algorithm: 14,000 patients, 2.6M savings |
| [AUT001] Automation: 50% prescribing reduction in 2mo |
| [SQL001] Data transformation: practice->patient level |
+------------------------------------------------------------------+
```
## The History / Examination / Plan Structure
This is a direct mapping from the clinical consultation format (SOAP notes) to career content:
| Clinical Term | CV Mapping | What Goes Here |
|--------------|------------|----------------|
| **History** | Context / Background | Why this role existed, what situation Andy walked into, reporting lines |
| **Examination** | Analysis / Findings | What Andy discovered, built, or analyzed — the technical and analytical work |
| **Plan** | Outcomes / Delivery | What was achieved, what impact was measured, what's ongoing |
Section headers ("HISTORY", "EXAMINATION", "PLAN") are styled in Inter 600, 12px, uppercase, letter-spacing 0.05em, gray-400 — exactly like the section dividers in a clinical consultation record.
## Coded Entries
At the bottom of each expanded consultation, "coded entries" appear — short-form tagged achievements with bracket codes. These mimic SNOMED CT / Read codes used in clinical systems. The codes are fictional but consistent (EFF = efficiency, ALG = algorithm, AUT = automation, SQL = data, etc.). Styled in Geist Mono, 12px, gray-500, with the code in brackets and the description after.
## Color Coding by Employer
Each consultation entry has a subtle left border (3px) indicating the employer:
- NHS Norfolk & Waveney ICB: NHS blue (`#005EB8`)
- Tesco PLC: Teal (`#00897B`)
This visual grouping helps the user quickly scan which organization each entry belongs to, without reading the text.
## Full Consultation Journal (all roles)
| Date | Organization | Role | Key Coded Entry |
|------|-------------|------|-----------------|
| May 2025 | NHS N&W ICB | Interim Head, Pop. Health & Data Analysis | [EFF001] 14.6M efficiency programme |
| Jul 2024 | NHS N&W ICB | Deputy Head, Pop. Health & Data Analysis | [BUD001] 220M budget management |
| May 2022 | NHS N&W ICB | High-Cost Drugs & Interface Pharmacist | [AUT002] Blueteq automation: 70% reduction |
| Nov 2017 | Tesco PLC | Pharmacy Manager | [INN001] Asthma screening: ~1M national revenue |
| Aug 2016 | Tesco PLC | Duty Pharmacy Manager | [REG001] GPhC registration commenced |
## Animation Behavior
- **Expand/collapse:** Height animation, 200ms, ease-out. No opacity fade — the content simply grows/shrinks.
- Only one consultation can be expanded at a time. Expanding a new entry collapses the previous one.
- The expand chevron rotates 180 degrees (pointing up when expanded).
+87
View File
@@ -0,0 +1,87 @@
# Reference: Visual Design System
> Extracted from goal.md — Visual System section. This is the SINGLE SOURCE OF TRUTH for colors, typography, spacing, borders, and motion throughout the Clinical Record PMR.
---
## Color Palette
This design is **light-mode only**. Clinical record systems operate in light mode — high ambient lighting in consulting rooms demands white backgrounds and dark text. A dark mode would break the metaphor.
**Backgrounds:**
- Main content area: `#F5F7FA` (cool light gray — the content background of EMIS/SystmOne)
- Card/panel surfaces: `#FFFFFF` (white)
- Sidebar: `#1E293B` (dark blue-gray — EMIS-style dark navigation panel)
- Patient banner: `#334155` (lighter blue-gray with white text)
- Login screen background: `#1E293B` (same as sidebar — institutional dark blue-gray)
**Text:**
- Primary text: `#111827` (gray-900 — near-black for maximum readability)
- Secondary text: `#6B7280` (gray-500)
- On dark surfaces: `#FFFFFF` (white) and `#94A3B8` (slate-400 for secondary)
**Accent and status colors:**
- NHS blue: `#005EB8` — primary interactive color. Used for buttons, active nav states, links, column headers. This is the actual NHS brand blue and will be instantly recognized.
- Green: `#22C55E` — active/resolved/current states. "Active" status dots, resolved problems, current role indicators.
- Amber: `#F59E0B` — alerts, in-progress items, notable achievements. The clinical alert banner uses this as its background.
- Red: `#EF4444` — urgent/critical markers. Used sparingly — only for genuinely important items (e.g., a "priority" flag on the referral form).
- Gray: `#6B7280` — inactive/historical items. Past roles that are no longer current, historical "medications."
**Traffic light system (used throughout):**
- Green circle: Active / Resolved / Current
- Amber circle: In progress / Alert / Notable
- Red circle: Urgent / Critical (rare)
- Gray circle: Inactive / Historical
## Typography
Clinical systems use system fonts — Inter or Segoe UI for general text, monospace for coded entries and data values. No decorative fonts, no variable tracking. Functional typography optimized for scanning dense tables.
- **Patient banner name:** Inter 600, 20px (not huge — clinical systems don't emphasize the patient name with large type)
- **Patient banner details:** Inter 400, 14px
- **Sidebar navigation labels:** Inter 500, 14px, white
- **Section headings (within main area):** Inter 600, 18px
- **Consultation entry titles:** Inter 600, 16px
- **Body text / descriptions:** Inter 400, 14px, line-height 1.6
- **Table headers:** Inter 600, 13px, uppercase, letter-spacing 0.03em, gray-500
- **Table data cells:** Inter 400, 14px
- **Coded entries / data values:** Geist Mono 400, 13px
- **Clinical codes (SNOMED-style):** Geist Mono 400, 12px, gray-400
- **Timestamps:** Geist Mono 400, 12px
- **Alert banner text:** Inter 500, 14px
## Spacing and Layout
- **Sidebar width:** 220px (fixed, desktop). Collapses to 56px (icon-only) on tablet.
- **Patient banner height:** 80px (full), 48px (condensed/sticky)
- **Main content max-width:** No max-width — clinical systems fill available space. Content flows within the area between sidebar and viewport edge.
- **Main content padding:** 24px
- **Card padding:** 16px (clinical systems are more compact than marketing sites)
- **Border radius:** 4px for cards and inputs (clinical systems use minimal rounding — 4px, not 12px or 16px)
- **Table row height:** 40px
- **Section spacing:** 24px between content blocks
- **Base unit:** 4px — tighter spacing than typical, reflecting clinical system density
## Borders and Surfaces
Borders are the dominant visual structuring element. Clinical systems do not rely on shadows or negative space — they use explicit borders to delineate every element.
- **All cards:** `1px solid #E5E7EB` (gray-200) border, `4px` border-radius, no shadow (or at most `0 1px 2px rgba(0,0,0,0.03)`)
- **Table cells:** `1px solid #E5E7EB` borders (all sides)
- **Sidebar border:** `1px solid #334155` (subtle right border in a slightly lighter shade)
- **Patient banner border:** `1px solid #475569` bottom border
- **Input fields:** `1px solid #D1D5DB` border, `4px` radius, `#FFFFFF` background, `8px 12px` padding
- **Active/selected rows:** `#EFF6FF` background (very subtle blue tint) — this is how EMIS highlights the selected row
## Motion
Clinical systems are fast and functional. Animations are minimal and purposeful — no spring physics, no bouncy transitions. Everything is immediate or uses simple ease-out.
- **Navigation switches:** Instant content swap. No crossfade, no slide. When you click a sidebar item, the main content area replaces immediately — just like clicking a tab in EMIS.
- **Consultation expand/collapse:** Height animation, 200ms, `ease-out`. No opacity fade — the content simply grows/shrinks.
- **Alert banner entrance:** Slide down from top, 250ms, with a subtle spring overshoot (this is the one exception — alerts are meant to demand attention).
- **Alert acknowledge:** The alert shrinks in height to zero (200ms) with a small green checkmark that flashes briefly.
- **Hover states:** Background-color transitions, 100ms. No transforms, no lifts. Just color.
- **Login typing:** Character-by-character reveal using `setInterval` (30ms per character for username, 20ms per dot for password).
- **Patient banner scroll condensation:** Smooth height transition (200ms) from full (80px) to condensed (48px) as user scrolls past the first 100px of content.
- **`prefers-reduced-motion`:** Typing animation completes instantly (full text appears), alert slides are replaced with fade-in, expand/collapse is instant.
+162
View File
@@ -0,0 +1,162 @@
# Reference: Interactions, Responsive Design, and Accessibility
> Extracted from goal.md — Interactions, Responsive Strategy, and Accessibility sections.
---
## Interactions and Micro-interactions
### Sidebar Navigation
- Clicking a sidebar item instantly swaps the main content area. No crossfade, no transition — just an immediate swap. This matches clinical system behavior exactly: navigation is instant.
- The active sidebar item updates its left border (3px, NHS blue) and background tint simultaneously, with no animation (instant state change).
### Consultation Expand / Collapse
- Clicking a consultation entry toggles between collapsed and expanded states.
- The expand animation: height grows from 0 to content height over 200ms, ease-out. Content opacity transitions from 0 to 1 over the same duration.
- Only one consultation can be expanded at a time. Expanding a new entry collapses the previous one.
- The expand chevron rotates 180 degrees (pointing up when expanded).
### Medication Row Hover
- Hovering a medication table row changes its background to `#EFF6FF` (subtle blue tint).
- No transform, no elevation change. Just color.
### Table Column Sorting
- Clicking a table column header sorts by that column. An arrow indicator (up/down) appears in the header.
- Clicking the same header again reverses sort direction.
- Sorting is instant (no animation on row reordering).
### Patient Banner Scroll Condensation
- As the user scrolls past 100px of content, the patient banner smoothly transitions from full (80px) to condensed (48px) over 200ms.
- The condensed banner shows only: name, NHS number, status dot, and action buttons.
- Scrolling back to top restores the full banner.
- Uses `position: sticky` with an `IntersectionObserver` to trigger the condensation.
### Alert Acknowledge
- Clicking "Acknowledge" on a clinical alert:
1. The warning icon cross-fades to a green checkmark (200ms)
2. After a 200ms hold, the alert's height animates to 0 (200ms, ease-out)
3. Content below shifts upward to fill the space (same 200ms timing)
### Search
- A search input in the sidebar header ("Search record...") provides fuzzy matching across all PMR sections.
- Typing shows a dropdown of results grouped by section (Consultations, Medications, Problems, etc.).
- Each result shows the section icon, the matching text, and a relevance indicator.
- Pressing Enter or clicking a result navigates to that section with the matching item highlighted/expanded.
- Implementation: fuse.js for fuzzy search across a pre-built index of all content.
### Context Menus
- Right-clicking (desktop) or long-pressing (mobile) on certain elements reveals a context menu:
- On a consultation entry: "Expand", "Copy to clipboard", "View coded entries"
- On a medication row: "View prescribing history", "Copy to clipboard"
- On a problem entry: "View linked consultations", "Copy to clipboard"
- Context menus styled: white background, `1px solid #E5E7EB` border, 4px radius, `box-shadow: 0 4px 12px rgba(0,0,0,0.1)`. Items in Inter 400, 14px, 36px row height.
### Login Screen Typing
- The username types character-by-character (30ms per character).
- The password dots appear faster (20ms per dot).
- A blinking cursor appears in the active field (530ms blink interval).
- The "Log In" button shows a brief active/pressed state before the interface materializes.
---
## Responsive Strategy
### Desktop (>1024px)
The full PMR experience. This is the design's primary target — clinical systems are desktop applications.
- Sidebar: 220px, always visible, dark blue-gray
- Patient banner: full width, 80px height, condensing to 48px on scroll
- Main content: fills remaining width (no max-width constraint)
- Tables: full column display, alternating row colors, sort controls
- Consultations: full History/Examination/Plan expanded view
- Search: integrated in sidebar header
### Tablet (768-1024px)
Sidebar collapses to icon-only mode (56px width). Hovering or tapping an icon shows the label as a tooltip.
- Patient banner: condensed to single-line format always (no full/condensed toggle)
- Main content: nearly full width
- Tables: may horizontally scroll if columns exceed available width
- Context menus: triggered by long-press instead of right-click
### Mobile (<768px)
The sidebar becomes a **bottom navigation bar** with 7 icon buttons.
**Bottom nav layout:**
```
[Summary] [Consult] [Meds] [Problems] [Invest] [Docs] [Refer]
```
Each icon from Lucide, 20px, with the active item highlighted in NHS blue with a label below. Height: 56px with safe area padding.
**Patient banner on mobile:** Minimal top bar: `CHARLWOOD, A (Mr) | 2211810 | (dot)` — action buttons collapse into "..." overflow menu.
**Content adaptations:**
- Tables switch to card layout: each row becomes a small card with fields stacked vertically
- Consultation entries: tap-to-expand pattern with larger tap targets (48px minimum height)
- Medications: table becomes stacked card list
- Referral form: full-width inputs, generous touch targets
- Search: moves to top of each view as a search bar
**Back navigation:** Each view has a back arrow returning to Summary.
### Breakpoint Summary
| Element | Desktop (>1024) | Tablet (768-1024) | Mobile (<768) |
|---------|-----------------|-------------------|---------------|
| Sidebar | 220px, full labels | 56px, icons only | Bottom nav bar |
| Patient banner | 80px full / 48px sticky | 48px always | Minimal top bar |
| Tables | Full columns, horizontal | Scroll if needed | Card layout (stacked) |
| Search | Sidebar header | Sidebar header | Top of each view |
| Context menus | Right-click | Long-press | Long-press |
---
## Accessibility
### Semantic HTML
- Sidebar: `<nav role="navigation" aria-label="Clinical record navigation">` with `<ul>` and `<li>` items. Active item uses `aria-current="page"`.
- Patient banner: `<header role="banner">` containing patient demographics.
- Main content area: `<main>` element with `aria-label` matching the current view name.
- Tables: Proper `<table>`, `<thead>`, `<th>`, `<tbody>`, `<tr>`, `<td>` markup. Column headers use `scope="col"`.
- Consultation entries: `<article>` elements with `<button>` for expand/collapse, `aria-expanded` attribute.
### Keyboard Navigation
- `Tab` moves between: sidebar items, patient banner buttons, main content interactive elements
- `ArrowUp` / `ArrowDown` within the sidebar moves between navigation items (roving tabindex)
- `Enter` / `Space` on sidebar items activates that view
- `Enter` / `Space` on consultation entries toggles expand/collapse
- `Alt+1` through `Alt+7` directly activates sidebar items
- `Escape` closes expanded items, context menus, and search dropdown
- Search input focusable with `/` key
### Screen Reader Experience
1. After login, announces: "Patient Record for Charlwood, Andrew. Summary view."
2. Clinical alert announced via `role="alert"`: full alert text
3. Tables announced with column headers
4. Expandable items announce expanded/collapsed state
5. Breadcrumb uses `<nav aria-label="Breadcrumb">`
### Alert Accessibility
- Uses `role="alert"` and `aria-live="assertive"`
- Acknowledge button: `aria-label="Acknowledge clinical alert"`
- Removal is smooth (element removes from accessibility tree)
### Focus Management
- After login: focus moves to first sidebar item (Summary)
- After navigating to new view: focus moves to first heading in main content
- After expanding consultation: focus moves to HISTORY heading
- After closing context menu: focus returns to trigger element
- After acknowledging alert: focus moves to main content first interactive element
### Color and Contrast
- All text meets WCAG 2.1 AA contrast requirements
- Traffic lights never sole communicator — always with text labels
- NHS blue on white: ~7.3:1 contrast ratio
- Amber alert text on amber bg: ~5.8:1 contrast ratio
### Motion Preferences
When `prefers-reduced-motion: reduce`:
- Login typing completes instantly
- Alert appears without slide
- Expand/collapse is instant
- Banner condensation is instant
- Hover background-color changes remain
+108
View File
@@ -0,0 +1,108 @@
# Reference: Investigations View (= Projects) + Documents View (= Education)
> Extracted from goal.md — Investigations and Documents sections. Two simpler views that share the expandable-row pattern.
---
## Investigations View (= Projects)
Projects presented as diagnostic investigations — tests that were ordered, performed, and returned results.
### Investigation List
```
+--[ Investigation Results ]----------------------------------------------+
| Test Name | Requested | Status | Result |
|------------------------------+-----------+----------+-------------------|
| PharMetrics Interactive | 2024 | Complete | Live (green) |
| Platform | | | |
| Patient Switching Algorithm | 2025 | Complete | 14,000 pts found |
| Blueteq Generator | 2023 | Complete | 70% reduction |
| CD Monitoring System | 2024 | Complete | Population-scale |
| Sankey Chart Analysis Tool | 2023 | Complete | Pathway audit |
| Patient Pathway Analysis | 2024 | Ongoing | In development |
+-------------------------------------------------------------------------+
```
### Status Badges
Styled like laboratory result status indicators:
- **Complete** (green dot): Investigation finished, results available
- **Ongoing** (amber dot): Investigation still in progress
- **Live** (pulsing green dot): Results are actively being used (for PharMetrics, which is a live URL)
### Expanded Investigation View
Clicking an investigation row reveals a detailed "results panel" below the row:
```
PharMetrics Interactive Platform
|-- Date Requested: 2024
|-- Date Reported: 2024
|-- Status: Complete - Live at medicines.charlwood.xyz
|-- Requesting Clinician: A. Charlwood
|-- Methodology:
| Real-time medicines expenditure dashboard providing
| actionable analytics for NHS decision-makers. Built with
| Power BI and SQL, tracking expenditure across the 220M
| prescribing budget.
|-- Results:
| - Real-time tracking of medicines expenditure
| - Actionable analytics for budget holders
| - Self-serve model for wider team
|-- Tech Stack: Power BI, SQL, DAX
|-- [View Results ->] (external link to medicines.charlwood.xyz)
```
The expanded view uses a tree-like indented structure (with box-drawing characters in monospace) to present the investigation report. This mirrors how lab results and imaging reports appear in clinical systems — structured, indented, with labelled fields.
### "View Results" Link
For PharMetrics (the only project with a live URL), a "View Results" button appears styled as an NHS blue action button. For internal projects, this button is absent.
---
## Documents View (= Education & Certifications)
Education and certifications presented as attached documents in the patient record.
### Document List
```
+--[ Attached Documents ]-------------------------------------------------+
| Type | Document | Date | Source |
|----------------+----------------------------------+---------+------------|
| Certificate | MPharm (Hons) 2:1 | 2015 | UEA |
| Registration | GPhC Pharmacist Registration | 2016 | GPhC |
| Certificate | Mary Seacole Programme (78%) | 2018 | NHS LA |
| Results | A-Levels: Maths A*, Chem B, | 2011 | Highworth |
| | Politics C | | Grammar |
| Research | Drug Delivery & Cocrystals | 2015 | UEA |
| | (75.1% Distinction) | | |
+-------------------------------------------------------------------------+
```
### Document Type Icons
Small document icons from Lucide:
- `FileText` for certificates
- `Award` for registrations
- `GraduationCap` for academic results
- `FlaskConical` for research
### Expanded Document Preview
```
MPharm (Hons) 2:1 - University of East Anglia
|-- Type: Academic Qualification
|-- Date Awarded: 2015
|-- Institution: University of East Anglia, Norwich
|-- Classification: Upper Second-Class Honours (2:1)
|-- Duration: 2011 - 2015 (4 years)
|-- Research: Drug delivery and cocrystals
| Grade: 75.1% (Distinction)
|-- Notes: MPharm is a 4-year integrated Master's degree
required for pharmacist registration in the UK.
```
The preview panel uses the same tree-indented structure as the Investigations expanded view, maintaining visual consistency across the PMR interface.
+93
View File
@@ -0,0 +1,93 @@
# Reference: Medications View (= Skills)
> Extracted from goal.md — Medications View section. Skills presented as an active medications list.
---
## Overview
Skills presented as an active medications list — the format every pharmacist and GP reads daily.
## Full Table Layout
```
+--[ Active Medications ]-------------------------------------------------+
| Drug Name | Dose | Frequency | Start | Status |
|--------------------+-------+------------+----------+-------------------|
| Python | 90% | Daily | 2017 | Active (green) |
| SQL | 88% | Daily | 2017 | Active (green) |
| Power BI | 92% | Daily | 2019 | Active (green) |
| Data Analysis | 95% | Daily | 2016 | Active (green) |
| JavaScript / TS | 70% | Weekly | 2020 | Active (green) |
| Dashboard Dev | 88% | Weekly | 2019 | Active (green) |
| Algorithm Design | 82% | Weekly | 2022 | Active (green) |
| Data Pipelines | 80% | Weekly | 2022 | Active (green) |
+-------------------------------------------------------------------------+
+--[ Clinical Medications ]-----------------------------------------------+
| Drug Name | Dose | Frequency | Start | Status |
|-------------------------+-------+------------+--------+----------------|
| Medicines Optimisation | 95% | Daily | 2016 | Active (green) |
| Pop. Health Analytics | 90% | Daily | 2022 | Active (green) |
| NICE TA Implementation | 85% | Weekly | 2022 | Active (green) |
| Health Economics | 80% | Monthly | 2023 | Active (green) |
| Clinical Pathways | 82% | Weekly | 2022 | Active (green) |
| CD Assurance | 88% | Weekly | 2024 | Active (green) |
+-------------------------------------------------------------------------+
+--[ PRN (As Required) ]--------------------------------------------------+
| Drug Name | Dose | Frequency | Start | Status |
|-------------------------+-------+------------+--------+----------------|
| Budget Management | 90% | As needed | 2024 | Active (green) |
| Stakeholder Engagement | 88% | As needed | 2022 | Active (green) |
| Pharma Negotiation | 85% | As needed | 2024 | Active (green) |
| Team Development | 82% | As needed | 2017 | Active (green) |
+-------------------------------------------------------------------------+
```
## Column Definitions
| Column | PMR Meaning | CV Mapping |
|--------|------------|------------|
| Drug Name | Medication name | Skill name |
| Dose | Dosage strength | Proficiency percentage |
| Frequency | How often taken | How often the skill is used (Daily / Weekly / Monthly / As needed) |
| Start | Date prescribed | Year Andy started using this skill (approximate) |
| Status | Active / Stopped | Active (green dot) for current skills, Historical (gray dot) for deprecated skills |
## Medication Categories (tabs within the view)
Skills are grouped into three "medication types," mimicking how clinical systems separate regular, acute, and PRN medications:
- **Active Medications** = Technical skills (the "regular medications" — taken daily, core to function)
- **Clinical Medications** = Healthcare domain skills (the specialist prescriptions)
- **PRN (As Required)** = Strategic & leadership skills (used situationally, not daily)
## Table Styling
- Table headers: Inter 600, 13px, uppercase, gray-400, `#F9FAFB` background
- Table rows: alternating `#FFFFFF` / `#F9FAFB` backgrounds
- Row height: 40px
- All borders: `1px solid #E5E7EB`
- Hover state: row background changes to `#EFF6FF` (subtle blue tint)
- Status dots: 6px circles, inline with status text
## Interaction — Prescribing History
Clicking any medication/skill row expands it downward to show a "prescribing history" — a mini-timeline of how the skill developed:
```
Python | 90% | Daily | 2017 | Active (green)
|-- Prescribing History:
2017 Started: Self-taught for data analysis automation
2019 Increased: Dashboard development, data pipeline work
2022 Specialist use: Blueteq automation, Sankey analysis tools
2024 Advanced: Switching algorithm (14,000 patients), CD monitoring
2025 Current: Population-level analytics, incentive scheme automation
```
The history entries are styled in Geist Mono, 12px, with year markers as bold anchors and descriptions in regular weight. This "prescribing history" shows skill progression in a format that clinicians understand intuitively.
## Sortable Columns
Table columns are sortable by clicking the header. Clicking "Dose" sorts by proficiency descending. Clicking "Start" sorts chronologically. A small sort indicator arrow appears in the active sort column header. Default sort: by category grouping.
+60
View File
@@ -0,0 +1,60 @@
# Reference: Problems View (= Achievements / Challenges)
> Extracted from goal.md — Problems View section. Career achievements framed as clinical problems that were identified, treated, and resolved.
---
## Overview
The "Problems" list in a clinical record tracks diagnoses — conditions that were identified, treated, and either resolved or require ongoing management. This maps perfectly to career achievements: challenges that Andy identified and resolved.
## Two Sections: Active Problems and Resolved Problems
### Active Problems (current / ongoing)
```
+--[ Active Problems ]----------------------------------------------------+
| Status | Code | Problem | Since |
|--------+-----------+--------------------------------------+------------|
| AMB | [MGT001] | 220M prescribing budget oversight | Jul 2024 |
| GRN | [TRN001] | Patient-level SQL transformation | 2025 |
| AMB | [LEA001] | Team data literacy programme | Jul 2024 |
+-------------------------------------------------------------------------+
```
### Resolved Problems (past achievements)
```
+--[ Resolved Problems ]--------------------------------------------------+
| Status | Code | Problem | Resolved | Outcome |
|--------+-----------+--------------------------------+-----------+------------------------------------------|
| GRN | [EFF001] | Manual prescribing analysis | Oct 2025 | Python algorithm: 14,000 pts, 2.6M/yr |
| | | inefficiency | | |
| GRN | [EFF002] | 14.6M efficiency target | Oct 2025 | Over-target performance achieved |
| GRN | [AUT001] | Blueteq form creation backlog | 2023 | 70% reduction, 200hrs saved |
| GRN | [INN001] | Asthma screening scalability | 2019 | National rollout: ~300 branches, ~1M |
| GRN | [AUT002] | Incentive scheme manual calc. | 2025 | Automated: 50% Rx reduction in 2 months |
| GRN | [DAT001] | HCD spend tracking gaps | 2023 | Blueteq-secondary care data integration |
| GRN | [VIS001] | Patient pathway opacity | 2023 | Sankey chart analysis tool |
| GRN | [MON001] | Population opioid exposure | 2024 | CD monitoring system: OME tracking |
| | | monitoring | | |
+-------------------------------------------------------------------------+
```
## Column Definitions
| Column | Meaning |
|--------|---------|
| Status | Traffic light: Green (resolved), Amber (in progress / active), Red (urgent — unused, reserved) |
| Code | SNOMED-style reference code. Fictional but internally consistent. Formatted in Geist Mono. |
| Problem | The challenge or opportunity Andy identified |
| Resolved | Date or year the problem was resolved |
| Outcome | Brief description of the resolution and its measurable impact |
## Expandable Rows
Each problem row can be expanded to show a full narrative: what the problem was, how Andy approached it, what tools/methods were used, and the quantified outcome. The expanded state also shows "linked consultations" — clicking a link navigates to the relevant entry in Consultations view.
## Traffic Light Status Indicators
Traffic lights are 8px circles with the status colors (green, amber, red, gray). They appear inline before the code column. This is exactly how clinical systems indicate problem severity/status — it's an immediately scannable visual language.
+72
View File
@@ -0,0 +1,72 @@
# Reference: Referrals View (= Contact)
> Extracted from goal.md — Referrals View section. Contact information presented as a clinical referral form.
---
## Overview
Contact information presented as a clinical referral form — the mechanism for "referring" a patient (Andy) to another service.
## Referral Form Layout
```
+--[ New Referral ]-------------------------------------------------------+
| |
| Referring to: CHARLWOOD, Andrew (Mr) |
| NHS Number: 221 181 0 |
| |
| Priority: ( ) Urgent (*) Routine ( ) Two-Week Wait |
| |
| Referrer Name: [________________________] |
| Referrer Email: [________________________] |
| Referrer Org: [________________________] (optional) |
| |
| Reason for Referral: |
| [ ] |
| [ ] |
| [ ] |
| |
| Contact Method: ( ) Email ( ) Phone ( ) LinkedIn |
| |
| [ Cancel ] [ Send Referral ] |
+-------------------------------------------------------------------------+
```
## Priority Toggle (tongue-in-cheek)
Three radio options styled like clinical referral priorities:
- **Urgent**: Red label, red dot. Selectable but the tooltip reads "All enquiries are welcome, urgent or not."
- **Routine**: Blue label, blue dot. Default selected.
- **Two-Week Wait**: Amber label. Tooltip: "NHS cancer referral pathway - this isn't that, but the spirit of promptness applies."
This is the design's main moment of humor. The priority options are visually authentic to clinical referral forms, and the tongue-in-cheek tooltips reward exploration without undermining the professional tone.
## Form Fields
Standard clinical form inputs: `1px solid #D1D5DB` border, `4px` radius, `8px 12px` padding. Labels in Inter 500, 13px, gray-600, positioned above inputs. Focus state: border changes to NHS blue, subtle blue glow (`box-shadow: 0 0 0 3px rgba(0, 94, 184, 0.15)`).
## Submit Button
"Send Referral" in NHS blue (`#005EB8`), white text, full width of the right half of the form. On hover: darkens to `#004494`. On click: brief loading state (spinner icon), then a success message:
```
Checkmark Referral sent successfully
Reference: REF-2026-0210-001
Expected response time: 24-48 hours
```
The reference number is generated from the current date. The success state mimics the confirmation screen shown after submitting a clinical referral in EMIS.
## Alternative Contact Methods (below the form)
```
+--[ Direct Contact ]-----------------------------------------------------+
| Email: andy@charlwood.xyz [Send Email ->] |
| Phone: 07795553088 [Call ->] |
| LinkedIn: linkedin.com/in/andycharlwood [View Profile ->] |
| Location: Norwich, UK |
+-------------------------------------------------------------------------+
```
Styled as a simple key-value table, same format as the Patient Demographics card in Summary view.
+116
View File
@@ -0,0 +1,116 @@
# Reference: Summary View + Clinical Alert
> Extracted from goal.md — Summary View and Clinical Alert sections. This is the landing view after login.
---
## Summary View
The landing view after login. This mimics the "Patient Summary" screen — the first screen a clinician sees when opening a patient record, showing the most important information at a glance.
**Layout:** A grid of summary cards arranged in a 2-column layout on desktop, single column on mobile. Each card has a header bar with the card title in Inter 600, 14px, uppercase, on a `#F9FAFB` background with `1px solid #E5E7EB` bottom border.
### Card 1: Patient Demographics (spans full width)
```
+--[ Patient Demographics ]------------------------------------------+
| Name: Andrew Charlwood Status: Active (dot) |
| DOB: 14 February 1993 Location: Norwich, UK |
| Registration: GPhC 2211810 Since: August 2016 |
| Qualification: MPharm (Hons) 2:1 University: UEA, 2015 |
+---------------------------------------------------------------------+
```
A two-column key-value table. Labels in Inter 500, 13px, gray-500. Values in Inter 400, 14px, gray-900. Labels right-aligned, values left-aligned — mimicking clinical system demographics layout.
### Card 2: Active Problems (left column)
```
+--[ Active Problems ]-----------------------------------------------+
| (green dot) Deputy Head, Pop. Health & Data Analysis Jul 2024-Present |
| NHS Norfolk & Waveney ICB |
| (green dot) 220M prescribing budget management Ongoing |
| (amber dot) Patient-level SQL analytics transformation In progress |
+---------------------------------------------------------------------+
```
A list with green dots for active/current items, amber dots for in-progress items. Each entry has a title in Inter 500, 14px, and a date range or status in Geist Mono, 12px, right-aligned. Click an entry to navigate to the corresponding Consultation.
### Card 3: Current Medications — Quick View (right column)
```
+--[ Current Medications (Quick View) ]-------------------------------+
| Python | 90% | Daily | Active (green dot) |
| SQL | 88% | Daily | Active (green dot) |
| Power BI | 92% | Daily | Active (green dot) |
| Data Analysis | 95% | Daily | Active (green dot) |
| JS / TypeScript | 70% | Weekly | Active (green dot) |
| [View Full List ->] |
+---------------------------------------------------------------------+
```
A compact 4-column table showing the top 5 skills. "View Full List" links to the Medications view. Table headers are uppercase, 12px, gray-400. Table rows alternate between `#FFFFFF` and `#F9FAFB` backgrounds.
### Card 4: Last Consultation (spans full width)
```
+--[ Last Consultation ]----------------------------------------------+
| Date: May 2025 Clinician: A. Charlwood Location: NHS N&W ICB |
| |
| Interim Head, Population Health & Data Analysis |
| Led strategic delivery of population health initiatives and |
| data-driven medicines optimisation across Norfolk & Waveney ICS... |
| [View Full Record ->] |
+---------------------------------------------------------------------+
```
A preview of the most recent role, truncated to 2-3 lines. "View Full Record" navigates to Consultations with that entry expanded.
### Card 5: Alerts (full width, positioned above all other cards)
This is the Clinical Alert — see below.
---
## The Clinical Alert (Signature Interaction)
When the user first loads the Summary view (immediately after the login transition), a clinical alert banner slides down from beneath the patient banner.
### Alert Styling
```
+--[ WARNING CLINICAL ALERT ]------------------------------------------+
| WARNING ALERT: This patient has identified 14.6M in prescribing |
| efficiency savings across Norfolk & Waveney ICS. |
| [Acknowledge]|
+----------------------------------------------------------------------+
```
- Background: amber (`#FEF3C7` — amber-100, light amber)
- Left border: 4px solid `#F59E0B` (amber-500)
- Warning icon: `AlertTriangle` from Lucide, amber-600
- Text: Inter 500, 14px, `#92400E` (amber-800)
- "Acknowledge" button: small outlined button, amber border and text
### Behavior
1. The alert slides down from beneath the patient banner with a spring animation (250ms, slight overshoot) after the PMR interface finishes materializing.
2. It pushes the Summary content downward, so it's impossible to miss.
3. Clicking "Acknowledge" triggers a brief animation: a green checkmark replaces the warning icon (200ms), then the alert collapses upward (200ms, ease-out) and is gone.
4. The dismiss state is stored in React state (session-only) — refreshing the page shows the alert again.
### Why This Works
Clinical alerts are the mechanism that clinical systems use to put critical information in front of clinicians before they do anything else. They are the highest-priority information in the system. By framing Andy's most impressive metric ("14.6M") as a clinical alert, it gets the same treatment — it's the first thing the user reads, it demands acknowledgment, and its format gives the number institutional weight. This is not a boast in a paragraph; it's a system-generated alert based on data. The framing makes the achievement feel objective.
### Second Alert (on Consultations view)
When the user first navigates to Consultations, a secondary alert appears:
```
WARNING NOTE: Patient has developed a Python-based switching algorithm
identifying 14,000 patients for cost-effective medication alternatives.
2.6M annual savings potential. Review recommended.
```
This second alert reinforces the key technical achievement in clinical language. It appears only once (on first navigation to Consultations) and is dismissible with the same "Acknowledge" interaction.
+202
View File
@@ -0,0 +1,202 @@
# Reference: ECG Transition + Login Sequence
> Extracted from goal.md — ECG Transition section. This covers the flatline exit from the ECG animation and the immersive login sequence that bridges into the PMR interface.
---
## Starting Point
"ANDREW CHARLWOOD" is on screen in neon green (`#00ff41`) on black. The heartbeat trace is complete. The name is fully formed and glowing.
## Phase 1: The Flatline (600ms)
The neon green name holds for a beat (300ms). Then the glow around the letters begins to fade. Simultaneously, from the right edge of the name, a flatline trace extends rightward — a perfectly horizontal green line drawn at the baseline, extending across the remaining viewport width over 300ms. The visual reads as a patient monitor flatline. This is deliberate: the "patient" (the animation phase) is ending. A new record is about to open.
The flatline has a subtle audio-visual implication without actual sound — the green line is steady and unbroken, the glow around the name letters reduces to zero. The entire canvas is now: a fading green name with a horizontal flatline extending to the right edge. All on black.
## Phase 2: Screen Clear (400ms)
The entire canvas fades to black over 200ms (the name and flatline dissolve into darkness). Then, from black, the background transitions to a dark blue-gray (`#1E293B`) over 200ms. This is the color of a clinical system login screen — the dark institutional background that every NHS worker recognizes from their Monday morning.
## Phase 3: Login Sequence (1200ms)
A login panel materializes center-screen: a white card (320px wide, 12px border-radius, subtle shadow) on the dark blue-gray background. The card contains:
- A small NHS-blue shield icon or generic clinical system logo at the top
- **Username field**: Empty text input with label "Username". After 200ms, a cursor appears and types `A.CHARLWOOD` character by character (30ms per character, ~350ms total). The typing uses Geist Mono / monospace font.
- **Password field**: After a 150ms pause, dots fill the password field in rapid succession (8 dots, 20ms each, ~160ms total).
- **"Log In" button**: NHS blue (`#005EB8`), full width. After another 150ms pause, the button receives a subtle pressed state (darkens slightly, 100ms) as if clicked.
The login card holds for 200ms in its "submitted" state, then...
## Phase 4: Interface Materialization (500ms)
The login card scales up slightly (103%) and fades out (200ms). As it fades, the full PMR interface fades in behind it:
1. **Patient banner** slides down from the top edge (200ms, ease-out)
2. **Sidebar** slides in from the left edge (250ms, ease-out, starting 50ms after the banner)
3. **Main content area** (Summary view) fades in (300ms, starting 100ms after sidebar begins)
4. **Clinical alert banner** slides down from beneath the patient banner (250ms, spring easing, starting 200ms after main content appears)
## Phase 5: Final State
The full PMR interface is visible: patient banner at top, dark sidebar on left, Summary view in the main content area, and the clinical alert banner demanding attention. The user is now "logged in" to Andy's career record.
**Total transition duration:** ~2.7 seconds
## Why This Works
The login sequence is the most immersive transition of all designs. Every NHS worker, every pharmacist, every GP has typed their credentials into a clinical system at 8am on a Monday. This transition puts them right there. It's specific, it's authentic, and it immediately establishes the metaphor: you are opening a patient record. The "patient" happens to be a career.
## Login Animation Implementation Notes
- Component mounts with dark blue-gray background
- Login card fades in (Framer Motion, 200ms)
- Username typing: `setInterval` adds one character per 30ms to a state string
- Password dots: `setInterval` adds one dot per 20ms
- Button press: state change triggers visual pressed state, then 200ms delay
- `onComplete` callback fires, parent component swaps to PMRInterface
- Typing respects `prefers-reduced-motion` — with reduced motion, full username appears instantly and login completes in ~500ms total
- **Font: Geist Mono** for username/password fields (NOT Fira Code)
---
## Design Guidance (from /frontend-design)
> Pre-baked design direction. Do NOT invoke `/frontend-design` at runtime — this section contains the output.
### Aesthetic Direction: Institutional Utilitarian
This is not "exciting" design — it is the visual equivalent of fluorescent lights, laminate desks, and the smell of hand sanitiser at 07:58 on a Monday morning. The card must look like every single hospital login prompt a doctor has ever seen: clean white, unadorned, functional. No personality. The branding is the only concession to identity. The magic is not visual flair — it is the uncanny recognition of "oh, this is exactly what that looks like" combined with the satisfying typewriter rhythm of credentials appearing.
### Key Design Decisions
1. **Active field focus ring**: NHS-blue border (`1px solid #005EB8`) on the currently active field, inactive fields shift to `#FAFAFA` background. Mirrors real NHS login forms (Lorenzo, SystmOne, EMIS Web). Transition 150ms.
2. **Reduced shadow to spec**: Use exactly `0 1px 2px rgba(0,0,0,0.03)`. Card sits on dark background through border definition, not shadow depth — more faithful to real NHS software.
3. **Border**: Use `1px solid #E5E7EB` per design system (not `rgba(255,255,255,0.1)`).
4. **Timer cleanup**: Track every `setInterval` and `setTimeout` via refs, clear all on unmount.
5. **Consolidated active field state**: Single `activeField` state (`'username' | 'password' | null`) instead of separate booleans.
6. **Accessibility**: `role="status"` + `aria-label` on outer container. Cursor pipes `aria-hidden="true"`. Card entrance `scale: 0.98` (not 0).
7. **The Monday-morning feeling**: No gradients, no decorative elements, no loading spinners, no "Welcome back!" messaging. Just white rectangle on gray, shield icon, two fields, button. Typing speed deliberately mechanical.
### Implementation Pattern
```tsx
import { useState, useEffect, useCallback, useRef } from 'react'
import { motion } from 'framer-motion'
import { Shield } from 'lucide-react'
interface LoginScreenProps {
onComplete: () => void
}
// Key state
const [username, setUsername] = useState('')
const [passwordDots, setPasswordDots] = useState(0)
const [showCursor, setShowCursor] = useState(true)
const [activeField, setActiveField] = useState<'username' | 'password' | null>('username')
const [buttonPressed, setButtonPressed] = useState(false)
const [isExiting, setIsExiting] = useState(false)
const fullUsername = 'A.CHARLWOOD'
const passwordLength = 8
```
Card structure:
```tsx
<motion.div
className="bg-white"
style={{
width: '320px',
padding: '32px',
borderRadius: '12px',
border: '1px solid #E5E7EB',
boxShadow: '0 1px 2px rgba(0, 0, 0, 0.03)',
}}
initial={{ opacity: 0, scale: 0.98 }}
animate={isExiting ? { scale: 1.03, opacity: 0 } : { scale: 1, opacity: 1 }}
transition={{ duration: 0.2, ease: 'easeOut' }}
>
```
Branding header:
```tsx
<div className="flex flex-col items-center" style={{ marginBottom: '28px' }}>
<div style={{
padding: '10px',
borderRadius: '8px',
backgroundColor: 'rgba(0, 94, 184, 0.07)',
marginBottom: '10px',
}}>
<Shield size={26} style={{ color: '#005EB8' }} strokeWidth={2.5} />
</div>
<span style={{
fontFamily: "'Inter', system-ui, sans-serif",
fontSize: '13px', fontWeight: 600,
color: '#64748B', letterSpacing: '0.01em',
}}>CareerRecord PMR</span>
<span style={{
fontFamily: "'Inter', system-ui, sans-serif",
fontSize: '11px', fontWeight: 400,
color: '#94A3B8', marginTop: '2px',
}}>Clinical Information System</span>
</div>
```
Input field pattern (username example):
```tsx
<div style={{
width: '100%',
padding: '9px 11px',
fontFamily: "'Geist Mono', 'Fira Code', monospace",
fontSize: '13px',
backgroundColor: activeField === 'username' ? '#FFFFFF' : '#FAFAFA',
border: activeField === 'username' ? '1px solid #005EB8' : '1px solid #E5E7EB',
borderRadius: '4px',
color: '#111827',
minHeight: '38px',
display: 'flex',
alignItems: 'center',
}}>
<span>{username}</span>
{activeField === 'username' && (
<span style={{ opacity: showCursor ? 1 : 0, color: '#005EB8' }} aria-hidden="true">|</span>
)}
</div>
```
Login button:
```tsx
<button style={{
width: '100%',
padding: '10px 16px',
fontFamily: "'Inter', system-ui, sans-serif",
fontSize: '14px', fontWeight: 600,
color: '#FFFFFF',
backgroundColor: buttonPressed ? '#004494' : '#005EB8',
border: 'none',
borderRadius: '4px',
}}>Log In</button>
```
Typing sequence (reduced motion branch):
```tsx
if (prefersReducedMotion) {
setUsername(fullUsername)
setPasswordDots(passwordLength)
setActiveField(null)
setTimeout(() => { setButtonPressed(true); setTimeout(triggerComplete, 100) }, 300)
return
}
// Normal: username at 30ms/char, 150ms pause, password at 20ms/dot, 150ms pause, button press
```
Footer:
```tsx
<div style={{ marginTop: '22px', paddingTop: '18px', borderTop: '1px solid #E5E7EB' }}>
<p style={{
fontFamily: "'Inter', system-ui, sans-serif",
fontSize: '11px', color: '#94A3B8', textAlign: 'center',
}}>Secure clinical system login</p>
</div>
```