import React, { useState, useCallback } from 'react'; import clsx from 'clsx'; import { Button } from '../Button'; export interface CardImageProps { /** Image source URL */ image: string; /** Alt text for the image */ imageAlt: string; /** Card title (1 line only) */ title: string; /** Card subtitle (max 3 lines) */ subtitle: string; /** Button label text */ buttonLabel: string; /** Link destination (renders card as clickable link) */ href?: string; /** Click handler for the button */ onClick?: () => void; /** Disabled state */ disabled?: boolean; /** Optional className for custom styling */ className?: string; /** When true, image fills entire container with object-fit: cover (no visible background) */ fullBleed?: boolean; /** Custom background color for image container (defaults to gray-100) */ backgroundColor?: string; } /** * BDS CardImage Component * * A responsive card component displaying an image, title, subtitle, and CTA button. * Features three responsive size variants (LG/MD/SM) that adapt to viewport width. * * Key behaviors: * - Hovering the card triggers the button's hover animation * - Card can link to a URL or trigger a click handler * - Supports disabled state * * @example * // Basic card with link * * * @example * // Card with click handler * console.log('clicked')} * /> */ export const CardImage: React.FC = ({ image, imageAlt, title, subtitle, buttonLabel, href, onClick, disabled = false, className = '', fullBleed = false, backgroundColor, }) => { // Track hover state for button animation const [isHovered, setIsHovered] = useState(false); const handleMouseEnter = useCallback(() => { if (!disabled) { setIsHovered(true); } }, [disabled]); const handleMouseLeave = useCallback(() => { if (!disabled) { setIsHovered(false); } }, [disabled]); // Build class names using BEM with bds namespace const classNames = clsx( 'bds-card-image', disabled && 'bds-card-image--disabled', isHovered && 'bds-card-image--hovered', fullBleed && 'bds-card-image--full-bleed', className ); // Handle card click for linked cards const handleCardClick = useCallback( (e: React.MouseEvent) => { // If clicking the button directly, don't navigate via card if ((e.target as HTMLElement).closest('.bds-btn')) { return; } if (href && !disabled) { window.location.href = href; } }, [href, disabled] ); // Handle button click const handleButtonClick = useCallback(() => { if (href) { window.location.href = href; } else if (onClick) { onClick(); } }, [href, onClick]); // Build inline style for image container background color const imageContainerStyle = backgroundColor ? { '--bds-card-image-bg': backgroundColor } as React.CSSProperties : undefined; // Common content structure const content = ( <> {/* Image container with customizable background */}
{imageAlt}
{/* Content area: title, subtitle, and button */}

{title}

{subtitle}

); // Render as clickable div (card itself handles navigation) return (
{ if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); window.location.href = href; } } : undefined } aria-disabled={disabled} > {content}
); }; export default CardImage;