Task 1b: Rebuild boot sequence and ECG animation
- Refactored BootSequence to config-driven architecture with type-safe line components - Added cursor position capture and smooth cursor-to-dot morph transition - Rebuilt ECGAnimation with mask-based text reveal technique - Implemented connector lines between letters with per-character profiles - ECG trace now starts from cursor position (no teleport) - Added prefers-reduced-motion support for both phases - Updated App.tsx to pass cursor position between components Quality checks: typecheck ✓, lint ✓, build ✓
This commit is contained in:
@@ -24,7 +24,7 @@ Each task below references a specific file in `Ralph/refs/` — read ONLY that f
|
||||
|
||||
- [x] **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-theme` class 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.md` and `Ralph/refs/ref-design-system.md`. Also read `ECGCombined.tsx` in 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, `#00ff41` bright green / `#3a6b45` dim green / `#00e5ff` cyan 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 a `startPosition` prop. 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) Respect `prefers-reduced-motion` — with reduced motion, skip animation and show static final frame or jump to login.
|
||||
- [x] **Task 1b: Rebuild boot sequence and ECG animation.** Read `Ralph/refs/ref-boot-ecg.md` and `Ralph/refs/ref-design-system.md`. Also read `ECGCombined.tsx` in 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, `#00ff41` bright green / `#3a6b45` dim green / `#00e5ff` cyan 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 a `startPosition` prop. 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) Respect `prefers-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.md` and `Ralph/refs/ref-design-system.md`. Rebuild `src/components/LoginScreen.tsx` to match the login sequence specification exactly: (a) Dark blue-gray `#1E293B` background. (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 types `A.CHARLWOOD` at 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) Respect `prefers-reduced-motion`. The login must feel like actually logging into NHS software at 8am on a Monday.
|
||||
|
||||
|
||||
@@ -91,3 +91,58 @@ Do NOT invoke the `/frontend-design` skill at runtime — it was pre-run and the
|
||||
|
||||
### ECG Reference Implementation
|
||||
`ECGCombined.tsx` in the project root is a Remotion version of the ECG animation with a superior mask-based text reveal technique. Task 1b references this for the canvas implementation.
|
||||
|
||||
### Iteration 2 — Task 1b: Rebuild boot sequence and ECG animation
|
||||
**Completed:** Task 1b
|
||||
**Changes made:**
|
||||
- **BootSequence.tsx**: Completely refactored from hardcoded HTML strings to config-driven architecture
|
||||
- Created type-safe `BootConfig`, `BootLine`, `BootLineType` interfaces
|
||||
- Individual line components: `BootLineHeader`, `BootLineStatus`, `BootLineSeparator`, `BootLineField`, `BootLineModule`, `BootLineReady`
|
||||
- Added CRT scanlines overlay during boot phase
|
||||
- Cursor now captures its screen position via ref and passes to parent via `onCursorPositionReady` callback
|
||||
- Cursor morph animation: block cursor scales down to 0 width over 300ms before ECG starts
|
||||
- Reduced motion support: instant boot completion, skips to ECG immediately
|
||||
|
||||
- **ECGAnimation.tsx**: Rebuilt with mask-based text reveal technique from ECGCombined.tsx
|
||||
- Added `startPosition` prop to receive cursor position from BootSequence
|
||||
- ECG trace now starts from cursor position (with `startOffsetX`) instead of x=0
|
||||
- Implemented offscreen canvas pre-rendering for text stroke
|
||||
- Mask-based text reveal: clipping region follows trace head, revealing pre-rendered text
|
||||
- Added connector lines between letters at baseline using `CONNECTOR_PROFILES`
|
||||
- Letter profiles define connector insets for natural-looking baseline connections
|
||||
- Multi-layer neon glow: outer (6px, 25% opacity), inner (2px solid)
|
||||
- Flatline draw phase extends to right edge after text completion
|
||||
- Background transitions from black to `#1E293B` (login background)
|
||||
- Reduced motion support: instant transition to PMR phase
|
||||
|
||||
- **App.tsx**: Updated to pass cursor position between BootSequence and ECGAnimation
|
||||
- Added `cursorPosition` state
|
||||
- `handleCursorPositionReady` captures position from BootSequence
|
||||
- Passed to ECGAnimation as `startPosition` prop
|
||||
|
||||
**Codebase patterns discovered:**
|
||||
- Canvas animation performance: pre-render text to offscreen canvas, then drawImage through clip region
|
||||
- Cursor-to-dot transition requires DOM ref position capture, not just CSS animation
|
||||
- World-space coordinates (headWX) vs screen-space coordinates (headSX) separation is critical
|
||||
- Viewport scrolling logic: offset calculated as `headWX - headSX` keeps trace visible
|
||||
- Connector profiles per character (C, O, D, L, E have special insets) make letter connections look natural
|
||||
- Background color transition handled via CSS transition on container, not canvas fill
|
||||
|
||||
**Quality checks:** All passed (typecheck, lint, build)
|
||||
- TypeScript: No errors
|
||||
- ESLint: 1 pre-existing warning in AccessibilityContext.tsx (not our changes)
|
||||
- Build: Successful, 388KB bundle
|
||||
|
||||
**Visual review:** N/A (animation component — visual verification would require browser screenshot)
|
||||
|
||||
**Issues encountered:** None
|
||||
|
||||
**Design decisions:**
|
||||
- Kept Fira Code for terminal/boot phase (it's the authentic clinical terminal aesthetic)
|
||||
- Used ECGCombined.tsx's mask technique but adapted for canvas API (not SVG like the Remotion version)
|
||||
- Beat amplitudes: 0.3 → 0.55 → 0.85 → 1.0 (same as original implementation)
|
||||
- Letter spacing: LETTER_W 72px, LETTER_G 10px, SPACE_W 30px (matches original, tighter than ECGCombined)
|
||||
- Morph animation uses Framer Motion scaleX/width/opacity for smooth cursor-to-dot transition
|
||||
|
||||
**Next task:** Task 2 — Rebuild LoginScreen component
|
||||
|
||||
|
||||
Reference in New Issue
Block a user