コンテンツへスキップ
最終更新:

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

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). `\n` renders as a line break; an all-bullet subtitle renders as a list. */
  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;
}

Default Values

  • disabled: false
  • className: ''
  • fullBleed: false
  • backgroundColor: undefined (falls back to the gray-100 image background)

Subtitle Formatting

subtitle is a plain string, but it is not rendered blindly:

  • Lines are split on \n, and blank lines are dropped.
  • If every line begins with a bullet marker (•, -, or *), the subtitle renders as a <ul> (bds-card-image__subtitle--list) with one <li> per line.
  • Anything else renders as a single <p>, where white-space: pre-line means \n still produces a visible line break.
// Renders as a bulleted list
<CardImage subtitle={"• Fast settlement\n• Low fees\n• Built-in DEX"} ... />

// Renders as a paragraph with a line break
<CardImage subtitle={"Fast settlement.\nLow fees."} ... />

Image Sizing

By default the image sits in a fixed-height container against a gray-100 background, preserving its aspect ratio.

  • fullBleed — sets bds-card-image--full-bleed, which drops the card's fixed height (height: auto) and makes the image fill the container using a 1:1 aspect ratio with object-fit: cover. Use this when the image is the whole visual and you don't want letterboxing.
  • backgroundColor — sets the --bds-card-image-bg custom property on the image container, overriding the gray-100 default. Has no visible effect alongside fullBleed, since the image covers the container.
<CardImage fullBleed image="/images/hero.png" ... />
<CardImage backgroundColor="#F3F1EB" image="/images/logo.svg" ... />

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

import { CardImage } from 'shared/components/CardImage';

<CardImage
  image="/images/docs-hero.png"
  imageAlt="Documentation illustration"
  title="Documentation"
  subtitle="Access everything you need to get started working with the XRPL."
  buttonLabel="Get Started"
  href="/docs"
/>

Card with Click Handler

<CardImage
  image="/images/feature.png"
  imageAlt="Feature illustration"
  title="New Feature"
  subtitle="Learn about our latest feature and how it can help you build better applications."
  buttonLabel="Learn More"
  onClick={() => console.log('clicked')}
/>

Disabled Card

<CardImage
  image="/images/coming-soon.png"
  imageAlt="Coming soon"
  title="Coming Soon"
  subtitle="This feature is not yet available."
  buttonLabel="Unavailable"
  disabled
/>

Card with Custom Class

<CardImage
  image="/images/hero.png"
  imageAlt="Hero image"
  title="Custom Styled"
  subtitle="Card with additional custom styling."
  buttonLabel="Explore"
  href="/explore"
  className="my-custom-card"
/>

Design Tokens

Spacing

TokenValueDescription
Image-to-content gap24pxGap between image and content area
Title-to-subtitle gap12pxGap between title and subtitle
Content horizontal padding8pxLeft/right padding for content
Button margin-top30pxButton locked to bottom
Border radius16pxCard corner radius

Colors

ElementLight ModeDark Mode
Card background#FFFFFFGray 800
Card borderGray 300 (#CAD4DF)Gray 700
Image backgroundGray 100 (#F0F3F7)Gray 700
Text color#141414White

Typography

ElementTokenSpecs
Title.sh-md-l28px/35px, -0.5px letter-spacing, light weight
Subtitle.body-l18px/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.

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
  • 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.