A card component with a title at the top and description at the bottom. Used within the CardsTwoColumn pattern to display content in a 2×2 grid, but can also be used independently.
- 6 Color Variants: Green, neutral-light, neutral-dark, lilac, yellow, and blue backgrounds
- Window shade overlay: On desktop (≥992px), hover animates a bottom-up overlay; active (
:active) shows the pressed overlay color - Focus: Keyboard Tab (
:focus-visible) uses the same card surface as hover for neutral variants; mouse click (:focuswithout:focus-visible) keeps the default surface so that after release, hover still shows the overlay when the pointer is still over the card - Visited links (
<a>withhref): When a link has been visited, default card colors and a hidden overlay apply until hover or active (see Visited state); rules are scoped tohtml.lightandhtml.darkso neutrals match each theme - Tablet & mobile (
<992px): Overlay transition is off; hover / focus-visible jump to the pressed overlay (same idea as TileLogo). neutral-light uses$gray-400; neutral-dark uses$gray-500so the two grays stay distinct on tap - Responsive Design: Adapts height and padding across breakpoints
- Optional Link:
hrefrenders an<a>; otherwise an<article> - Flexible Content: Title and description support
ReactNode
import { TextCard } from 'shared/components/TextCard';
// Basic usage
<TextCard
title="Institutions"
description="Banks, asset managers, PSPs, and fintechs use XRPL to build financial products."
color="green"
/>
// As a clickable card
<TextCard
title="Developers"
description="Build decentralized applications with comprehensive documentation."
href="/developers"
color="lilac"
/>| Prop | Type | Default | Description |
|---|---|---|---|
title | ReactNode | required | Card title (heading-lg typography) |
description | ReactNode | - | Card description (body-l typography) |
href | string | - | Optional link URL (renders <a> instead of <article>) |
color | TextCardColor | 'neutral-light' | Background color variant |
disabled | boolean | false | Whether the card is disabled |
className | string | - | Additional CSS classes |
type TextCardColor = 'green' | 'neutral-light' | 'neutral-dark' | 'lilac' | 'yellow' | 'blue';| Breakpoint | Height | Padding |
|---|---|---|
| Desktop (≥992px) | 340px | 24px |
| Tablet (576–991px) | 309px | 20px |
| Mobile (<576px) | 274px | 16px |
- Default: Card background color from the variant; overlay is clipped off (shade “up”).
- Hover (desktop): Window shade reveals the hover overlay color (see tables below).
- Active (
:active): Overlay uses the pressed color; shade stays fully revealed while the pointer is down. - Keyboard focus (
:focus-visible): For neutral-light and neutral-dark, the card background matches the hover surface token; overlay behavior matches hover. Other variants keep the default card background; outline follows focus rules below. - Mouse focus (
:focuswithout:focus-visible): Neutral variants keep the default card background so releasing a click while still hovering does not paint the whole card as hover-only— the overlay continues to show hover via:hover. - Tablet / mobile (
max-widthbelowlg): No clip-path animation; hover/focus-visible shows the pressed overlay color immediately. Neutral-dark uses$gray-500on tap; neutral-light uses$gray-400.
For linked cards (href set), after the URL is visited:
- Light theme (
html.light):avisited styles reset to the light-mode default background for that variant and hide the overlay until:hoveror:active. - Dark theme (
html.dark): Same idea with dark-mode default surfaces (e.g. neutral-light$gray-300, neutral-dark$gray-400).
Implementation: TextCard.scss — visited rules live only under html.light { … } and html.dark { … } so neutral grays never mix themes.
Colors below refer to the card default background, overlay fill (hover / focus ring of the shade), and pressed overlay. The overlay is the animated layer; default column is the base card color.
| Variant | Default | Hover (overlay) | Focus keyboard (neutral) / overlay others | Pressed (overlay) |
|---|---|---|---|---|
green | $green-200 (#70EE97) | $green-300 (#21E46B) | $green-300 | $green-400 (#0DAA3E) |
neutral-light | $gray-200 (#E6EAF0) | $gray-300 (#CAD4DF) | Card bg $gray-300 | $gray-400 (#8A919A) |
neutral-dark | $gray-300 (#CAD4DF) | $gray-200 (#E6EAF0) | Card bg $gray-200 | $gray-400 (#8A919A) |
lilac | $lilac-200 (#D9CAFF) | $lilac-300 (#C0A7FF) | $lilac-300 | $lilac-400 (#7649E3) |
yellow | $yellow-100 (#F3F1EB) | $yellow-200 (#E6F1A7) | $yellow-200 | $yellow-300 (#DBF15E) |
blue | $blue-100 (#EDF4FF) | $blue-200 (#93BFF1) | $blue-200 | $blue-300 (#428CFF) |
| Variant | Default | Hover (overlay) | Focus keyboard (neutral) / overlay others | Pressed (overlay) |
|---|---|---|---|---|
green | $green-200 (#70EE97) | $green-300 (#21E46B) | $green-300 | $green-400 (#0DAA3E) |
neutral-light | $gray-300 (#CAD4DF) | $gray-200 (#E6EAF0) | Card bg $gray-200 | $gray-400 (#8A919A) |
neutral-dark | $gray-400 (#8A919A) | $gray-300 (#CAD4DF) | Card bg $gray-300 | $gray-500 (#72777E) |
lilac | $lilac-200 (#D9CAFF) | $lilac-300 (#C0A7FF) | $lilac-300 | $lilac-400 (#7649E3) |
yellow | $yellow-100 (#F3F1EB) | $yellow-200 (#E6F1A7) | $yellow-200 | $yellow-300 (#DBF15E) |
blue | $blue-100 (#EDF4FF) | $blue-200 (#93BFF1) | $blue-200 | $blue-300 (#428CFF) |
| Mode | Background | Text |
|---|---|---|
| Light | $gray-100 (#F0F3F7) | $gray-500 (#72777E) |
| Dark | rgba($gray-500, 0.3) | Default text color |
| Mode | Focus Outline |
|---|---|
| Light Mode | 2px solid black outline with 2px offset |
| Dark Mode | 2px solid white outline with 2px offset |
.bds-text-card // Base card container
.bds-text-card--green // Green variant
.bds-text-card--neutral-light // Neutral light variant
.bds-text-card--neutral-dark // Neutral dark variant
.bds-text-card--lilac // Lilac variant
.bds-text-card--yellow // Yellow variant
.bds-text-card--blue // Blue variant
.bds-text-card--disabled // Disabled modifier
.bds-text-card__overlay // Window shade overlay
.bds-text-card__title // Title (h3)
.bds-text-card__description // Description (p)Title: Uses
h-lgclass (heading-lg, Tobias Light font)- Desktop: 48px / 52.8px line-height
- Tablet: 42px / 46.2px line-height
- Mobile: 36px / 39.6px line-height
Description: Uses
body-lclass (Booton Light font)- All breakpoints: 18px / 26.1px line-height
- Max width: 478px (from Figma)
<TextCard title="Green" description="$green-200" color="green" />
<TextCard title="Neutral Light" description="$gray-200" color="neutral-light" />
<TextCard title="Neutral Dark" description="$gray-300" color="neutral-dark" />
<TextCard title="Lilac" description="$lilac-200" color="lilac" />
<TextCard title="Yellow" description="$yellow-100" color="yellow" />
<TextCard title="Blue" description="$blue-100" color="blue" /><TextCard
title="Disabled Card"
description="This card is disabled and cannot be interacted with."
color="neutral-light"
disabled
/>import { CardsTwoColumn } from 'shared/sections/CardsTwoColumn';
<CardsTwoColumn
title="Section Title"
description="Section description text."
cards={[
{ title: "Card 1", description: "Description 1", color: "lilac" },
{ title: "Card 2", description: "Description 2", color: "neutral-light" },
{ title: "Card 3", description: "Description 3", color: "neutral-dark" },
{ title: "Card 4", description: "Description 4", color: "green" }
]}
/>TextCard.tsx- Component implementationTextCard.scss- Styles (variants,html.light/html.dark, visited, breakpoint behavior)index.ts- Barrel exportsTextCard.md- This documentation
- CardsTwoColumn: Pattern that uses TextCard in a 2×2 grid (
shared/sections/CardsTwoColumn)
- Figma Design: Section Cards - Two Column
- Showcase:
/showcase/cards-two-column(seeshowcase/cards-two-column.page.tsx) - Component Location:
shared/components/TextCard/