# CardImage Component Documentation
## Overview
The CardImage component is a responsive card implementation following the XRPL Brand Design System (BDS). It displays an image, title, subtitle, and call-to-action button with three responsive size variants that adapt to viewport width.
## Features
- **Three Responsive Variants**: LG (≥992px), MD (576px-991px), SM (<576px)
- **Interactive States**: Default, Hover, Focus, Pressed, Disabled
- **Button Animation on Card Hover**: Hovering the card triggers the button's hover animation
- **Flexible Usage**: Supports both link navigation and click handlers
- **Accessibility**: Keyboard navigation and screen reader support
## Props API
```typescript
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;
}
```
### Default Values
- `disabled`: `false`
- `className`: `''`
## Responsive Variants
### LG (Large) - Desktop (≥992px)
- Card height: 620px
- Image height: 400px (1:1 aspect ratio preserved)
- 3-column grid width
### MD (Medium) - Tablet (576px - 991px)
- Card height: 560px
- Image height: 280px
- 2-column grid width
### SM (Small) - Mobile (<576px)
- Card height: 536px
- Image height: 268px
- 1-column grid width (full width)
## States
### Default State
The default interactive state with the button showing its primary green background.
### Hover State
When the user hovers over the card:
- Button background fills from bottom-to-top (green-300 → green-200)
- Arrow icon line shrinks
- Gap between label and icon increases
### Focus State
When the card receives keyboard focus:
- Black border outline around the card
- Button shows focus styling
### Pressed State
When the button is being pressed:
- Button returns to default styling momentarily
### Disabled State
When `disabled={true}`:
- Card is non-interactive
- Button shows disabled styling (gray background, no icon)
- Text colors muted
- Cursor changes to `not-allowed`
## Usage Examples
### Basic Card with Link
```tsx
import { CardImage } from 'shared/components/CardImage';
```
### Card with Click Handler
```tsx
console.log('clicked')}
/>
```
### Disabled Card
```tsx
```
### Card with Custom Class
```tsx
```
## Design Tokens
### Spacing
| Token | Value | Description |
|-------|-------|-------------|
| Image-to-content gap | 24px | Gap between image and content area |
| Title-to-subtitle gap | 12px | Gap between title and subtitle |
| Content horizontal padding | 8px | Left/right padding for content |
| Button margin-top | 30px | Button locked to bottom |
| Border radius | 16px | Card corner radius |
### Colors
| Element | Light Mode | Dark Mode |
|---------|------------|-----------|
| Card background | #FFFFFF | Gray 800 |
| Card border | Gray 300 (#CAD4DF) | Gray 700 |
| Image background | Gray 100 (#F0F3F7) | Gray 700 |
| Text color | #141414 | White |
### Typography
| Element | Token | Specs |
|---------|-------|-------|
| Title | `.sh-md-l` | 28px/35px, -0.5px letter-spacing, light weight |
| Subtitle | `.body-l` | 18px/26.1px, -0.5px letter-spacing, light weight |
## How It Works
### Hover Animation
The card tracks hover state via React's `useState`. When hovered:
1. A `bds-card-image--hovered` class is added to the card
2. CSS rules target the nested Button component and apply hover styles
3. The button's `::before` pseudo-element animates (background fill)
4. The arrow icon line shrinks via `scaleX(0)`
This approach ensures the button animation triggers even when hovering areas of the card outside the button itself.
### Link Navigation
When `href` is provided:
- The entire card becomes clickable
- Clicking anywhere on the card navigates to the href
- The card is keyboard accessible (Enter/Space to activate)
### Button Integration
The component uses the existing BDS Button component with:
- `variant="primary"` - Solid green background
- `color="green"` - Green color theme
## Accessibility
### Keyboard Navigation
- **Tab**: Focus the card
- **Enter/Space**: Activate the card (navigate to href or trigger onClick)
### Screen Reader Support
- Card has appropriate `role="link"` when href is provided
- Image has descriptive alt text
- `aria-disabled` attribute for disabled state
## File Structure
```
shared/components/CardImage/
├── CardImage.tsx # Component implementation
├── CardImage.scss # Component styles
├── CardImage.md # This documentation
└── index.ts # Exports
```
## Related Components
- **Button**: Used internally for the CTA button
- **CardOffgrid**: Similar card component with different layout
## Browser Support
The component uses modern CSS features:
- CSS Grid/Flexbox
- CSS transforms and transitions
- `:focus-visible` pseudo-class
- `-webkit-line-clamp` for text truncation
All features are widely supported in modern browsers.