diff --git a/Ralph/prd.json b/Ralph/prd.json index f3d4cc6..b28aa0c 100644 --- a/Ralph/prd.json +++ b/Ralph/prd.json @@ -14,7 +14,7 @@ "Typecheck passes" ], "priority": 1, - "passes": false, + "passes": true, "notes": "Temporary — final story reverts this. Phase state is on line 47 of App.tsx." }, { @@ -34,7 +34,7 @@ "Typecheck passes" ], "priority": 2, - "passes": false, + "passes": true, "notes": "The SVG uses a transform with scale(0.05, -0.05) and translate — you'll need to simplify the viewBox and transforms for React. The three IDs are capsule-rx, capsule-terminal, capsule-data. Framer Motion is already installed (11.15.0). Look at LogoReveal/frame 1-5.jpg for the animation sequence. The fan-out in frames 4-5 shows: teal Rx tilts left, amber terminal stays center, green data tilts right." }, { @@ -56,7 +56,7 @@ "Verify in browser using dev-browser skill" ], "priority": 3, - "passes": false, + "passes": true, "notes": "LoginScreen.tsx currently uses inline styles with hardcoded colors (#E5E7EB borders, #64748B text, etc). Replace these with the dashboard CSS custom properties defined in index.css (--surface, --accent, --border, --text-primary, --text-secondary, --text-tertiary). Font family vars: var(--font-ui) for labels/buttons, var(--font-geist-mono) for input monospace." }, { @@ -76,7 +76,7 @@ "Verify in browser using dev-browser skill" ], "priority": 4, - "passes": false, + "passes": true, "notes": "The Shield icon is at LoginScreen.tsx lines 213-218. The logo animation is ~1000ms (500ms rise + 500ms fan-out). Increase the startLoginSequence delay from 400ms to ~1500ms (400ms card entrance + 1000ms logo + 100ms pause). CvmisLogo component from US-002." }, { diff --git a/Ralph/progress.txt b/Ralph/progress.txt index 2569d66..17ebcac 100644 --- a/Ralph/progress.txt +++ b/Ralph/progress.txt @@ -50,16 +50,70 @@ - cvmis-logo.svg — source SVG with 3 capsule groups - LogoReveal/frame 1-5.jpg — animation reference frames -### LoginScreen.tsx Key Lines +### CvmisLogo Component +- `size` prop: numeric, sets SVG height attribute directly +- `cssHeight` prop: string, sets height via CSS style (use for clamp/responsive values) +- `animated` prop: boolean, enables framer-motion reveal animation (1000ms total) +- Logo animation: 500ms rise (green capsule) + 500ms fan-out (all three) = 1000ms total + +### LoginScreen.tsx Key Lines (post US-004) - Line 20: connectionState useState - Line 43: canLogin derived state - Line 60-101: startLoginSequence (typing animation) -- Line 110-137: useEffect with connectionTimeout (2000ms) and startLoginSequence delay (400ms) -- Line 145-415: JSX render (card, form, button, status indicator) -- Line 213-218: Shield icon (to be replaced) -- Line 229: "CareerRecord PMR" title -- Line 240: "Clinical Information System" subtitle -- Line 367-388: Connection status indicator (6px dot, 10px text) +- Line 110-139: useEffect with connectionTimeout (2000ms) and startLoginSequence delay (1500ms / 400ms reduced motion) +- Line 145-409: JSX render (card, form, button, status indicator) +- Line 208-211: CvmisLogo with cssHeight="clamp(48px, 4vw, 64px)" animated=true +- Line 221: "CVMIS" title +- Line 232: "CV Management Information System" subtitle +- Line 350-382: Connection status indicator (6px dot, 10px text) --- +## 2026-02-15 - US-004 +- Rebranded login from "CareerRecord PMR" to "CVMIS" with subtitle "CV Management Information System" +- Replaced Shield icon with CvmisLogo component (animated=true, responsive cssHeight) +- Added `cssHeight` prop to CvmisLogo for CSS clamp-based responsive sizing: clamp(48px, 4vw, 64px) +- Increased startLoginSequence delay from 400ms to 1500ms to let logo animation complete before typing begins +- prefers-reduced-motion: keeps original 400ms delay since logo renders instantly +- Fixed lint warning: added prefersReducedMotion to useEffect dependency array +- Files changed: src/components/LoginScreen.tsx, src/components/CvmisLogo.tsx +- **Learnings for future iterations:** + - CvmisLogo `size` prop is numeric (SVG height attribute) — use `cssHeight` string prop for CSS clamp values + - Logo animation is 1000ms total (500ms rise + 500ms fan-out) — typing delay must account for this + - The committed LoginScreen from US-003 still had Shield icon — US-003 only committed responsive sizing, not branding changes +--- + +## 2026-02-15 - US-003 +- Responsive card: width clamp(320px,28vw,480px), maxWidth calc(100vw-32px), padding clamp(24px,2.5vw,40px) +- Replaced hardcoded colors with CSS variables: --surface, --bg-dashboard, --accent, --text-secondary, --text-tertiary +- Input fields: #E4EDEB default border, var(--accent) focus border, var(--bg-dashboard) inactive bg +- Font sizes: labels clamp(12px,1vw,14px), inputs clamp(13px,1.1vw,15px), button clamp(14px,1.1vw,16px) +- Card shadow: 0 1px 2px rgba(26,43,42,0.05) matching project shadow tokens +- Files changed: src/components/LoginScreen.tsx +- **Learnings for future iterations:** + - No --border-card CSS variable exists in index.css — use #E4EDEB directly + - LoginScreen uses inline styles throughout, not Tailwind classes (except for focus-visible ring on button) + - The card used className="bg-white" which needed to be replaced with inline style for consistency +--- + +## 2026-02-15 - US-002 +- Created CvmisLogo.tsx component with inlined SVG paths from cvmis-logo.svg +- Three capsule groups: capsule-rx (teal #0b7979), capsule-terminal (amber #d97706), capsule-data (green #059669) +- Props: size (height px), animated (boolean, default false), className (optional) +- Framer Motion animation: Phase 1 (rise 500ms) — green data capsule scales from 0, Phase 2 (fan-out 500ms) — all three appear +- prefers-reduced-motion: skips animation, renders final state immediately +- Files changed: src/components/CvmisLogo.tsx (new) +- **Learnings for future iterations:** + - The SVG uses viewBox="0 0 600 506" with internal g transform scale(0.05,-0.05) — keep this coordinate system intact + - framer-motion's useReducedMotion() hook is the simplest way to handle reduced motion + - transform-origin in SVG needs px units when using framer-motion on g elements +--- + +## 2026-02-15 - US-001 +- Changed initial Phase state from 'boot' to 'login' in App.tsx line 47 +- Files changed: src/App.tsx +- **Learnings for future iterations:** + - Phase state is a simple string union type on line 47 of App.tsx + - US-010 will revert this exact change back to 'boot' +--- + diff --git a/src/components/CvmisLogo.tsx b/src/components/CvmisLogo.tsx index 90aec54..e3b21df 100644 --- a/src/components/CvmisLogo.tsx +++ b/src/components/CvmisLogo.tsx @@ -2,12 +2,13 @@ import { useEffect, useState } from 'react' import { motion, useReducedMotion } from 'framer-motion' interface CvmisLogoProps { - size: number + size?: number + cssHeight?: string animated?: boolean className?: string } -export function CvmisLogo({ size, animated = false, className }: CvmisLogoProps) { +export function CvmisLogo({ size, cssHeight, animated = false, className }: CvmisLogoProps) { const prefersReducedMotion = useReducedMotion() const [animationPhase, setAnimationPhase] = useState<'rise' | 'fan' | 'done'>( animated && !prefersReducedMotion ? 'rise' : 'done' @@ -34,11 +35,11 @@ export function CvmisLogo({ size, animated = false, className }: CvmisLogoProps) return ( {/* Capsule: Rx (Pharmacy) - Left — teal, tilts left in fan */} diff --git a/src/components/LoginScreen.tsx b/src/components/LoginScreen.tsx index a290a1c..d63bd87 100644 --- a/src/components/LoginScreen.tsx +++ b/src/components/LoginScreen.tsx @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback, useRef } from 'react' import { motion } from 'framer-motion' -import { Shield } from 'lucide-react' +import { CvmisLogo } from './CvmisLogo' import { useAccessibility } from '../contexts/AccessibilityContext' interface LoginScreenProps { @@ -118,10 +118,12 @@ export function LoginScreen({ onComplete }: LoginScreenProps) { setConnectionState('connected') }, 2000) - // Delay start slightly for card entrance animation + // Delay start to allow card entrance + logo animation to complete + // Reduced motion: logo shows instantly, so use original 400ms delay + // Full motion: 400ms card entrance + 1000ms logo animation + 100ms pause = 1500ms const startTimeout = addTimeout(() => { startLoginSequence() - }, 400) + }, prefersReducedMotion ? 400 : 1500) // Capture ref value for cleanup const pendingTimeouts = timeoutRefs.current @@ -134,7 +136,7 @@ export function LoginScreen({ onComplete }: LoginScreenProps) { clearTimeout(connectionTimeout) pendingTimeouts.forEach(id => clearTimeout(id)) } - }, [startLoginSequence, addTimeout]) + }, [startLoginSequence, addTimeout, prefersReducedMotion]) const buttonBg = buttonPressed ? '#085858' @@ -204,18 +206,10 @@ export function LoginScreen({ onComplete }: LoginScreenProps) { className="flex flex-col items-center" style={{ marginBottom: '28px' }} > -
- +
- CareerRecord PMR + CVMIS - Clinical Information System + CV Management Information System