From f28693b0adc11eeaf0eb04fa5e07ac018cc4781c Mon Sep 17 00:00:00 2001 From: Andy Charlwood Date: Sun, 15 Feb 2026 01:47:44 +0000 Subject: [PATCH] feat: US-002 - Create CvmisLogo React SVG component --- src/components/CvmisLogo.tsx | 109 +++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/components/CvmisLogo.tsx diff --git a/src/components/CvmisLogo.tsx b/src/components/CvmisLogo.tsx new file mode 100644 index 0000000..90aec54 --- /dev/null +++ b/src/components/CvmisLogo.tsx @@ -0,0 +1,109 @@ +import { useEffect, useState } from 'react' +import { motion, useReducedMotion } from 'framer-motion' + +interface CvmisLogoProps { + size: number + animated?: boolean + className?: string +} + +export function CvmisLogo({ size, animated = false, className }: CvmisLogoProps) { + const prefersReducedMotion = useReducedMotion() + const [animationPhase, setAnimationPhase] = useState<'rise' | 'fan' | 'done'>( + animated && !prefersReducedMotion ? 'rise' : 'done' + ) + + useEffect(() => { + if (!animated || prefersReducedMotion) return + + const riseTimer = setTimeout(() => setAnimationPhase('fan'), 500) + const fanTimer = setTimeout(() => setAnimationPhase('done'), 1000) + + return () => { + clearTimeout(riseTimer) + clearTimeout(fanTimer) + } + }, [animated, prefersReducedMotion]) + + const skipAnimation = !animated || prefersReducedMotion + const showAll = animationPhase === 'fan' || animationPhase === 'done' + + // The original SVG viewBox is 600pt x 506pt with an internal transform of + // scale(0.05, -0.05) translate(0, 506). We keep the original coordinate + // system and let the outer viewBox handle scaling. + return ( + + + {/* Capsule: Rx (Pharmacy) - Left — teal, tilts left in fan */} + + + + + + {/* Capsule: Terminal (Code) - Centre — amber, stays upright */} + + + + + {/* Capsule: Data (Analytics) - Right — green, the "rising" capsule */} + + + + + + ) +}