import { useState, useEffect, useRef } from "react"; import { motion } from "motion/react"; import { Users, Settings, User, Globe, MessageSquare, GraduationCap, TrendingUp, Building, ArrowRight } from "lucide-react"; import { BrandedTag } from "./about/BrandedTag"; import { StandardCTAButton } from "./StandardCTAButton"; import { navigateTo } from "./Router"; import { ImageWithFallback } from "./figma/ImageWithFallback"; interface HighlightCard { card_title: string; icon_url: string; accessible_label: string; body_text: string; display_order: number; } interface ServicesSectionProps { highlightCards?: HighlightCard[]; isLoading?: boolean; } export function ServicesSection({ highlightCards = [], isLoading = false }: ServicesSectionProps) { const [isVisible, setIsVisible] = useState(false); const cardRefs = useRef<(HTMLDivElement | null)[]>([]); const sectionRef = useRef(null); // Create service items from highlightCards data const serviceItems = highlightCards.map((card, index) => ({ id: index + 1, title: card.card_title, description: card.body_text, iconUrl: card.icon_url, accessibleLabel: card.accessible_label, route: '/services' // You might want to map to specific routes based on title })); // Add card refs helper const addCardRef = (el: HTMLDivElement | null, index: number) => { cardRefs.current[index] = el; }; // Intersection observer for animations useEffect(() => { const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { setIsVisible(true); } }); }, { threshold: 0.2 } ); if (sectionRef.current) { observer.observe(sectionRef.current); } return () => observer.disconnect(); }, []); // Keyboard navigation const handleKeyDown = (e: React.KeyboardEvent, index: number) => { if (e.key === 'ArrowDown' && index < cardRefs.current.length - 1) { cardRefs.current[index + 1]?.focus(); e.preventDefault(); } else if (e.key === 'ArrowUp' && index > 0) { cardRefs.current[index - 1]?.focus(); e.preventDefault(); } }; // Show loading skeleton if isLoading is true if (isLoading) { return (
{[1, 2, 3, 4].map((i) => (
))}
); } return (
{/* Desktop Layout - Grid with Sticky Sidebar */}
{/* Left Side - Sticky Content */}

Shaping Leaders, Cultures, and Institutions

No two institutions are alike — and neither are their leadership needs. That's why every KLC service is rooted in research, tailored to context, and aligned with strategy. From shaping leaders and managers to shaping culture, developing talent frameworks, and offering practical high impact learning, we partner with you to create leadership solutions that deliver lasting value.

{/* CTA Button - Left aligned */}
navigateTo('/services')} ariaLabel="Explore our services" />
{/* Right Side - Scrolling Cards */}
{serviceItems.map((item, index) => (
addCardRef(el, index)} className={`recognition-card group scroll-animate-stagger cursor-pointer focus-ring ${isVisible ? 'animate-in' : ''}`} role="listitem" aria-labelledby={`recognition-title-${item.id}`} aria-describedby={`recognition-desc-${item.id}`} tabIndex={0} onKeyDown={(e) => handleKeyDown(e, index)} style={{ transitionDelay: `${(index + 1) * 150}ms`, opacity: isVisible ? 1 : 0 }} onClick={() => navigateTo(item.route)} >
{/* Image icon from icon_url */} {item.accessibleLabel { // Fallback if image fails to load e.currentTarget.style.display = 'none'; // You could add a fallback icon here if needed }} />

{item.title}

{item.description}

))}
{/* Mobile Layout - Stacked Header + Horizontal Scrollable Cards */}
{/* Mobile Header */}

Shaping Leaders, Cultures, and Institutions

No two institutions are alike — and neither are their leadership needs. That's why every KLC service is rooted in research, tailored to context, and aligned with strategy. From shaping leaders and managers to shaping culture, developing talent frameworks, and offering practical high impact learning, we partner with you to create leadership solutions that deliver lasting value.

{/* CTA Button - Left aligned for mobile */}
navigateTo('/services')} ariaLabel="Explore our services" />
{/* Mobile Horizontal Scrollable Cards */}
{serviceItems.map((item, index) => (
handleKeyDown(e, index)} style={{ scrollSnapAlign: 'start', width: '320px', transitionDelay: `${(index + 1) * 150}ms`, opacity: isVisible ? 1 : 0 }} >

{item.title}

{item.description}

))}
); }