mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2026-09-27 23:47:59 +00:00
* BDS component polish: link visibility, static cards, uniform CTAs Component-level fixes and refinements across the 2026 brand components. Accessibility / contrast - StandardCard: pin description link colors. Every card variant has a light background in both themes, so theme-level link colors were wrong inside it — dark mode painted plain anchors white and BdsLink lilac-300, both of which wash out on a pale card. Links (including :visited) now use the card's own text color with an underline carrying the affordance; hover uses lilac-500, which clears 4.5:1 on all four card backgrounds. - Breadcrumbs: point the open dropdown menu at the breadcrumb color tokens so the trail, trigger, and menu read as one color in both themes, and give dark mode gray-6 (7.41:1, matching light mode's 7.23:1). Interaction - CardOffgrid: drop every hover affordance when a card has neither href nor onClick. Static cards no longer get a pointer cursor, the color-wipe overlay, or a pressed state — the tokenization and trading carousels pass link-less cards and were advertising a click target that did not exist. - CarouselFeatured: add a 'fade' transition alongside the default 'slide', for decks whose slides share a heading. Inactive slides are now inert, keeping focus and pointer events out of them in both styles. - Add a bds-reduced-motion mixin so components can collapse motion to an instant state change. Design consistency - ButtonGroup: add forceVariant and forceNoPadding overrides, letting a section opt out of the count-based variant defaults and render one uniform treatment. Existing consumers are unaffected. - FeatureTwoColumn: render every link as a tertiary button regardless of count, flush with the title and description. - CardImage: render an all-bullet subtitle as a real <ul> so wrapped text hangs under the first character and screen readers announce it as a list. - docs: give the node-installation card descriptions a paragraph break before their "Learn More" link. Dependencies - Bump @codemirror/state and view, add lang-javascript, lang-json, and lint, with overrides pinning state/view to one copy. Docs updated alongside each component. Built CSS regenerated with the production script to match the committed artifact's minified format. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * ButtonGroup: don't strip padding from forced filled variants `noPadding` was derived as `forceNoPadding || isMultiButton`, which was safe while the 3+ block layout was always tertiary. `forceVariant` also accepts `primary` and `secondary`, so a 3-button group forcing a filled variant had `padding: 0 !important` (Button.scss) applied with no way to opt out. Tie the implied no-padding to the resolved variant being tertiary. Behavior is unchanged for every caller that doesn't pass `forceVariant`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Stacked hero variant, fade-by-default carousel, component docs Layout - HeaderHeroPrimaryMedia: add a `stacked` prop that puts the headline, subtitle, and buttons in one column (full width at base, 7/8 at md, 9/12 at lg) instead of the default headline-left / CTA-right split. The headline and CTA block bottom-align against each other in the two-column layout, so the stacked variant undoes that. Both arrangements now share the same headline and CTA elements, so they can't drift apart. Used on the docs landing hero. Motion - CarouselFeatured: make `fade` the default transition. Slides that share a heading are the common case, and a horizontal wipe drags the identical heading across the screen only to set it back down. `slide` is now opt-in for decks whose panels are genuinely distinct. Nudge the crossfade to 260ms in / 200ms out. The home page carousel opts into fade explicitly; developer-funding now inherits it. Fixes - CardTextIconCard: pass `headingAs` through to `cardContent`, which was accepting the prop but never receiving it. Docs - Expand the Button, CardImage, CardTextIcon, PageGrid, CalloutMediaBanner, LogoSquareGrid, and HeaderHeroPrimaryMedia references. Built CSS regenerated with the production script. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
161 lines
5.1 KiB
Markdown
161 lines
5.1 KiB
Markdown
# CardTextIconCard Component
|
||
|
||
A card component featuring an icon, heading, and description. Built from Section Cards - Icon and Section Cards - Text Grid Figma designs.
|
||
|
||
## Overview
|
||
|
||
CardTextIconCard displays an icon at the top, followed by a heading and description. The description accepts `ReactNode`, so it can include hyperlinks and other rich content. No buttons; links are inline within the description.
|
||
|
||
## Features
|
||
|
||
- **Icon + Text Layout**: Icon container, heading, and description in a vertical stack (optional)
|
||
- **Rich Description**: `description` accepts `ReactNode` for inline links and formatted content
|
||
- **Aspect Ratio Foundation**: Optional `aspectRatio` prop for future responsive sizing
|
||
- **Light/Dark Mode**: Full theming support
|
||
- **Responsive Design**: Adaptive icon size and spacing across breakpoints
|
||
|
||
## Usage
|
||
|
||
### Basic Usage
|
||
|
||
```tsx
|
||
<CardTextIconCard
|
||
icon="/icons/docs.svg"
|
||
iconAlt="Documentation"
|
||
heading="Documentation"
|
||
description="Access everything you need to get started with the XRPL."
|
||
/>
|
||
```
|
||
|
||
### With Inline Link in Description
|
||
|
||
```tsx
|
||
<CardTextIconCard
|
||
icon="/icons/docs.svg"
|
||
heading="Documentation"
|
||
description={
|
||
<>
|
||
Learn more in our{' '}
|
||
<a href="/docs">documentation</a>.
|
||
</>
|
||
}
|
||
/>
|
||
```
|
||
|
||
Inline `<a>` tags in the description share the card’s description styles in `CardTextIconCard.scss`. In **light** mode, global `html.light` link rules can compete with those styles; use **`BdsLink`** with the design-system `bds-link` class if you need consistent BDS link behavior, or see `CardTextIconCard.scss` for `.bds-card-text-icon-card__description` link styling.
|
||
|
||
### With Aspect Ratio
|
||
|
||
```tsx
|
||
<CardTextIconCard
|
||
icon="/icons/docs.svg"
|
||
heading="Documentation"
|
||
description="Access everything you need."
|
||
aspectRatio={4 / 3}
|
||
/>
|
||
```
|
||
|
||
## Props
|
||
|
||
### CardTextIconCardProps
|
||
|
||
| Prop | Type | Default | Description |
|
||
|------|------|---------|-------------|
|
||
| `icon` | `string` | - | Icon image URL |
|
||
| `iconAlt` | `string` | `''` | Alt text for the icon image |
|
||
| `heading` | `string` | Required | Card heading |
|
||
| `headingAs` | `'h1'`–`'h6'` | `'h3'` | Semantic heading element, so cards enter the document outline. Use a level that fits the page hierarchy (typically one below the section heading). |
|
||
| `description` | `React.ReactNode` | Required | Card description; accepts rich content (e.g., text with inline links) |
|
||
| `aspectRatio` | `number` | - | Optional ratio for future use; applied via CSS variable |
|
||
| `gridColSpan` | `ResponsiveValue<PageGridSpanValue>` | - | When provided, the card renders as `PageGrid.Col as="li"` with this span, becoming the grid column itself. See [Grid integration](#grid-integration). |
|
||
| `height` | `number` | - | Explicit `height` attribute for the icon image |
|
||
| `width` | `number` | - | Explicit `width` attribute for the icon image |
|
||
| `className` | `string` | - | Additional CSS classes |
|
||
|
||
## Grid integration
|
||
|
||
The card has two rendering modes:
|
||
|
||
- **Standalone (default)** — renders a plain `<div class="bds-card-text-icon-card">`.
|
||
Use this when you're placing the card inside your own layout.
|
||
- **Grid column** — when `gridColSpan` is provided, the card renders as
|
||
`PageGrid.Col as="li"` with the modifier class
|
||
`bds-card-text-icon-card--grid-col`. The card *is* the grid column, so it must
|
||
sit inside a `PageGrid.Row as="ul"`.
|
||
|
||
This is how [CardsTextGrid](../../sections/CardsTextGrid/README.md) and
|
||
[CardsIconGrid](../../sections/CardsIconGrid/README.md) consume it — both pass
|
||
`gridColSpan={{ base: 4, md: 4, lg: 6 }}`.
|
||
|
||
```tsx
|
||
<PageGrid.Row as="ul">
|
||
<CardTextIconCard
|
||
heading="Documentation"
|
||
description="Access everything you need."
|
||
gridColSpan={{ base: 4, md: 4, lg: 6 }}
|
||
/>
|
||
</PageGrid.Row>
|
||
```
|
||
|
||
### Heading levels
|
||
|
||
`headingAs` defaults to `'h3'`. Because these cards are usually rendered under a
|
||
section heading, set it explicitly when `h3` would skip a level:
|
||
|
||
```tsx
|
||
<CardTextIconCard
|
||
heading="Documentation"
|
||
headingAs="h4"
|
||
description="Access everything you need."
|
||
/>
|
||
```
|
||
|
||
## Component Structure
|
||
|
||
```tsx
|
||
<>
|
||
<div className="bds-card-text-icon-card__icon">
|
||
{icon && (
|
||
<img
|
||
src={icon}
|
||
alt={iconAlt}
|
||
{...(iconHeight != null && { height: iconHeight })}
|
||
{...(iconWidth != null && { width: iconWidth })}
|
||
className="bds-card-text-icon-card__icon-img"
|
||
/>
|
||
)}
|
||
<strong className="bds-card-text-icon-card__heading sh-md-r">{heading}</strong>
|
||
</div>
|
||
<p className="bds-card-text-icon-card__description body-l">
|
||
{description}
|
||
</p>
|
||
</>
|
||
```
|
||
|
||
## Responsive Sizing
|
||
|
||
| Breakpoint | Icon Size | Padding | Gap |
|
||
|------------|-----------|---------|-----|
|
||
| Base (< 576px) | 32px | 16px | 16px |
|
||
| MD (576px - 991px) | 36px | 20px | 20px |
|
||
| LG (≥ 992px) | 40px | 32px | 24px |
|
||
|
||
## Files
|
||
|
||
- `CardTextIconCard.tsx` - React component with TypeScript
|
||
- `CardTextIconCard.scss` - Styles with BEM naming
|
||
- `index.ts` - Barrel exports
|
||
- `README.md` - This file
|
||
|
||
## Import
|
||
|
||
```tsx
|
||
import { CardTextIconCard } from 'shared/components/CardTextIcon';
|
||
// or
|
||
import { CardTextIconCard, type CardTextIconCardProps } from 'shared/components/CardTextIcon';
|
||
```
|
||
|
||
## Design System
|
||
|
||
Part of the Brand Design System (BDS) with `bds-` namespace prefix.
|