Refactor payments and index pages to integrate BenefitsSection component

- Replaced the manual benefits list in the index page with the BenefitsSection component for improved maintainability.
- Added BenefitsSection to the payments page, showcasing embedded payment use cases with new card data.
- Updated ProjectCards component to support optional button text for enhanced project presentation.
- Introduced new CSS styles for embedded payments icons and battle-tested project cards for better visual consistency.
This commit is contained in:
akcodez
2025-08-26 07:38:18 -07:00
parent e94a5a0269
commit 9e2b88fbb8
13 changed files with 245 additions and 22 deletions

View File

@@ -2,6 +2,7 @@ import React, { useState } from "react";
import { useThemeHooks } from "@redocly/theme/core/hooks"; import { useThemeHooks } from "@redocly/theme/core/hooks";
import { AdvantagesSection } from "shared/components/advantages-section"; import { AdvantagesSection } from "shared/components/advantages-section";
import { ProjectCards } from "shared/components/project-cards"; import { ProjectCards } from "shared/components/project-cards";
import { BenefitsSection } from "shared/components/benefits-section";
export const frontmatter = { export const frontmatter = {
seo: { seo: {
@@ -104,6 +105,63 @@ const PaymentsPage: React.FC = () => {
}, },
]; ];
const embeddedPaymentsCards = [
{
id: 'digital-wallets',
title: 'Digital Wallets',
description: 'Offer fast, low-fee stablecoin payments between users and applications.',
},
{
id: 'cross-border-remittance',
title: 'Cross-Border Remittance',
description: 'Use secure payment channels and the most optimal liquidity pathways for global remittances with RLUSD.',
},
{
id: 'regulated-foreign-exchange',
title: 'Regulated Foreign Exchange',
description: 'Tap into a set of fiat-backed stablecoins, instantaneous swaps for efficient Foreign Exchange.',
},
{
id: 'merchant-settlement',
title: 'Merchant Settlement',
description: 'Settle daily payments across assets using escrow or checks with compliance-focused features.',
},
{
id: 'b2b-payment-rails',
title: 'B2B Payment Rails',
description: 'Build programmable payment flows with conditions and real-time data feeds.',
},
{
id: 'compliance-first-payment-acceptance',
title: 'Compliance-First Payment Acceptance',
description: 'Add Deposit Authorization and whitelisting to comply with AML and KYC workflows.',
},
];
const battleTestedProjects = [
{
id: "coinpayments",
label: "CoinPayments",
url: "#",
description: "CoinPayments uses XRPL's fast and low-cost payment rails to enable merchants to accept digital assets globally with near-instant settlement and minimal transaction fees.",
buttonText: "Case Study"
},
{
id: "ripple",
label: "Ripple",
url: "#",
description: "Ripple Payments enables crypto companies, payment service providers and fintech to facilitate real-time cross-border payments using stablecoins, digital assets and local currencies — with XRPL as a foundational transaction layer.",
buttonText: "Case Study"
},
{
id: "fiipay",
label: "FiiPay",
url: "#",
description: "FiiPay connects XRPL-based crypto wallets to point-of-sale terminals, allowing customers to pay with RLUSD or XRP while helping merchants save costs on card processing fees.",
buttonText: "Case Study"
},
];
return ( return (
<main className="use-case-payments"> <main className="use-case-payments">
<section className="use-case-payments__hero"> <section className="use-case-payments__hero">
@@ -140,13 +198,29 @@ const PaymentsPage: React.FC = () => {
useLinks={false} useLinks={false}
className="payments-advantages-spacing" className="payments-advantages-spacing"
/> />
<ProjectCards <ProjectCards
title="Enterprise-Grade Stablecoins, Issued Natively on XRPL" title="Enterprise-Grade Stablecoins, Issued Natively on XRPL"
projects={paymentProjects} projects={paymentProjects}
showCarousel={false} showCarousel={false}
className="mt-12 px-0" className="mt-12 px-0"
/> />
<BenefitsSection
title="Unlock New Business Models with Embedded Payments"
description="XRPL Payments supports modern fintech use cases with plug-and-play APIs or partner-led deployments."
cards={embeddedPaymentsCards}
showImages={true}
className="embedded-payments-section px-0"
listId="embedded-payments-list"
/>
<ProjectCards
title="Payments Solution, Battle-Tested by Industry Leaders"
projects={battleTestedProjects}
showCarousel={false}
className="battle-tested-section px-0"
/>
</main> </main>
); );
}; };

