Files
xrpl-dev-portal/shared/patterns/CardsTwoColumn/CardsTwoColumn.tsx
akcodez 29356aea8f Add CardsTwoColumn pattern styles and integrate into XRPL styles
- Introduced new styles for the CardsTwoColumn pattern, including responsive layouts and various card designs.
- Updated the xrpl.scss file to import the new CardsTwoColumn styles, ensuring they are included in the overall styling framework.
2026-06-08 16:54:55 -07:00

118 lines
4.2 KiB
TypeScript

import React from 'react';
import clsx from 'clsx';
import { TextCard, TextCardProps } from './TextCard';
/**
* 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 text (body-l typography, muted color) */
description?: React.ReactNode;
/** Secondary description paragraph (body-l typography, muted color) */
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. Follows the "Section Cards - Two Column" design from Figma.
*
* 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, description right (flex row)
* - Cards: 2x2 grid (2 columns, 2 rows)
* - Section padding: 40px vertical, 32px horizontal
* - Gap between header and cards: 40px
* - Gap between cards: 8px
*
* - Tablet (576-991px):
* - Header: Stacked (title above description)
* - 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)
* - 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}
>
<div className="bds-cards-two-column__container">
{/* Header Section */}
<div className="bds-cards-two-column__header">
<div className="bds-cards-two-column__header-left">
<h2 className="bds-cards-two-column__title h-md">{title}</h2>
</div>
{(description || secondaryDescription) && (
<div className="bds-cards-two-column__header-right">
<div className="bds-cards-two-column__description body-l">
{description && <p>{description}</p>}
{secondaryDescription && <p>{secondaryDescription}</p>}
</div>
</div>
)}
</div>
{/* Cards Grid - 2x2 on desktop, stacked on tablet/mobile */}
<div className="bds-cards-two-column__cards">
{cards.map((card, index) => (
<TextCard key={index} {...card} />
))}
</div>
</div>
</section>
);
}
);
CardsTwoColumn.displayName = 'CardsTwoColumn';
export default CardsTwoColumn;