Files
xrpl-dev-portal/shared/sections/CardsTwoColumn/CardsTwoColumn.tsx
Calvin 32e89c1299 Component Library Refactor & New Components (#3510)
* 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
2026-02-23 15:00:18 -08:00

119 lines
4.4 KiB
TypeScript

import React from 'react';
import clsx from 'clsx';
import { TextCard, TextCardProps } from 'shared/components/TextCard';
import { PageGrid } from 'shared/components/PageGrid';
/**
* Configuration for a card in the CardsTwoColumn pattern
*/
export type CardsTwoColumnCardConfig = TextCardProps;
/**
* Props for the CardsTwoColumn pattern component
*/
export interface CardsTwoColumnProps extends Omit<React.ComponentPropsWithoutRef<'section'>, 'title'> {
/** Section title (heading-md typography) */
title: React.ReactNode;
/** Section description (body-l typography, muted color). Can be string or ReactNode */
description?: React.ReactNode;
/** Secondary description paragraph (body-l typography, muted color). Can be string or ReactNode */
secondaryDescription?: React.ReactNode;
/** Array of 4 card configurations for the 2x2 grid */
cards: readonly [CardsTwoColumnCardConfig, CardsTwoColumnCardConfig, CardsTwoColumnCardConfig, CardsTwoColumnCardConfig];
}
/**
* CardsTwoColumn Pattern Component
*
* A section pattern that displays a header with title/description and a 2x2 grid
* of TextCard components. Uses PageGrid for responsive layout.
*
* Structure:
* - Header: Title (left) + Description (right) on desktop, stacked on tablet/mobile
* - Cards: 2x2 grid on desktop, single column stacked on tablet/mobile
*
* Responsive behavior:
* - Desktop (≥992px):
* - Header: Title left (6 cols), description right (6 cols)
* - Cards: 2x2 grid (6 cols each)
* - Section padding: 40px vertical, 32px horizontal
* - Gap between header and cards: 40px
* - Gap between cards: 8px
*
* - Tablet (576-991px):
* - Header: Stacked (title above description, full width)
* - Cards: Single column, stacked vertically
* - Section padding: 32px vertical, 24px horizontal
* - Gap between header and cards: 32px
* - Gap between cards: 8px
*
* - Mobile (<576px):
* - Header: Stacked (title above description, full width)
* - Cards: Single column, stacked vertically
* - Section padding: 24px vertical, 16px horizontal
* - Gap between header and cards: 24px
* - Gap between cards: 8px
*
* @example
* ```tsx
* <CardsTwoColumn
* title="The Future of Finance is Already Onchain"
* description="XRP Ledger isn't about bold predictions. It's about delivering value now."
* secondaryDescription="On XRPL, you're not waiting for the future. You're building it."
* cards={[
* { title: "Institutions", description: "Banks, asset managers...", color: "lilac" },
* { title: "Developers", description: "Build decentralized...", color: "neutral-light" },
* { title: "Enterprise", description: "Scale your business...", color: "neutral-dark" },
* { title: "Community", description: "Join the global...", color: "green" }
* ]}
* />
* ```
*/
export const CardsTwoColumn = React.forwardRef<HTMLElement, CardsTwoColumnProps>(
(props, ref) => {
const { title, description, secondaryDescription, cards, className, ...rest } = props;
if (cards.length !== 4) {
console.warn('CardsTwoColumn: Exactly 4 cards are required');
return null;
}
return (
<section
ref={ref}
className={clsx('bds-cards-two-column', className)}
{...rest}
>
<PageGrid className="bds-cards-two-column__container">
{/* Header Row */}
<PageGrid.Row className="bds-cards-two-column__header">
<PageGrid.Col span={{ md: 8, lg: 6 }} className="bds-cards-two-column__header-left">
<h2 className="bds-cards-two-column__title h-md">{title}</h2>
</PageGrid.Col>
{(description || secondaryDescription) && (
<PageGrid.Col span={{ md: 8, lg: 6 }} className="bds-cards-two-column__header-right bds-cards-two-column__description body-l">
{description && <p>{description}</p>}
{secondaryDescription && <p>{secondaryDescription}</p>}
</PageGrid.Col>
)}
</PageGrid.Row>
{/* Cards Row - 2x2 on desktop, stacked on tablet/mobile */}
<PageGrid.Row className="bds-cards-two-column__cards">
{cards.map((card, index) => (
<PageGrid.Col key={index} span={{ md: 8, lg: 6 }}>
<TextCard {...card} />
</PageGrid.Col>
))}
</PageGrid.Row>
</PageGrid>
</section>
);
}
);
CardsTwoColumn.displayName = 'CardsTwoColumn';
export default CardsTwoColumn;