View File

@@ -1,5 +1,6 @@
import { useThemeHooks } from '@redocly/theme/core/hooks'; import { useThemeHooks } from '@redocly/theme/core/hooks';
import { Link } from '@redocly/theme/components/Link/Link'; import { Link } from '@redocly/theme/components/Link/Link';
import { BenefitsSection } from 'shared/components/benefits-section';
export const frontmatter = { export const frontmatter = {
seo: { seo: {
@@ -147,23 +148,12 @@ export default function Index() {
</p> </p>
</div> </div>
</section> </section>
<section className="container-new py-26"> <BenefitsSection
<div className="d-flex flex-column-reverse col-sm-8 p-0"> eyebrow="Benefits"
<h3 className="h4 h2-sm">{translate('Why developers choose the XRP Ledger')}</h3> title="Why developers choose the XRP Ledger"
<h6 className="eyebrow mb-3">{translate('Benefits')}</h6> cards={cards}
</div> showImages={true}
<ul className="mt-10 card-grid card-grid-3xN" id="benefits-list"> />
{cards.map(card => (
<li className="col ls-none" key={card.id}>
<img id={card.id} alt={card.title + ' Icon'} />
<h4 className="mt-3 mb-0 h5">{translate(card.title)}</h4>
<p className="mt-6-until-sm mt-3 mb-0">
{typeof card.description === 'string' ? translate(card.description) : card.description}
</p>
</li>
))}
</ul>
</section>
<section className="container-new py-26"> <section className="container-new py-26">
<div className="d-flex flex-column-reverse col-sm-8 p-0"> <div className="d-flex flex-column-reverse col-sm-8 p-0">
<h3 className="h4 h2-sm"> <h3 className="h4 h2-sm">

View File

@@ -0,0 +1,55 @@
import React from "react";
import { useThemeHooks } from "@redocly/theme/core/hooks";
export interface BenefitCard {
id: string;
title: string;
description: React.ReactNode | string;
}
export interface BenefitsSectionProps {
eyebrow?: string;
title: string;
description?: string;
cards: BenefitCard[];
className?: string;
showImages?: boolean;
listId?: string;
}
export const BenefitsSection: React.FC<BenefitsSectionProps> = ({
eyebrow,
title,
description,
cards,
className = "",
showImages = true,
listId = "benefits-list",
}) => {
const { useTranslate } = useThemeHooks();
const { translate } = useTranslate();
return (
<section className={`container-new py-26 ${className}`}>
<div className="d-flex flex-column-reverse col-lg-10 col-sm-8 p-0">
<h3 className="h4 h2-sm">{translate(title)}</h3>
{eyebrow && <h6 className="eyebrow mb-3">{translate(eyebrow)}</h6>}
</div>
{description && (
<p className="mt-6 mb-0 col-lg-8 col-sm-8 p-0">{translate(description)}</p>
)}
<ul className="mt-10 card-grid card-grid-3xN" id={listId}>
{cards.map(card => (
<li className="col ls-none" key={card.id}>
{showImages && <img id={card.id} alt={card.title + ' Icon'} />}
<h4 className="mt-3 mb-0 h5">{translate(card.title)}</h4>
<p className="mt-6-until-sm mt-3 mb-0">
{typeof card.description === 'string' ? translate(card.description) : card.description}
</p>
</li>
))}
</ul>
</section>
);
};

View File

@@ -6,6 +6,7 @@ interface Project {
label: string; label: string;
url: string; url: string;
description?: string; // New optional field for payments page description?: string; // New optional field for payments page
buttonText?: string; // Optional button text for battle-tested cards
} }
interface ProjectCardsProps { interface ProjectCardsProps {
@@ -51,6 +52,11 @@ const ProjectCard = ({ project, index, showCarousel = true }: {
})()} })()}
</div> </div>
)} )}
{!showCarousel && project.buttonText && (
<div className="project-button">
<a href={project.url} className="btn-arrow battle-tested-arrow">{translate(project.buttonText)}</a>
</div>
)}
</a> </a>
); );
}; };

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -89,6 +89,33 @@
} }
} }
// Payments page specific embedded payments icons
#embedded-payments-list {
#digital-wallets {
content: url("../img/uses/payments/digital-wallet.png");
}
#cross-border-remittance {
content: url("../img/uses/payments/cross-border.png");
}
#regulated-foreign-exchange {
content: url("../img/uses/payments/regulated.png");
}
#merchant-settlement {
content: url("../img/uses/payments/merchant-settlement.png");
}
#b2b-payment-rails {
content: url("../img/uses/payments/b2b-payment.png");
}
#compliance-first-payment-acceptance {
content: url("../img/uses/payments/compliance.png");
}
}
.cta { .cta {
position: absolute; position: absolute;

View File

@@ -1083,6 +1083,9 @@ body,
background-color: transparent; background-color: transparent;
white-space: normal; white-space: normal;
box-sizing: border-box; box-sizing: border-box;
.card-title{
margin-bottom: 16px;
}
} }
.security-card::before { .security-card::before {
@@ -1150,7 +1153,6 @@ body,
padding: 0; padding: 0;
margin: 0; margin: 0;
} }
.advantage-item { .advantage-item {
position: relative; position: relative;
padding-left: 20px; padding-left: 20px;
@@ -1161,7 +1163,6 @@ body,
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
color: #7919FF;
font-weight: bold; font-weight: bold;
font-size: 16px; font-size: 16px;
} }
@@ -1226,7 +1227,6 @@ body,
position: relative; position: relative;
padding: 32px; padding: 32px;
.project-description { .project-description {
padding: 0 1rem;
text-align: left; /* Changed from center to left */ text-align: left; /* Changed from center to left */
.first-word { .first-word {
@@ -1307,4 +1307,75 @@ body,
&.even::before { &.even::before {
background: linear-gradient(90deg, #4BB7FF -0.32%, #32E685 30.61%); background: linear-gradient(90deg, #4BB7FF -0.32%, #32E685 30.61%);
} }
}
/* Battle-tested section styles */
.use-case-payments .battle-tested-section {
h4.eyebrow {
font-size: 28px !important;
}
.payments-project-card {
/* Override styles for battle-tested cards */
min-height: 384px;
display: flex;
flex-direction: column;
.project-logo img {
/* Placeholder images - use standard sizing */
width: 120px;
height: 60px;
background-color: #333;
border-radius: 8px;
content: "";
}
.project-description {
flex-grow: 1;
}
.project-button {
margin-top: auto;
padding-top: 32px;
display: flex;
justify-content: center;
.battle-tested-arrow {
color: #9A52FF;
font-size: 16px;
font-style: normal;
font-weight: 700;
text-decoration: none;
cursor: pointer;
display: inline-flex;
align-items: center;
background: none !important;
&::after {
position: relative;
top: -1px;
display: inline-block;
content: url('../img/icons/arrow-right-purple.svg');
margin-left: 8px;
transition: transform 0.3s ease-out;
width: 16px;
height: 16px;
}
&:hover {
text-decoration: none;
background: none !important;
&::after {
transform: translateX(4px);
}
}
&:focus {
background: none !important;
outline: none;
}
}
}
}
} }