mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2026-07-30 18:40:19 +00:00
* adding showcase page * adding CardStatsList * clean up, tighter code * code review and code clean up * update import, clean up env for error message * tweak some css code * less css, rebuilt * re-adding bem, modifier for bds variants
308 lines
9.0 KiB
Markdown
308 lines
9.0 KiB
Markdown
# LinkTextDirectory Component
|
|
|
|
A section pattern that displays a numbered list of LinkTextCard components with a heading and optional description.
|
|
|
|
## Overview
|
|
|
|
LinkTextDirectory is a section-level pattern that combines a header (heading + description) with a vertically stacked list of LinkTextCard components. Each card is automatically numbered sequentially (01, 02, 03...), making it perfect for feature lists, step-by-step guides, or numbered content sections.
|
|
|
|
## Features
|
|
|
|
- **Automatic Numbering**: Cards are numbered sequentially starting from 01
|
|
- **Responsive Layout**: Adaptive spacing and alignment across breakpoints
|
|
- **Desktop Right-Alignment**: Cards are right-aligned on desktop for visual interest
|
|
- **Minimal HTML Structure**: Flat, efficient DOM hierarchy
|
|
- **Light/Dark Mode**: Full theming support
|
|
- **Flexible Content**: Supports any number of cards
|
|
|
|
## Layout Behavior
|
|
|
|
| Breakpoint | Card Alignment | Gap Between Cards | Header Gap |
|
|
|------------|----------------|-------------------|------------|
|
|
| Base (< 576px) | Left | 24px | 8px |
|
|
| MD (576px - 991px) | Left | 32px | 8px |
|
|
| LG (≥ 992px) | Right | 40px | 16px |
|
|
|
|
**Desktop Behavior**: Cards are right-aligned using `align-items: flex-end`, creating a visually distinct layout compared to mobile/tablet.
|
|
|
|
## Usage
|
|
|
|
### Basic Usage
|
|
|
|
```tsx
|
|
<LinkTextDirectory
|
|
heading="Explore XRPL Developer Tools"
|
|
description="XRP Ledger is a compliance-focused blockchain where financial applications come to life"
|
|
cards={[
|
|
{
|
|
heading: "Fast Settlement and Low Fees",
|
|
description: "Settle transactions in 3-5 seconds for a fraction of a cent, ideal for large-scale, high-volume RWA tokenization",
|
|
buttons: [
|
|
{ label: "Get Started", href: "/start" },
|
|
{ label: "Learn More", href: "/docs" }
|
|
]
|
|
},
|
|
{
|
|
heading: "Secure and Reliable",
|
|
description: "Built on proven blockchain technology with enterprise-grade security",
|
|
buttons: [
|
|
{ label: "Read Documentation", href: "/docs" }
|
|
]
|
|
},
|
|
{
|
|
heading: "Developer Friendly",
|
|
description: "Comprehensive APIs and SDKs for seamless integration",
|
|
buttons: [
|
|
{ label: "View API", href: "/api" },
|
|
{ label: "See Examples", href: "/examples" }
|
|
]
|
|
}
|
|
]}
|
|
/>
|
|
```
|
|
|
|
### Without Description
|
|
|
|
```tsx
|
|
<LinkTextDirectory
|
|
heading="Key Features"
|
|
cards={featuresList}
|
|
/>
|
|
```
|
|
|
|
### With Dynamic Data
|
|
|
|
```tsx
|
|
const features = [
|
|
{
|
|
heading: "Feature One",
|
|
description: "Description for feature one",
|
|
buttons: [{ label: "Learn More", href: "/feature-1" }]
|
|
},
|
|
// ... more features
|
|
];
|
|
|
|
<LinkTextDirectory
|
|
heading="Platform Features"
|
|
description="Everything you need to build amazing applications"
|
|
cards={features}
|
|
/>
|
|
```
|
|
|
|
## Props
|
|
|
|
### LinkTextDirectoryProps
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `heading` | `string` | Required | Section heading |
|
|
| `description` | `string` | - | Optional description text |
|
|
| `cards` | `LinkTextCardData[]` | Required | Array of card data |
|
|
| `className` | `string` | - | Additional CSS classes |
|
|
|
|
### LinkTextCardData
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `heading` | `string` | Required | Card heading |
|
|
| `description` | `string` | Required | Card description |
|
|
| `buttons` | `ButtonConfig[]` | Required | Array of button configs (max 2) |
|
|
|
|
### ButtonConfig (from ButtonGroup)
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `label` | `string` | Required | Button text |
|
|
| `href` | `string` | - | Link destination |
|
|
| `onClick` | `() => void` | - | Click handler |
|
|
|
|
## Component Structure
|
|
|
|
```tsx
|
|
<PageGrid className="bds-link-text-directory">
|
|
<PageGridRow>
|
|
<PageGridCol className="bds-link-text-directory__header" span={{ base: 12, md: 6, lg: 8 }}>
|
|
<h2 className="h-md">{heading}</h2>
|
|
<p className="body-l">{description}</p>
|
|
</PageGridCol>
|
|
</PageGridRow>
|
|
|
|
<PageGridRow>
|
|
<PageGridCol span={{ base: 12, md: 8, lg: 8 }} offset={{ lg: 4 }}>
|
|
<ul>
|
|
{cards.map((card, index) => (
|
|
<LinkTextCard
|
|
key={index}
|
|
index={index}
|
|
heading={card.heading}
|
|
description={card.description}
|
|
buttons={card.buttons}
|
|
/>
|
|
))}
|
|
</ul>
|
|
</PageGridCol>
|
|
</PageGridRow>
|
|
</PageGrid>
|
|
```
|
|
|
|
**Key Design Decisions:**
|
|
- **PageGrid Integration**: Uses PageGrid system for responsive layout
|
|
- **Typography Classes**: Uses existing `h-md` and `body-l` utility classes
|
|
- **Flexbox Header**: Header uses flexbox with gap for spacing between heading and description
|
|
- **Desktop Right-Alignment**: Cards offset by 4 columns at LG breakpoint (right-aligned)
|
|
- **Semantic List**: Cards wrapped in `<ul>` with each card as `<li>`
|
|
|
|
## Responsive Spacing
|
|
|
|
| Breakpoint | Section Padding | Header Gap | Header Margin-Bottom |
|
|
|------------|-----------------|------------|----------------------|
|
|
| Base (< 576px) | 24px | 8px | 24px |
|
|
| MD (576px - 991px) | 32px | 8px | 32px |
|
|
| LG (≥ 992px) | 40px | 16px | 40px |
|
|
|
|
**Section Padding**: Top and bottom padding on the entire section
|
|
**Header Gap**: Space between heading and description (via flexbox gap)
|
|
**Header Margin-Bottom**: Space between header and cards list
|
|
|
|
## Styling
|
|
|
|
### CSS Classes
|
|
|
|
- `.bds-link-text-directory` - Main PageGrid container with section padding
|
|
- `.bds-link-text-directory__header` - Header section (flexbox column with gap)
|
|
|
|
### Typography
|
|
|
|
- **Heading**: `h-md` class (responsive heading)
|
|
- **Description**: `body-l` class (large body text)
|
|
- Card content uses LinkTextCard's built-in typography
|
|
|
|
### Grid Layout
|
|
|
|
- **Header Column**: `span={{ base: 12, md: 6, lg: 8 }}`
|
|
- **Cards Column**: `span={{ base: 12, md: 8, lg: 8 }}` with `offset={{ lg: 4 }}`
|
|
- Cards are right-aligned on desktop via the 4-column offset
|
|
|
|
### Dark Mode
|
|
|
|
- Text color changes to white in dark mode
|
|
- Applied to entire section via `bds-theme-mode(dark)` mixin
|
|
|
|
## Card Numbering
|
|
|
|
Cards are automatically numbered based on their array index:
|
|
|
|
```typescript
|
|
cards[0] → LinkTextCard(index: 0) → displays "01"
|
|
cards[1] → LinkTextCard(index: 1) → displays "02"
|
|
cards[2] → LinkTextCard(index: 2) → displays "03"
|
|
// ... and so on
|
|
```
|
|
|
|
## Files
|
|
|
|
- `LinkTextDirectory.tsx` - React component
|
|
- `LinkTextDirectory.scss` - SCSS styles
|
|
- `index.ts` - Barrel exports
|
|
- `README.md` - This file
|
|
|
|
## Related Components
|
|
|
|
- **LinkTextCard**: Used for each card in the list
|
|
- **ButtonGroup**: Used by LinkTextCard for action buttons
|
|
|
|
## Import
|
|
|
|
```tsx
|
|
import { LinkTextDirectory } from 'shared/sections/LinkTextDirectory';
|
|
// or
|
|
import {
|
|
LinkTextDirectory,
|
|
type LinkTextDirectoryProps,
|
|
type LinkTextCardData
|
|
} from 'shared/sections/LinkTextDirectory';
|
|
```
|
|
|
|
## Design System
|
|
|
|
Part of the Brand Design System (BDS) with `bds-` namespace prefix.
|
|
|
|
## Best Practices
|
|
|
|
1. **Consistent Card Content**: Try to keep similar text lengths across cards for visual balance
|
|
2. **Limit Cards**: 3-6 cards works best for readability
|
|
3. **Clear Descriptions**: Keep descriptions concise but informative
|
|
4. **Button Labels**: Use clear, action-oriented button labels
|
|
5. **Logical Ordering**: Order cards by priority or logical sequence
|
|
|
|
## Accessibility
|
|
|
|
- Semantic HTML with proper heading hierarchy (`<h2>` for section, `<h5>` for cards)
|
|
- Semantic list structure: `<ul>` containing `<li>` elements
|
|
- Sequential tab order through cards and buttons
|
|
- ARIA-compliant button and link elements (via ButtonGroup)
|
|
- Maintains focus order: heading → description → card 1 → card 2 → etc.
|
|
|
|
## Best Practices for React Keys
|
|
|
|
When mapping over cards, use a stable identifier instead of array index:
|
|
|
|
```tsx
|
|
// ❌ Avoid using index as key
|
|
{cards.map((card, index) => (
|
|
<LinkTextCard key={index} ... />
|
|
))}
|
|
|
|
// ✅ Better: Use a unique identifier
|
|
{cards.map((card, index) => (
|
|
<LinkTextCard key={card.id || card.heading} ... />
|
|
))}
|
|
|
|
// ✅ Best: Add an id field to LinkTextCardData
|
|
interface LinkTextCardData {
|
|
id: string; // Unique identifier
|
|
heading: string;
|
|
description: string;
|
|
buttons: ButtonConfig[];
|
|
}
|
|
|
|
{cards.map((card) => (
|
|
<LinkTextCard key={card.id} ... />
|
|
))}
|
|
```
|
|
|
|
## Example with All Features
|
|
|
|
```tsx
|
|
<LinkTextDirectory
|
|
heading="Why Choose XRPL"
|
|
description="The most efficient blockchain for real-world applications"
|
|
cards={[
|
|
{
|
|
heading: "Lightning Fast",
|
|
description: "Process thousands of transactions per second with sub-3-second finality",
|
|
buttons: [
|
|
{ label: "View Benchmarks", href: "/performance" },
|
|
{ label: "Try Demo", onClick: () => openDemo() }
|
|
]
|
|
},
|
|
{
|
|
heading: "Cost Effective",
|
|
description: "Minimal transaction fees make XRPL perfect for micro-transactions and high-volume use cases",
|
|
buttons: [
|
|
{ label: "See Pricing", href: "/pricing" }
|
|
]
|
|
},
|
|
{
|
|
heading: "Battle Tested",
|
|
description: "Over 10 years of continuous operation with billions of transactions processed",
|
|
buttons: [
|
|
{ label: "Read Case Studies", href: "/case-studies" },
|
|
{ label: "View Stats", href: "/statistics" }
|
|
]
|
|
}
|
|
]}
|
|
className="my-custom-class"
|
|
/>
|
|
```
|