mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2026-01-13 11:15:18 +00:00
Compare commits
4 Commits
brand-upda
...
pattern/he
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce75b4388c | ||
|
|
f346a80ce0 | ||
|
|
e849cc95b9 | ||
|
|
0bff1aab4c |
692
about/header-hero-split-media-showcase.page.tsx
Normal file
692
about/header-hero-split-media-showcase.page.tsx
Normal file
@@ -0,0 +1,692 @@
|
||||
import * as React from 'react';
|
||||
import { PageGrid, PageGridRow, PageGridCol } from 'shared/components/PageGrid/page-grid';
|
||||
import { HeaderHeroSplitMedia } from 'shared/patterns/HeaderHeroSplitMedia';
|
||||
|
||||
export const frontmatter = {
|
||||
seo: {
|
||||
title: 'HeaderHeroSplitMedia Pattern Showcase',
|
||||
description: 'Interactive showcase of the HeaderHeroSplitMedia pattern with all variants, layouts, and responsive behavior.',
|
||||
},
|
||||
};
|
||||
|
||||
export default function HeaderHeroSplitMediaShowcase() {
|
||||
// Placeholder image - using the demo-bg.png file
|
||||
const placeholderImage = '/img/demo-bg.png';
|
||||
|
||||
return (
|
||||
<div className="landing">
|
||||
<div className="overflow-hidden">
|
||||
{/* Hero Section */}
|
||||
<section className="py-26 text-center">
|
||||
<div className="col-lg-8 mx-auto">
|
||||
<h6 className="eyebrow mb-3">Pattern Showcase</h6>
|
||||
<h1 className="mb-4">HeaderHeroSplitMedia Pattern</h1>
|
||||
<p className="longform">
|
||||
A page-level hero pattern that pairs prominent editorial content with a primary media element in a split layout.
|
||||
Designed to introduce major concepts, products, or use cases while maintaining strong visual hierarchy and clear calls to action.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Surface Variants */}
|
||||
<section className="py-26">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<div className="d-flex flex-column-reverse mb-8">
|
||||
<h2 className="h4 mb-0">Surface Variants</h2>
|
||||
<h6 className="eyebrow mb-3">Default vs Accent</h6>
|
||||
</div>
|
||||
<p className="mb-10">
|
||||
The pattern supports two surface treatments: Default (no background) and Accent (green background on title section).
|
||||
Theme is automatically controlled by <code>html.light</code> and <code>html.dark</code> classes.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
|
||||
{/* Default Surface */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">Default Surface</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
No background surface behind the hero title. Entire content area has uniform background.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="default"
|
||||
layout="content-left"
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions with developer tools and APIs."
|
||||
description="XRPL Payments Suite helps fintechs and payment providers move money fast, globally, and at low cost - all through simple APIs."
|
||||
primaryCta={{ label: "Primary Link", href: "#primary" }}
|
||||
secondaryCta={{ label: "Tertiary Link", href: "#tertiary" }}
|
||||
media={{ src: placeholderImage, alt: "Tokenization illustration" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Accent Surface */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">Accent Surface</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
Green accent background with internal padding behind the hero title and subtitle section.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="accent"
|
||||
layout="content-left"
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions with developer tools and APIs."
|
||||
description="XRPL Payments Suite helps fintechs and payment providers move money fast, globally, and at low cost - all through simple APIs."
|
||||
primaryCta={{ label: "Primary Link", href: "#primary" }}
|
||||
secondaryCta={{ label: "Tertiary Link", href: "#tertiary" }}
|
||||
media={{ src: placeholderImage, alt: "Tokenization illustration" }}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Layout Variants */}
|
||||
<section className="py-26">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<div className="d-flex flex-column-reverse mb-8">
|
||||
<h2 className="h4 mb-0">Layout Variants</h2>
|
||||
<h6 className="eyebrow mb-3">Content Position</h6>
|
||||
</div>
|
||||
<p className="mb-10">
|
||||
Control whether the content block appears on the left or right side of the media.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
|
||||
{/* Content Left */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">Content Left (Default)</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
Content appears on the left, media on the right. This is the default layout.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="accent"
|
||||
layout="content-left"
|
||||
title="Build on the XRP Ledger"
|
||||
subtitle="Start developing with the most sustainable blockchain."
|
||||
description="Join thousands of developers building the future of finance."
|
||||
primaryCta={{ label: "Start Building", href: "#start" }}
|
||||
secondaryCta={{ label: "View Tutorials", href: "#tutorials" }}
|
||||
media={{ src: placeholderImage, alt: "XRPL development" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Content Right */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">Content Right</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
Content appears on the right, media on the left. Useful for visual variety.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="accent"
|
||||
layout="content-right"
|
||||
title="Enterprise Solutions"
|
||||
subtitle="Scale your business with blockchain technology."
|
||||
description="Leverage the XRPL Ledger for enterprise-grade applications."
|
||||
primaryCta={{ label: "Contact Sales", href: "#contact" }}
|
||||
secondaryCta={{ label: "Learn More", href: "#learn" }}
|
||||
media={{ src: placeholderImage, alt: "Enterprise solutions" }}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Responsive Behavior */}
|
||||
<section className="py-26">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<div className="d-flex flex-column-reverse mb-8">
|
||||
<h2 className="h4 mb-0">Responsive Behavior</h2>
|
||||
<h6 className="eyebrow mb-3">Breakpoint Adaptations</h6>
|
||||
</div>
|
||||
<p className="mb-6">
|
||||
The pattern adapts responsively across desktop, tablet, and mobile breakpoints. Resize your browser window to see the changes.
|
||||
</p>
|
||||
|
||||
<div className="d-flex flex-column gap-4 mb-10">
|
||||
<div className="d-flex flex-row gap-4 align-items-start" style={{ flexWrap: 'wrap' }}>
|
||||
<div style={{ flex: '1 1 300px', minWidth: '280px' }}>
|
||||
<h6 className="mb-3">Desktop (≥992px)</h6>
|
||||
<ul className="mb-0">
|
||||
<li><strong>Layout:</strong> Side-by-side (50/50 split)</li>
|
||||
<li><strong>Grid columns:</strong> Content 6/12, Media 6/12</li>
|
||||
<li><strong>Text width:</strong> 5/12 of grid (83.33% of column)</li>
|
||||
<li><strong>Content gap:</strong> 8px</li>
|
||||
<li><strong>CTA gap:</strong> 24px (horizontal)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style={{ flex: '1 1 300px', minWidth: '280px' }}>
|
||||
<h6 className="mb-3">Tablet (576px–991px)</h6>
|
||||
<ul className="mb-0">
|
||||
<li><strong>Layout:</strong> Stacked (content above media)</li>
|
||||
<li><strong>Grid columns:</strong> Content 8/8, Media 8/8</li>
|
||||
<li><strong>Text width:</strong> 6/8 of grid (75% of column)</li>
|
||||
<li><strong>Content gap:</strong> 32px</li>
|
||||
<li><strong>CTA gap:</strong> 24px (horizontal)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style={{ flex: '1 1 300px', minWidth: '280px' }}>
|
||||
<h6 className="mb-3">Mobile (<576px)</h6>
|
||||
<ul className="mb-0">
|
||||
<li><strong>Layout:</strong> Stacked (content above media)</li>
|
||||
<li><strong>Grid columns:</strong> Content 4/4, Media 4/4</li>
|
||||
<li><strong>Text width:</strong> Full width</li>
|
||||
<li><strong>Content gap:</strong> 32px</li>
|
||||
<li><strong>CTA gap:</strong> 16px (vertical)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-4 mb-10" style={{ backgroundColor: 'rgba(114, 119, 126, 0.1)', borderRadius: '8px' }}>
|
||||
<h6 className="mb-3">Accent Surface Padding</h6>
|
||||
<ul className="mb-0">
|
||||
<li><strong>Desktop:</strong> 16px top, 16px left/right, 24px bottom</li>
|
||||
<li><strong>Tablet:</strong> 16px top, 16px left/right, 24px bottom</li>
|
||||
<li><strong>Mobile:</strong> 8px top, 8px left/right, 16px bottom</li>
|
||||
</ul>
|
||||
</div>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
</section>
|
||||
|
||||
{/* Optional Props Combinations */}
|
||||
<section className="py-26">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<div className="d-flex flex-column-reverse mb-8">
|
||||
<h2 className="h4 mb-0">Optional Props Combinations</h2>
|
||||
<h6 className="eyebrow mb-3">Flexible Content</h6>
|
||||
</div>
|
||||
<p className="mb-10">
|
||||
The pattern gracefully handles various combinations of optional props. Description, primaryCta, and secondaryCta are all optional.
|
||||
The layout automatically adjusts based on which props are provided.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
|
||||
{/* Full Content - All Props */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">Full Content (All Props)</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
Title, subtitle, description, primary CTA, and secondary CTA all provided.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="default"
|
||||
layout="content-left"
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions with developer tools and APIs."
|
||||
description="XRPL Payments Suite helps fintechs and payment providers move money fast, globally, and at low cost - all through simple APIs."
|
||||
primaryCta={{ label: "Primary Link", href: "#primary" }}
|
||||
secondaryCta={{ label: "Tertiary Link", href: "#tertiary" }}
|
||||
media={{ src: placeholderImage, alt: "Full content example" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Full Content - Accent Surface */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">Full Content (Accent Surface)</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
Same as above but with accent surface for the title section.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="accent"
|
||||
layout="content-left"
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions with developer tools and APIs."
|
||||
description="XRPL Payments Suite helps fintechs and payment providers move money fast, globally, and at low cost - all through simple APIs."
|
||||
primaryCta={{ label: "Primary Link", href: "#primary" }}
|
||||
secondaryCta={{ label: "Tertiary Link", href: "#tertiary" }}
|
||||
media={{ src: placeholderImage, alt: "Full content accent example" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* No Description - CTAs Only */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">No Description (CTAs Only)</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
Title, subtitle, and both CTAs - no description text. CTAs appear directly below the title section.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="default"
|
||||
layout="content-left"
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions with developer tools and APIs."
|
||||
primaryCta={{ label: "Primary Link", href: "#primary" }}
|
||||
secondaryCta={{ label: "Tertiary Link", href: "#tertiary" }}
|
||||
media={{ src: placeholderImage, alt: "No description example" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* No Description - Accent Surface */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">No Description (Accent Surface)</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
Same as above but with accent surface.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="accent"
|
||||
layout="content-left"
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions with developer tools and APIs."
|
||||
primaryCta={{ label: "Primary Link", href: "#primary" }}
|
||||
secondaryCta={{ label: "Tertiary Link", href: "#tertiary" }}
|
||||
media={{ src: placeholderImage, alt: "No description accent example" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Primary CTA Only (No Description) */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">Primary CTA Only (No Description)</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
Title, subtitle, and only primary CTA - no description or secondary CTA.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="default"
|
||||
layout="content-left"
|
||||
title="Quick Start Guide"
|
||||
subtitle="Get up and running in minutes."
|
||||
primaryCta={{ label: "Begin", href: "#begin" }}
|
||||
media={{ src: placeholderImage, alt: "Primary CTA only example" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Primary CTA Only (With Description) */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">Primary CTA Only (With Description)</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
Title, subtitle, description, and only primary CTA - no secondary CTA.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="default"
|
||||
layout="content-left"
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions with developer tools and APIs."
|
||||
description="XRPL Payments Suite helps fintechs and payment providers move money fast, globally, and at low cost - all through simple APIs."
|
||||
primaryCta={{ label: "Primary Link", href: "#primary" }}
|
||||
media={{ src: placeholderImage, alt: "Primary CTA with description example" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* No CTAs (Description Only) */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">No CTAs (Description Only)</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
Title, subtitle, and description - no CTA buttons.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="default"
|
||||
layout="content-left"
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions with developer tools and APIs."
|
||||
description="XRPL Payments Suite helps fintechs and payment providers move money fast, globally, and at low cost - all through simple APIs."
|
||||
media={{ src: placeholderImage, alt: "No CTAs example" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Title and Subtitle Only (Minimum) */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">Title and Subtitle Only (Minimum)</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
Only the required props: title, subtitle, and media. No description or CTAs.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="default"
|
||||
layout="content-left"
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions with developer tools and APIs."
|
||||
media={{ src: placeholderImage, alt: "Minimum props example" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Title and Subtitle Only (Accent) */}
|
||||
<div className="mb-10">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<h3 className="h5 mb-4">Title and Subtitle Only (Accent Surface)</h3>
|
||||
<p className="mb-6 text-muted">
|
||||
Minimum props with accent surface - title section is centered vertically.
|
||||
</p>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
<HeaderHeroSplitMedia
|
||||
surface="accent"
|
||||
layout="content-left"
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions with developer tools and APIs."
|
||||
media={{ src: placeholderImage, alt: "Minimum props accent example" }}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Theme Support */}
|
||||
<section className="py-26">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<div className="d-flex flex-column-reverse mb-8">
|
||||
<h2 className="h4 mb-0">Theme Support</h2>
|
||||
<h6 className="eyebrow mb-3">Light & Dark Modes</h6>
|
||||
</div>
|
||||
<p className="mb-6">
|
||||
Theme is automatically controlled by the <code>html.light</code> and <code>html.dark</code> classes on the document root.
|
||||
No theme prop is needed. Toggle your theme preference to see the pattern adapt.
|
||||
</p>
|
||||
<div className="p-4 mb-10" style={{ backgroundColor: 'rgba(114, 119, 126, 0.1)', borderRadius: '8px' }}>
|
||||
<h6 className="mb-3">Theme Colors</h6>
|
||||
<div className="d-flex flex-row gap-6" style={{ flexWrap: 'wrap' }}>
|
||||
<div style={{ flex: '1 1 300px', minWidth: '280px' }}>
|
||||
<strong className="d-block mb-2">Light Mode</strong>
|
||||
<ul className="mb-0">
|
||||
<li>Background: White</li>
|
||||
<li>Title/Subtitle: Black (#141414)</li>
|
||||
<li>Description: Gray 500 (#72777e)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style={{ flex: '1 1 300px', minWidth: '280px' }}>
|
||||
<strong className="d-block mb-2">Dark Mode</strong>
|
||||
<ul className="mb-0">
|
||||
<li>Background: Black (#141414)</li>
|
||||
<li>Title/Subtitle: White</li>
|
||||
<li>Description: Neutral 200 (#e6eaf0)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
</section>
|
||||
|
||||
{/* Code Examples */}
|
||||
<section className="py-26">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<div className="d-flex flex-column-reverse mb-8">
|
||||
<h2 className="h4 mb-0">Code Examples</h2>
|
||||
<h6 className="eyebrow mb-3">Implementation</h6>
|
||||
</div>
|
||||
<div className="p-6-sm p-10-until-sm br-8 mb-6" style={{ backgroundColor: '#1e1e1e', color: '#d4d4d4' }}>
|
||||
<pre style={{ margin: 0, overflow: 'auto' }}>
|
||||
<code>{`import { HeaderHeroSplitMedia } from 'shared/patterns/HeaderHeroSplitMedia';
|
||||
|
||||
// Full content - all props provided
|
||||
<HeaderHeroSplitMedia
|
||||
surface="accent"
|
||||
layout="content-left"
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions."
|
||||
description="XRPL helps fintechs move money fast, globally, at low cost."
|
||||
primaryCta={{ label: "Get Started", href: "/docs" }}
|
||||
secondaryCta={{ label: "Learn More", href: "/about" }}
|
||||
media={{ src: "/img/hero.png", alt: "Hero illustration" }}
|
||||
/>
|
||||
|
||||
// No description - CTAs directly below title
|
||||
<HeaderHeroSplitMedia
|
||||
surface="default"
|
||||
layout="content-left"
|
||||
title="Build on XRPL"
|
||||
subtitle="Start developing today."
|
||||
primaryCta={{ label: "Start Building", href: "/docs" }}
|
||||
secondaryCta={{ label: "View Tutorials", href: "/tutorials" }}
|
||||
media={{ src: "/img/hero.png", alt: "Development" }}
|
||||
/>
|
||||
|
||||
// Primary CTA only (no description, no secondary CTA)
|
||||
<HeaderHeroSplitMedia
|
||||
surface="accent"
|
||||
layout="content-left"
|
||||
title="Quick Start"
|
||||
subtitle="Get up and running in minutes."
|
||||
primaryCta={{ label: "Begin", href: "/quickstart" }}
|
||||
media={{ src: "/img/quickstart.png", alt: "Quick start" }}
|
||||
/>
|
||||
|
||||
// Primary CTA only with description
|
||||
<HeaderHeroSplitMedia
|
||||
surface="default"
|
||||
layout="content-right"
|
||||
title="Enterprise Solutions"
|
||||
subtitle="Scale your business."
|
||||
description="Leverage XRPL for enterprise applications."
|
||||
primaryCta={{ label: "Contact Sales", href: "/contact" }}
|
||||
media={{ src: "/img/enterprise.png", alt: "Enterprise" }}
|
||||
/>
|
||||
|
||||
// No CTAs - description only
|
||||
<HeaderHeroSplitMedia
|
||||
surface="default"
|
||||
layout="content-left"
|
||||
title="About XRPL"
|
||||
subtitle="The decentralized ledger for everyone."
|
||||
description="Learn about the technology powering global payments."
|
||||
media={{ src: "/img/about.png", alt: "About XRPL" }}
|
||||
/>
|
||||
|
||||
// Title and subtitle only (minimum required props)
|
||||
<HeaderHeroSplitMedia
|
||||
title="Welcome"
|
||||
subtitle="Explore the possibilities."
|
||||
media={{ src: "/img/welcome.png", alt: "Welcome" }}
|
||||
/>`}</code>
|
||||
</pre>
|
||||
</div>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
</section>
|
||||
|
||||
{/* Component API */}
|
||||
<section className="py-26">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<div className="d-flex flex-column-reverse mb-8">
|
||||
<h2 className="h4 mb-0">Component API</h2>
|
||||
<h6 className="eyebrow mb-3">Props Reference</h6>
|
||||
</div>
|
||||
<div className="mb-10">
|
||||
{/* Header Row */}
|
||||
<div className="d-flex flex-row mb-3 pb-2" style={{ gap: '1rem', borderBottom: '2px solid var(--bs-border-color, #dee2e6)' }}>
|
||||
<div style={{ width: '120px', flexShrink: 0 }}><strong>Prop</strong></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}><strong>Type</strong></div>
|
||||
<div style={{ width: '100px', flexShrink: 0 }}><strong>Default</strong></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}><strong>Description</strong></div>
|
||||
</div>
|
||||
|
||||
{/* surface */}
|
||||
<div className="d-flex flex-row py-3" style={{ gap: '1rem', borderBottom: '1px solid var(--bs-border-color, #dee2e6)' }}>
|
||||
<div style={{ width: '120px', flexShrink: 0 }}><code>surface</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}><code>'default' | 'accent'</code></div>
|
||||
<div style={{ width: '100px', flexShrink: 0 }}><code>'default'</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}>Surface variant - accent adds green background on title section</div>
|
||||
</div>
|
||||
|
||||
{/* layout */}
|
||||
<div className="d-flex flex-row py-3" style={{ gap: '1rem', borderBottom: '1px solid var(--bs-border-color, #dee2e6)' }}>
|
||||
<div style={{ width: '120px', flexShrink: 0 }}><code>layout</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}><code>'content-left' | 'content-right'</code></div>
|
||||
<div style={{ width: '100px', flexShrink: 0 }}><code>'content-left'</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}>Controls content position relative to media</div>
|
||||
</div>
|
||||
|
||||
{/* title */}
|
||||
<div className="d-flex flex-row py-3" style={{ gap: '1rem', borderBottom: '1px solid var(--bs-border-color, #dee2e6)' }}>
|
||||
<div style={{ width: '120px', flexShrink: 0 }}><code>title</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}><code>string</code></div>
|
||||
<div style={{ width: '100px', flexShrink: 0 }}><em>required</em></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}>Hero title text (display-md typography)</div>
|
||||
</div>
|
||||
|
||||
{/* subtitle */}
|
||||
<div className="d-flex flex-row py-3" style={{ gap: '1rem', borderBottom: '1px solid var(--bs-border-color, #dee2e6)' }}>
|
||||
<div style={{ width: '120px', flexShrink: 0 }}><code>subtitle</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}><code>string</code></div>
|
||||
<div style={{ width: '100px', flexShrink: 0 }}><em>required</em></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}>Hero subtitle text (subhead-sm-l typography)</div>
|
||||
</div>
|
||||
|
||||
{/* description */}
|
||||
<div className="d-flex flex-row py-3" style={{ gap: '1rem', borderBottom: '1px solid var(--bs-border-color, #dee2e6)' }}>
|
||||
<div style={{ width: '120px', flexShrink: 0 }}><code>description</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}><code>string</code></div>
|
||||
<div style={{ width: '100px', flexShrink: 0 }}><code>undefined</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}>Description text below title section (body-l typography)</div>
|
||||
</div>
|
||||
|
||||
{/* primaryCta */}
|
||||
<div className="d-flex flex-row py-3" style={{ gap: '1rem', borderBottom: '1px solid var(--bs-border-color, #dee2e6)' }}>
|
||||
<div style={{ width: '120px', flexShrink: 0 }}><code>primaryCta</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}><code>{'{ label: string; href: string }'}</code></div>
|
||||
<div style={{ width: '100px', flexShrink: 0 }}><code>undefined</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}>Primary CTA button configuration</div>
|
||||
</div>
|
||||
|
||||
{/* secondaryCta */}
|
||||
<div className="d-flex flex-row py-3" style={{ gap: '1rem', borderBottom: '1px solid var(--bs-border-color, #dee2e6)' }}>
|
||||
<div style={{ width: '120px', flexShrink: 0 }}><code>secondaryCta</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}><code>{'{ label: string; href: string }'}</code></div>
|
||||
<div style={{ width: '100px', flexShrink: 0 }}><code>undefined</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}>Secondary/Tertiary CTA button configuration</div>
|
||||
</div>
|
||||
|
||||
{/* media */}
|
||||
<div className="d-flex flex-row py-3" style={{ gap: '1rem', borderBottom: '1px solid var(--bs-border-color, #dee2e6)' }}>
|
||||
<div style={{ width: '120px', flexShrink: 0 }}><code>media</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}><code>{'{ src: string; alt: string }'}</code></div>
|
||||
<div style={{ width: '100px', flexShrink: 0 }}><em>required</em></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}>Hero media (image) configuration</div>
|
||||
</div>
|
||||
|
||||
{/* className */}
|
||||
<div className="d-flex flex-row py-3" style={{ gap: '1rem' }}>
|
||||
<div style={{ width: '120px', flexShrink: 0 }}><code>className</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}><code>string</code></div>
|
||||
<div style={{ width: '100px', flexShrink: 0 }}><code>undefined</code></div>
|
||||
<div style={{ flex: '1 1 0', minWidth: 0 }}>Additional CSS classes</div>
|
||||
</div>
|
||||
</div>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
</section>
|
||||
|
||||
{/* Design References */}
|
||||
<section className="py-26">
|
||||
<PageGrid>
|
||||
<PageGridRow>
|
||||
<PageGridCol span={12}>
|
||||
<div className="d-flex flex-column-reverse mb-8">
|
||||
<h2 className="h4 mb-0">Design References</h2>
|
||||
<h6 className="eyebrow mb-3">Figma & Documentation</h6>
|
||||
</div>
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<div>
|
||||
<strong>Figma Design:</strong>{' '}
|
||||
<a href="https://www.figma.com/design/olsJKEo16jmwaNXpHxCdbN/Header-Hero---Split-Media?node-id=10066-2126&m=dev" target="_blank" rel="noopener noreferrer">
|
||||
Header Hero - Split Media Pattern
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Example Usage:</strong>{' '}
|
||||
<a href="https://www.figma.com/design/olsJKEo16jmwaNXpHxCdbN/Header-Hero---Split-Media?node-id=10066-1792&m=dev" target="_blank" rel="noopener noreferrer">
|
||||
Figma - Example Usage
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Documentation:</strong>{' '}
|
||||
<code>shared/patterns/HeaderHeroSplitMedia/HeaderHeroSplitMedia.md</code>
|
||||
</div>
|
||||
</div>
|
||||
</PageGridCol>
|
||||
</PageGridRow>
|
||||
</PageGrid>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
236
shared/patterns/HeaderHeroSplitMedia/HeaderHeroSplitMedia.md
Normal file
236
shared/patterns/HeaderHeroSplitMedia/HeaderHeroSplitMedia.md
Normal file
@@ -0,0 +1,236 @@
|
||||
# HeaderHeroSplitMedia Pattern
|
||||
|
||||
A page-level hero pattern that pairs prominent editorial content with a primary media element in a split layout. Designed to introduce major concepts, products, or use cases while maintaining strong visual hierarchy and clear calls to action.
|
||||
|
||||
## Overview
|
||||
|
||||
Header Hero Split Media supports both neutral and accent surface treatments and adapts responsively across desktop, tablet, and mobile breakpoints while preserving a consistent internal structure.
|
||||
|
||||
## When to Use
|
||||
|
||||
- The page represents a high priority destination or thematic entry point
|
||||
- A strong headline and supporting narrative are required
|
||||
- Visual media reinforces the concept or story being introduced
|
||||
- One or two clear primary actions should be immediately visible
|
||||
- The page benefits from a balanced content and media relationship rather than a full bleed hero
|
||||
|
||||
## Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `surface` | `'default' \| 'accent'` | `'default'` | Default uses no background surface behind the hero title. AccentSurface adds an accent background with internal padding behind the hero title |
|
||||
| `layout` | `'content-left' \| 'content-right'` | `'content-left'` | Controls whether the content block appears on the left or right side of the media |
|
||||
| `title` | `string` | *required* | Hero title text (display-md typography) |
|
||||
| `subtitle` | `string` | *required* | Hero subtitle text (subhead-sm-l typography) |
|
||||
| `description` | `string` | - | Description text below title section (body-l typography) |
|
||||
| `primaryCta` | `{ label: string; href: string }` | - | Primary CTA button configuration |
|
||||
| `secondaryCta` | `{ label: string; href: string }` | - | Secondary/Tertiary CTA button configuration |
|
||||
| `media` | `{ src: string; alt: string }` | *required* | Hero media (image) configuration |
|
||||
| `className` | `string` | - | Additional CSS classes |
|
||||
|
||||
## Variants
|
||||
|
||||
### Theme
|
||||
|
||||
Theme is automatically controlled by the `html.light` and `html.dark` classes on the document root. The component will automatically adapt its colors based on the current theme.
|
||||
|
||||
- **Light**: White background with dark text (when `html.light` is present)
|
||||
- **Dark**: Dark background with light text (when `html.dark` is present)
|
||||
|
||||
### Surface
|
||||
|
||||
Controls the hero title section styling.
|
||||
|
||||
- **Default**: No background surface behind the hero title
|
||||
- **Accent**: Adds a green accent background with internal padding behind the hero title and subtitle
|
||||
|
||||
### Layout
|
||||
|
||||
Controls the position of content relative to media.
|
||||
|
||||
- **Content Left** (default): Content on the left, media on the right
|
||||
- **Content Right**: Content on the right, media on the left
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```tsx
|
||||
import { HeaderHeroSplitMedia } from '@/shared/patterns/HeaderHeroSplitMedia';
|
||||
|
||||
function MyPage() {
|
||||
return (
|
||||
<HeaderHeroSplitMedia
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions with developer tools and APIs."
|
||||
description="XRPL Payments Suite helps fintechs and payment providers move money fast, globally, and at low cost - all through simple APIs."
|
||||
primaryCta={{ label: "Get Started", href: "/docs/tutorials" }}
|
||||
secondaryCta={{ label: "Learn More", href: "/about" }}
|
||||
media={{ src: "/img/hero-tokenization.png", alt: "Tokenization illustration" }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Light Theme with Accent Surface
|
||||
|
||||
The theme is automatically controlled by the `html.light` class on the document root.
|
||||
|
||||
```tsx
|
||||
<HeaderHeroSplitMedia
|
||||
surface="accent"
|
||||
layout="content-left"
|
||||
title="Real-world asset tokenization"
|
||||
subtitle="Learn how to issue crypto tokens and build tokenization solutions."
|
||||
description="XRPL helps fintechs move money fast, globally, at low cost."
|
||||
primaryCta={{ label: "Primary Link", href: "/docs" }}
|
||||
secondaryCta={{ label: "Tertiary Link", href: "/learn" }}
|
||||
media={{ src: "/img/hero.png", alt: "Hero" }}
|
||||
/>
|
||||
```
|
||||
|
||||
### Dark Theme with Accent Surface
|
||||
|
||||
The theme is automatically controlled by the `html.dark` class on the document root.
|
||||
|
||||
```tsx
|
||||
<HeaderHeroSplitMedia
|
||||
surface="accent"
|
||||
layout="content-left"
|
||||
title="Build on the XRP Ledger"
|
||||
subtitle="Start developing with the most sustainable blockchain."
|
||||
description="Join thousands of developers building the future of finance."
|
||||
primaryCta={{ label: "Start Building", href: "/docs" }}
|
||||
secondaryCta={{ label: "View Tutorials", href: "/tutorials" }}
|
||||
media={{ src: "/img/hero-dark.png", alt: "XRPL Hero" }}
|
||||
/>
|
||||
```
|
||||
|
||||
### Content Right Layout
|
||||
|
||||
```tsx
|
||||
<HeaderHeroSplitMedia
|
||||
surface="default"
|
||||
layout="content-right"
|
||||
title="Enterprise Solutions"
|
||||
subtitle="Scale your business with blockchain technology."
|
||||
description="Leverage the XRP Ledger for enterprise-grade applications."
|
||||
primaryCta={{ label: "Contact Sales", href: "/contact" }}
|
||||
media={{ src: "/img/enterprise.png", alt: "Enterprise" }}
|
||||
/>
|
||||
```
|
||||
|
||||
### Minimal (No Description or Secondary CTA)
|
||||
|
||||
```tsx
|
||||
<HeaderHeroSplitMedia
|
||||
title="Quick Start Guide"
|
||||
subtitle="Get up and running in minutes."
|
||||
primaryCta={{ label: "Begin", href: "/quickstart" }}
|
||||
media={{ src: "/img/quickstart.png", alt: "Quick start" }}
|
||||
/>
|
||||
```
|
||||
|
||||
## Responsive Behavior
|
||||
|
||||
### Desktop (≥992px)
|
||||
- Side-by-side layout with content and media columns (6/12 columns each)
|
||||
- Media uses 1:1 aspect ratio
|
||||
- Gap between content and media columns: 8px
|
||||
- Horizontal gap between CTAs: 24px
|
||||
- Gap between description and CTA: 40px
|
||||
|
||||
### Tablet (576px - 991px)
|
||||
- Side-by-side layout maintained (4/8 columns each)
|
||||
- Media uses 2:1 aspect ratio (width:height)
|
||||
- Gap between content and media columns: 32px
|
||||
- Horizontal gap between CTAs: 24px
|
||||
- Gap between description and CTA: 24px
|
||||
|
||||
### Mobile (<576px)
|
||||
- Stacked layout (content above media, 4/4 columns each = full width)
|
||||
- Media uses 1:1 aspect ratio, full width
|
||||
- Gap between content and media columns: 32px
|
||||
- CTAs stack vertically with 16px gap
|
||||
- Gap between description and CTA: 24px
|
||||
|
||||
## Accent Surface Spacing
|
||||
|
||||
When using `surface="accent"`, the title section receives a green background with specific padding:
|
||||
|
||||
| Breakpoint | Padding Top | Padding Left/Right | Padding Bottom |
|
||||
|------------|-------------|-------------------|----------------|
|
||||
| Desktop | 16px | 16px | 24px |
|
||||
| Tablet | 16px | 16px | 24px |
|
||||
| Mobile | 8px | 8px | 16px |
|
||||
|
||||
## Anatomy
|
||||
|
||||
```
|
||||
HeaderHeroSplitMedia
|
||||
├── PageGrid Container (responsive padding)
|
||||
│ └── PageGrid.Row (flex layout with custom gap)
|
||||
│ ├── PageGrid.Col (content column)
|
||||
│ │ └── Content
|
||||
│ │ ├── TitleSurface (optional accent background)
|
||||
│ │ │ └── TitleGroup
|
||||
│ │ │ ├── Title (h1, display-md)
|
||||
│ │ │ └── Subtitle (p, sh-sm-l)
|
||||
│ │ └── DescriptionGroup
|
||||
│ │ ├── Description (p, body-l)
|
||||
│ │ └── CTA
|
||||
│ │ ├── Primary Button
|
||||
│ │ └── Tertiary Button
|
||||
│ └── PageGrid.Col (media column)
|
||||
│ └── Media
|
||||
│ └── Image (object-fit: cover)
|
||||
```
|
||||
|
||||
## CTA Guidelines
|
||||
|
||||
- **Use Primary and Tertiary buttons only** - Do not use Secondary buttons in this pattern
|
||||
- Secondary buttons introduce competing visual shapes and reduce clarity
|
||||
- Using Primary and Tertiary maintains clean hierarchy and avoids visual noise
|
||||
|
||||
## Media Guidelines
|
||||
|
||||
- Width is always used as the anchor when calculating height
|
||||
- Media spans the grid width defined by the layout
|
||||
- Aspect ratio rules by breakpoint:
|
||||
- Desktop: 1:1 ratio
|
||||
- Tablet: 2:1 ratio (W:H)
|
||||
- Mobile: 1:1 ratio
|
||||
|
||||
## CSS Classes
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `.bds-hero-split-media` | Root element |
|
||||
| `.bds-hero-split-media--default` | Default surface modifier |
|
||||
| `.bds-hero-split-media--accent` | Accent surface modifier |
|
||||
| `.bds-hero-split-media--content-left` | Content left layout |
|
||||
| `.bds-hero-split-media--content-right` | Content right layout |
|
||||
| `.bds-hero-split-media__container` | PageGrid container with responsive vertical padding |
|
||||
| `.bds-hero-split-media__row` | PageGrid.Row with custom gap spacing |
|
||||
| `.bds-hero-split-media__content-col` | PageGrid.Col wrapper for content |
|
||||
| `.bds-hero-split-media__content` | Content column |
|
||||
| `.bds-hero-split-media__title-surface` | Title background wrapper |
|
||||
| `.bds-hero-split-media__title-group` | Title + subtitle container |
|
||||
| `.bds-hero-split-media__title` | Main heading |
|
||||
| `.bds-hero-split-media__subtitle` | Subtitle text |
|
||||
| `.bds-hero-split-media__description-group` | Description + CTA container |
|
||||
| `.bds-hero-split-media__description` | Body text |
|
||||
| `.bds-hero-split-media__cta` | CTA buttons container |
|
||||
| `.bds-hero-split-media__media-col` | PageGrid.Col wrapper for media |
|
||||
| `.bds-hero-split-media__media` | Media column |
|
||||
| `.bds-hero-split-media__media-img` | Media image |
|
||||
|
||||
**Note:** This pattern uses the `PageGrid` component system. The container uses `PageGrid` (`.bds-grid__container`), rows use `PageGrid.Row` (`.bds-grid__row`), and columns use `PageGrid.Col` (`.bds-grid__col-*`). Custom classes are applied for pattern-specific styling.
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Uses semantic `<section>` element for the pattern container
|
||||
- Title uses `<h1>` heading for proper document structure
|
||||
- Media requires `alt` text for screen readers
|
||||
- Buttons inherit accessible labels from the Button component
|
||||
- Color contrast ratios meet WCAG 2.1 AA standards
|
||||
428
shared/patterns/HeaderHeroSplitMedia/HeaderHeroSplitMedia.scss
Normal file
428
shared/patterns/HeaderHeroSplitMedia/HeaderHeroSplitMedia.scss
Normal file
@@ -0,0 +1,428 @@
|
||||
// HeaderHeroSplitMedia Pattern Styles
|
||||
// =============================================================================
|
||||
// A page-level hero pattern with split content and media layout.
|
||||
// Supports theme (light/dark), surface (default/accent), and layout variants.
|
||||
|
||||
// Helper mixin to combine typography properties from two tokens
|
||||
// Uses font-size from $size-token, line-height and letter-spacing from $spacing-token
|
||||
@mixin _type-mixed($size-token, $spacing-token) {
|
||||
$size-t: map-get($type-scale, $size-token);
|
||||
$spacing-t: map-get($type-scale, $spacing-token);
|
||||
|
||||
font-family: map-get($spacing-t, font);
|
||||
font-weight: map-get($spacing-t, weight);
|
||||
|
||||
// Mobile
|
||||
$size-mobile: map-get($size-t, mobile);
|
||||
$spacing-mobile: map-get($spacing-t, mobile);
|
||||
font-size: map-get($size-mobile, size);
|
||||
line-height: map-get($spacing-mobile, line);
|
||||
letter-spacing: map-get($spacing-mobile, letter);
|
||||
|
||||
// Tablet
|
||||
@include media-breakpoint-up(md) {
|
||||
$size-tablet: map-get($size-t, tablet);
|
||||
$spacing-tablet: map-get($spacing-t, tablet);
|
||||
font-size: map-get($size-tablet, size);
|
||||
line-height: map-get($spacing-tablet, line);
|
||||
letter-spacing: map-get($spacing-tablet, letter);
|
||||
}
|
||||
|
||||
// Desktop
|
||||
@include media-breakpoint-up(lg) {
|
||||
$size-desktop: map-get($size-t, desktop);
|
||||
$spacing-desktop: map-get($spacing-t, desktop);
|
||||
font-size: map-get($size-desktop, size);
|
||||
line-height: map-get($spacing-desktop, line);
|
||||
letter-spacing: map-get($spacing-desktop, letter);
|
||||
}
|
||||
}
|
||||
//
|
||||
// BEM Naming Convention:
|
||||
// .bds-hero-split-media - Root element
|
||||
// .bds-hero-split-media--default - Default surface (no background)
|
||||
// .bds-hero-split-media--accent - Accent surface (green background on title)
|
||||
// .bds-hero-split-media--content-left - Content on left, media on right
|
||||
// .bds-hero-split-media--content-right - Content on right, media on left
|
||||
// .bds-hero-split-media__container - PageGrid container with vertical padding
|
||||
// .bds-hero-split-media__row - PageGrid.Row with custom gap spacing
|
||||
// .bds-hero-split-media__content-col - PageGrid.Col wrapper for content
|
||||
// .bds-hero-split-media__content - Content column (title + description)
|
||||
// .bds-hero-split-media__title-surface - Optional accent background wrapper
|
||||
// .bds-hero-split-media__title-group - Title + subtitle container
|
||||
// .bds-hero-split-media__title - Main heading (display-md)
|
||||
// .bds-hero-split-media__subtitle - Subtitle text (sh-sm-l)
|
||||
// .bds-hero-split-media__description-group - Description + CTA container
|
||||
// .bds-hero-split-media__description - Body text (body-l)
|
||||
// .bds-hero-split-media__cta - CTA buttons container
|
||||
// .bds-hero-split-media__media-col - PageGrid.Col wrapper for media
|
||||
// .bds-hero-split-media__media - Media column
|
||||
// .bds-hero-split-media__media-img - Media image
|
||||
|
||||
// =============================================================================
|
||||
// Design Tokens
|
||||
// =============================================================================
|
||||
|
||||
// Colors - using design tokens from _colors.scss
|
||||
$bds-hero-accent-bg: $green-200; // #70EE97 - Accent surface background
|
||||
$bds-hero-light-bg: $white; // Light theme background
|
||||
$bds-hero-dark-bg: $black; // #141414 - Dark theme background (neutral/black)
|
||||
$bds-hero-title-color: $black; // #141414 - Title text color (neutral/black)
|
||||
$bds-hero-title-color-dark: $white; // #FFFFFF - Title text color in dark mode
|
||||
$bds-hero-description-light: $gray-500; // #72777E - Description text in light mode (neutral/500)
|
||||
$bds-hero-description-dark: $gray-200; // #E6EAF0 - Description text in dark mode (neutral/200)
|
||||
|
||||
// Spacing - Desktop (≥992px)
|
||||
$bds-hero-desktop-container-py: 40px;
|
||||
$bds-hero-desktop-title-surface-pt: 16px;
|
||||
$bds-hero-desktop-title-surface-px: 16px;
|
||||
$bds-hero-desktop-title-surface-pb: 24px;
|
||||
$bds-hero-desktop-title-gap: 16px;
|
||||
$bds-hero-desktop-description-gap: 40px;
|
||||
$bds-hero-desktop-cta-gap: 24px;
|
||||
$bds-hero-desktop-content-gap: 8px;
|
||||
|
||||
// Spacing - Tablet (576px - 991px)
|
||||
// Base values for DEFAULT surface
|
||||
$bds-hero-tablet-container-py: 32px;
|
||||
$bds-hero-tablet-title-surface-pt: 16px;
|
||||
$bds-hero-tablet-title-surface-px: 16px;
|
||||
$bds-hero-tablet-title-surface-pb: 24px;
|
||||
$bds-hero-tablet-title-gap: 8px; // Default: 8px, Accent: 16px
|
||||
$bds-hero-tablet-description-gap: 32px; // Default: 32px, Accent: 24px
|
||||
$bds-hero-tablet-cta-gap: 16px; // Both: 16px
|
||||
$bds-hero-tablet-content-gap: 32px; // Default: 32px, Accent: 40px
|
||||
// Accent-specific tablet spacing
|
||||
$bds-hero-tablet-accent-title-gap: 16px;
|
||||
$bds-hero-tablet-accent-description-gap: 24px;
|
||||
$bds-hero-tablet-accent-content-gap: 40px;
|
||||
|
||||
// Spacing - Mobile (<576px)
|
||||
$bds-hero-mobile-container-py: 24px;
|
||||
$bds-hero-mobile-title-surface-pt: 8px;
|
||||
$bds-hero-mobile-title-surface-px: 8px;
|
||||
$bds-hero-mobile-title-surface-pb: 16px;
|
||||
$bds-hero-mobile-title-gap: 8px;
|
||||
$bds-hero-mobile-description-gap: 24px;
|
||||
$bds-hero-mobile-cta-gap: 16px;
|
||||
$bds-hero-mobile-content-gap: 32px;
|
||||
|
||||
// =============================================================================
|
||||
// Base Styles
|
||||
// =============================================================================
|
||||
|
||||
.bds-hero-split-media {
|
||||
width: 100%;
|
||||
|
||||
// Container - uses PageGrid container, adds vertical padding
|
||||
&__container {
|
||||
// Mobile vertical padding
|
||||
padding-top: $bds-hero-mobile-container-py;
|
||||
padding-bottom: $bds-hero-mobile-container-py;
|
||||
|
||||
// Tablet vertical padding
|
||||
@include media-breakpoint-up(md) {
|
||||
padding-top: $bds-hero-tablet-container-py;
|
||||
padding-bottom: $bds-hero-tablet-container-py;
|
||||
}
|
||||
|
||||
// Desktop vertical padding
|
||||
@include media-breakpoint-up(lg) {
|
||||
padding-top: $bds-hero-desktop-container-py;
|
||||
padding-bottom: $bds-hero-desktop-container-py;
|
||||
}
|
||||
}
|
||||
|
||||
// Row - uses PageGrid.Row, override gap for custom spacing
|
||||
&__row {
|
||||
// Override PageGrid default gap with custom spacing
|
||||
gap: $bds-hero-mobile-content-gap;
|
||||
|
||||
// Tablet gap
|
||||
@include media-breakpoint-up(md) {
|
||||
gap: $bds-hero-tablet-content-gap;
|
||||
}
|
||||
|
||||
// Desktop gap
|
||||
@include media-breakpoint-up(lg) {
|
||||
gap: $bds-hero-desktop-content-gap;
|
||||
}
|
||||
}
|
||||
|
||||
// Content column wrapper - uses PageGrid.Col
|
||||
&__content-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
// Content column
|
||||
&__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
|
||||
// Tablet & Desktop - match media height
|
||||
@include media-breakpoint-up(md) {
|
||||
min-height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// Title surface - wrapper for accent background
|
||||
// Default surface has no background or padding (see .bds-hero-split-media--accent modifier)
|
||||
// Styles are applied via .bds-hero-split-media--accent modifier only
|
||||
|
||||
// Title group - contains title and subtitle
|
||||
// Text width constraints: 4/4 mobile, 6/8 tablet, 5/12 desktop
|
||||
&__title-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $bds-hero-mobile-title-gap;
|
||||
// Mobile: full width (4/4)
|
||||
max-width: 100%;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
gap: $bds-hero-tablet-title-gap;
|
||||
// Tablet: 6/8 of grid, column is 8/8 (full width), so text = 6/8 = 75%
|
||||
max-width: 75%;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
gap: $bds-hero-desktop-title-gap;
|
||||
// Desktop: 5/12 of grid, column is 6/12, so text = 5/6 of column
|
||||
max-width: calc(5 / 6 * 100%);
|
||||
}
|
||||
}
|
||||
|
||||
// Title - main heading
|
||||
&__title {
|
||||
color: $bds-hero-title-color;
|
||||
@include type(display-md);
|
||||
margin: 0; // Override mixin's margin-bottom from pspace
|
||||
}
|
||||
|
||||
// Subtitle
|
||||
// Uses font-size from subhead-sm-r, line-height and letter-spacing from subhead-sm-l
|
||||
&__subtitle {
|
||||
color: $bds-hero-title-color;
|
||||
@include _type-mixed(subhead-sm-r, subhead-sm-l);
|
||||
margin: 0; // Override mixin's margin-bottom from pspace
|
||||
}
|
||||
|
||||
// Description group - contains body text and CTA
|
||||
&__description-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $bds-hero-mobile-description-gap;
|
||||
margin-top: $bds-hero-mobile-content-gap;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
gap: $bds-hero-tablet-description-gap;
|
||||
margin-top: $bds-hero-tablet-content-gap; // Gap between title and description on tablet
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
gap: $bds-hero-desktop-description-gap;
|
||||
margin-top: 0; // Desktop uses space-between, no explicit margin needed
|
||||
}
|
||||
}
|
||||
|
||||
// Description text
|
||||
// Text width constraints: 4/4 mobile, 6/8 tablet, 5/12 desktop
|
||||
&__description {
|
||||
color: $bds-hero-description-light;
|
||||
@include type(body-l);
|
||||
margin: 0; // Override mixin's margin-bottom from pspace
|
||||
// Mobile: full width (4/4)
|
||||
max-width: 100%;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
// Tablet: 6/8 of grid, column is 8/8 (full width), so text = 6/8 = 75%
|
||||
max-width: 75%;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
// Desktop: 5/12 of grid, column is 6/12, so text = 5/6 of column
|
||||
max-width: calc(5 / 6 * 100%);
|
||||
}
|
||||
}
|
||||
|
||||
// CTA buttons container
|
||||
&__cta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start; // Prevent buttons from stretching to full width on mobile
|
||||
|
||||
// Tablet & Desktop - horizontal layout
|
||||
@include media-breakpoint-up(md) {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
// Media column wrapper - uses PageGrid.Col
|
||||
&__media-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
// Media column
|
||||
&__media {
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
overflow: hidden;
|
||||
|
||||
// Tablet - 2:1 aspect ratio
|
||||
@include media-breakpoint-up(md) {
|
||||
aspect-ratio: 2 / 1;
|
||||
}
|
||||
|
||||
// Desktop - 1:1 aspect ratio
|
||||
@include media-breakpoint-up(lg) {
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Media image
|
||||
&__media-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Theme Styles (controlled by html.light/html.dark classes)
|
||||
// =============================================================================
|
||||
|
||||
// Light theme (default)
|
||||
html.light {
|
||||
.bds-hero-split-media {
|
||||
background-color: $bds-hero-light-bg;
|
||||
|
||||
&__title,
|
||||
&__subtitle {
|
||||
color: $bds-hero-title-color;
|
||||
}
|
||||
|
||||
&__description {
|
||||
color: $bds-hero-description-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dark theme
|
||||
html.dark {
|
||||
.bds-hero-split-media {
|
||||
background-color: $bds-hero-dark-bg;
|
||||
|
||||
&__title,
|
||||
&__subtitle {
|
||||
color: $bds-hero-title-color-dark;
|
||||
}
|
||||
|
||||
&__description {
|
||||
color: $bds-hero-description-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Surface Modifiers
|
||||
// =============================================================================
|
||||
|
||||
// Accent surface - green background on title section
|
||||
.bds-hero-split-media--accent {
|
||||
.bds-hero-split-media__title-surface {
|
||||
background-color: $bds-hero-accent-bg;
|
||||
|
||||
// Mobile padding
|
||||
padding: $bds-hero-mobile-title-surface-pt $bds-hero-mobile-title-surface-px $bds-hero-mobile-title-surface-pb;
|
||||
|
||||
// Tablet padding
|
||||
@include media-breakpoint-up(md) {
|
||||
padding: $bds-hero-tablet-title-surface-pt $bds-hero-tablet-title-surface-px $bds-hero-tablet-title-surface-pb;
|
||||
}
|
||||
|
||||
// Desktop padding
|
||||
@include media-breakpoint-up(lg) {
|
||||
padding: $bds-hero-desktop-title-surface-pt $bds-hero-desktop-title-surface-px $bds-hero-desktop-title-surface-pb;
|
||||
}
|
||||
}
|
||||
|
||||
// Title and subtitle always use dark text on accent surface (light mode)
|
||||
.bds-hero-split-media__title,
|
||||
.bds-hero-split-media__subtitle {
|
||||
color: $bds-hero-title-color;
|
||||
}
|
||||
|
||||
// Accent surface has different spacing on tablet
|
||||
.bds-hero-split-media__title-group {
|
||||
@include media-breakpoint-up(md) {
|
||||
gap: $bds-hero-tablet-accent-title-gap;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
gap: $bds-hero-desktop-title-gap;
|
||||
}
|
||||
}
|
||||
|
||||
.bds-hero-split-media__description-group {
|
||||
@include media-breakpoint-up(md) {
|
||||
gap: $bds-hero-tablet-accent-description-gap;
|
||||
margin-top: $bds-hero-tablet-accent-content-gap;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
gap: $bds-hero-desktop-description-gap;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Accent surface in dark mode - ensure black text on green background
|
||||
// Higher specificity needed to override html.dark rules
|
||||
html.dark .bds-hero-split-media--accent {
|
||||
.bds-hero-split-media__title,
|
||||
.bds-hero-split-media__subtitle {
|
||||
color: $bds-hero-title-color; // #141414 - always black on green accent
|
||||
}
|
||||
}
|
||||
|
||||
html.light .bds-hero-split-media--accent {
|
||||
.bds-hero-split-media__title,
|
||||
.bds-hero-split-media__subtitle {
|
||||
color: $bds-hero-title-color; // #141414 - always black on green accent
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Layout Modifiers
|
||||
// =============================================================================
|
||||
|
||||
// Content right layout - order is handled by component JSX
|
||||
// No CSS needed as column order is controlled by React component order
|
||||
|
||||
// =============================================================================
|
||||
// Optional Content Modifiers
|
||||
// =============================================================================
|
||||
|
||||
// Title only - no description or CTAs
|
||||
// When there's no description group content, the title section should expand
|
||||
.bds-hero-split-media--title-only {
|
||||
.bds-hero-split-media__content {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
// No description but has CTAs
|
||||
// CTAs should be positioned closer to title without extra gap
|
||||
.bds-hero-split-media--no-description {
|
||||
.bds-hero-split-media__description-group {
|
||||
// Remove the gap since there's no description text
|
||||
gap: 0;
|
||||
}
|
||||
}
|
||||
171
shared/patterns/HeaderHeroSplitMedia/HeaderHeroSplitMedia.tsx
Normal file
171
shared/patterns/HeaderHeroSplitMedia/HeaderHeroSplitMedia.tsx
Normal file
@@ -0,0 +1,171 @@
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { Button } from '../../components/Button/Button';
|
||||
import { PageGrid } from '../../components/PageGrid/page-grid';
|
||||
|
||||
export interface HeaderHeroSplitMediaProps {
|
||||
/** Surface variant - 'accent' adds green background behind hero title */
|
||||
surface?: 'default' | 'accent';
|
||||
/** Layout direction - content on left or right of media */
|
||||
layout?: 'content-left' | 'content-right';
|
||||
/** Hero title text (display-md typography) */
|
||||
title: string;
|
||||
/** Hero subtitle text (subhead-sm-l typography) */
|
||||
subtitle: string;
|
||||
/** Description text below title section (body-l typography) */
|
||||
description?: string;
|
||||
/** Primary CTA button configuration */
|
||||
primaryCta?: {
|
||||
label: string;
|
||||
href: string;
|
||||
};
|
||||
/** Secondary/Tertiary CTA button configuration */
|
||||
secondaryCta?: {
|
||||
label: string;
|
||||
href: string;
|
||||
};
|
||||
/** Hero media (image) configuration */
|
||||
media: {
|
||||
src: string;
|
||||
alt: string;
|
||||
};
|
||||
/** Additional CSS classes */
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* HeaderHeroSplitMedia Pattern
|
||||
*
|
||||
* A page-level hero pattern that pairs prominent editorial content with a primary
|
||||
* media element in a split layout. Designed to introduce major concepts, products,
|
||||
* or use cases while maintaining strong visual hierarchy and clear calls to action.
|
||||
*
|
||||
* Uses the PageGrid component system for responsive layout:
|
||||
* - Mobile: Stacked layout (columns 4/4 each, text spans full width)
|
||||
* - Tablet: Stacked layout (columns 8/8 each, text constrained to 6/8 = 75%)
|
||||
* - Desktop: Side-by-side (columns 6/12 each, text constrained to 5/12 ≈ 83.33%)
|
||||
*
|
||||
* Supports:
|
||||
* - Theme: Automatically controlled by html.light/html.dark classes
|
||||
* - Surface: Default (no background) / Accent (green background on title section)
|
||||
* - Layout: Content Left / Content Right
|
||||
* - Responsive: Desktop (side-by-side 1:1), Tablet (stacked), Mobile (stacked)
|
||||
*
|
||||
* @example
|
||||
* <HeaderHeroSplitMedia
|
||||
* surface="accent"
|
||||
* layout="content-left"
|
||||
* title="Real-world asset tokenization"
|
||||
* subtitle="Learn how to issue crypto tokens and build tokenization solutions"
|
||||
* description="XRPL helps fintechs move money fast, globally, at low cost."
|
||||
* primaryCta={{ label: "Get Started", href: "/docs" }}
|
||||
* secondaryCta={{ label: "Learn More", href: "/about" }}
|
||||
* media={{ src: "/img/hero.png", alt: "Hero illustration" }}
|
||||
* />
|
||||
*/
|
||||
export const HeaderHeroSplitMedia: React.FC<HeaderHeroSplitMediaProps> = ({
|
||||
surface = 'default',
|
||||
layout = 'content-left',
|
||||
title,
|
||||
subtitle,
|
||||
description,
|
||||
primaryCta,
|
||||
secondaryCta,
|
||||
media,
|
||||
className,
|
||||
}) => {
|
||||
// Determine if we have any description group content
|
||||
const hasDescriptionGroupContent = description || primaryCta || secondaryCta;
|
||||
|
||||
// Build root class names
|
||||
const rootClasses = clsx(
|
||||
'bds-hero-split-media',
|
||||
`bds-hero-split-media--${surface}`,
|
||||
`bds-hero-split-media--${layout}`,
|
||||
{
|
||||
'bds-hero-split-media--title-only': !hasDescriptionGroupContent,
|
||||
'bds-hero-split-media--no-description': !description && hasDescriptionGroupContent,
|
||||
},
|
||||
className
|
||||
);
|
||||
|
||||
// Render hero content section
|
||||
const renderHeroContent = () => (
|
||||
<div className="bds-hero-split-media__content">
|
||||
{/* Hero Title Section */}
|
||||
<div className="bds-hero-split-media__title-surface">
|
||||
<div className="bds-hero-split-media__title-group">
|
||||
<h1 className="bds-hero-split-media__title">{title}</h1>
|
||||
<p className="bds-hero-split-media__subtitle">{subtitle}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Hero Description & CTA Section - only render if there's content */}
|
||||
{hasDescriptionGroupContent && (
|
||||
<div className="bds-hero-split-media__description-group">
|
||||
{description && (
|
||||
<p className="bds-hero-split-media__description">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* CTA Buttons */}
|
||||
{(primaryCta || secondaryCta) && (
|
||||
<div className="bds-hero-split-media__cta">
|
||||
{primaryCta && (
|
||||
<Button
|
||||
variant="primary"
|
||||
href={primaryCta.href}
|
||||
>
|
||||
{primaryCta.label}
|
||||
</Button>
|
||||
)}
|
||||
{secondaryCta && (
|
||||
<Button
|
||||
variant="tertiary"
|
||||
href={secondaryCta.href}
|
||||
>
|
||||
{secondaryCta.label}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
// Render hero media section
|
||||
const renderHeroMedia = () => (
|
||||
<div className="bds-hero-split-media__media">
|
||||
<img
|
||||
src={media.src}
|
||||
alt={media.alt}
|
||||
className="bds-hero-split-media__media-img"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<section className={rootClasses}>
|
||||
<PageGrid className="bds-hero-split-media__container">
|
||||
<PageGrid.Row className="bds-hero-split-media__row">
|
||||
<PageGrid.Col
|
||||
span={{ base: 4, md: 8, lg: 6 }}
|
||||
className="bds-hero-split-media__content-col"
|
||||
>
|
||||
{renderHeroContent()}
|
||||
</PageGrid.Col>
|
||||
<PageGrid.Col
|
||||
span={{ base: 4, md: 8, lg: 6 }}
|
||||
className="bds-hero-split-media__media-col"
|
||||
>
|
||||
{renderHeroMedia()}
|
||||
</PageGrid.Col>
|
||||
</PageGrid.Row>
|
||||
</PageGrid>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeaderHeroSplitMedia;
|
||||
2
shared/patterns/HeaderHeroSplitMedia/index.ts
Normal file
2
shared/patterns/HeaderHeroSplitMedia/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { HeaderHeroSplitMedia } from './HeaderHeroSplitMedia';
|
||||
export type { HeaderHeroSplitMediaProps } from './HeaderHeroSplitMedia';
|
||||
@@ -9647,14 +9647,14 @@ p {
|
||||
font-size: 14px;
|
||||
line-height: 20.1px;
|
||||
letter-spacing: 0px;
|
||||
margin-bottom: 18px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.label-r {
|
||||
font-size: 14px;
|
||||
line-height: 20.1px;
|
||||
letter-spacing: 0px;
|
||||
margin-bottom: 18px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
@@ -9662,7 +9662,7 @@ p {
|
||||
font-size: 16px;
|
||||
line-height: 23.2px;
|
||||
letter-spacing: 0px;
|
||||
margin-bottom: 18px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16363,6 +16363,299 @@ html.light .bds-card-icon--disabled.bds-card-icon--green .bds-card-icon__icon-im
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.bds-hero-split-media {
|
||||
width: 100%;
|
||||
}
|
||||
.bds-hero-split-media__container {
|
||||
padding-top: 24px;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media__container {
|
||||
padding-top: 32px;
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.bds-hero-split-media__container {
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
}
|
||||
.bds-hero-split-media__row {
|
||||
gap: 32px;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media__row {
|
||||
gap: 32px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.bds-hero-split-media__row {
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
.bds-hero-split-media__content-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.bds-hero-split-media__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media__content {
|
||||
min-height: 100%;
|
||||
}
|
||||
}
|
||||
.bds-hero-split-media__title-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
max-width: 100%;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media__title-group {
|
||||
gap: 8px;
|
||||
max-width: 75%;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.bds-hero-split-media__title-group {
|
||||
gap: 16px;
|
||||
max-width: 83.3333333333%;
|
||||
}
|
||||
}
|
||||
.bds-hero-split-media__title {
|
||||
color: #141414;
|
||||
font-family: "Tobias", "Noto Serif", monospace;
|
||||
font-weight: 300;
|
||||
font-size: 48px;
|
||||
line-height: 53px;
|
||||
letter-spacing: -2px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media__title {
|
||||
font-size: 60px;
|
||||
line-height: 66px;
|
||||
letter-spacing: -2px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.bds-hero-split-media__title {
|
||||
font-size: 72px;
|
||||
line-height: 75.6px;
|
||||
letter-spacing: -3px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
.bds-hero-split-media__title {
|
||||
margin: 0;
|
||||
}
|
||||
.bds-hero-split-media__subtitle {
|
||||
color: #141414;
|
||||
font-family: "Booton", "Noto Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
font-weight: 300;
|
||||
font-size: 18px;
|
||||
line-height: 23px;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media__subtitle {
|
||||
font-size: 18px;
|
||||
line-height: 23px;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.bds-hero-split-media__subtitle {
|
||||
font-size: 24px;
|
||||
line-height: 30px;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
}
|
||||
.bds-hero-split-media__subtitle {
|
||||
margin: 0;
|
||||
}
|
||||
.bds-hero-split-media__description-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
margin-top: 32px;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media__description-group {
|
||||
gap: 32px;
|
||||
margin-top: 32px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.bds-hero-split-media__description-group {
|
||||
gap: 40px;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
.bds-hero-split-media__description {
|
||||
color: #72777E;
|
||||
font-family: "Booton", "Noto Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
font-weight: 300;
|
||||
font-size: 16px;
|
||||
line-height: 23.2px;
|
||||
letter-spacing: 0px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media__description {
|
||||
font-size: 16px;
|
||||
line-height: 23.2px;
|
||||
letter-spacing: 0px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.bds-hero-split-media__description {
|
||||
font-size: 18px;
|
||||
line-height: 26.1px;
|
||||
letter-spacing: -0.5px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
.bds-hero-split-media__description {
|
||||
margin: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media__description {
|
||||
max-width: 75%;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.bds-hero-split-media__description {
|
||||
max-width: 83.3333333333%;
|
||||
}
|
||||
}
|
||||
.bds-hero-split-media__cta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media__cta {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.bds-hero-split-media__media-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.bds-hero-split-media__media {
|
||||
width: 100%;
|
||||
aspect-ratio: 1/1;
|
||||
overflow: hidden;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media__media {
|
||||
aspect-ratio: 2/1;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.bds-hero-split-media__media {
|
||||
aspect-ratio: 1/1;
|
||||
}
|
||||
}
|
||||
.bds-hero-split-media__media-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
html.light .bds-hero-split-media {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
html.light .bds-hero-split-media__title, html.light .bds-hero-split-media__subtitle {
|
||||
color: #141414;
|
||||
}
|
||||
html.light .bds-hero-split-media__description {
|
||||
color: #72777E;
|
||||
}
|
||||
|
||||
html.dark .bds-hero-split-media {
|
||||
background-color: #141414;
|
||||
}
|
||||
html.dark .bds-hero-split-media__title, html.dark .bds-hero-split-media__subtitle {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
html.dark .bds-hero-split-media__description {
|
||||
color: #E6EAF0;
|
||||
}
|
||||
|
||||
.bds-hero-split-media--accent .bds-hero-split-media__title-surface {
|
||||
background-color: #70EE97;
|
||||
padding: 8px 8px 16px;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media--accent .bds-hero-split-media__title-surface {
|
||||
padding: 16px 16px 24px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.bds-hero-split-media--accent .bds-hero-split-media__title-surface {
|
||||
padding: 16px 16px 24px;
|
||||
}
|
||||
}
|
||||
.bds-hero-split-media--accent .bds-hero-split-media__title,
|
||||
.bds-hero-split-media--accent .bds-hero-split-media__subtitle {
|
||||
color: #141414;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media--accent .bds-hero-split-media__title-group {
|
||||
gap: 16px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.bds-hero-split-media--accent .bds-hero-split-media__title-group {
|
||||
gap: 16px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.bds-hero-split-media--accent .bds-hero-split-media__description-group {
|
||||
gap: 24px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.bds-hero-split-media--accent .bds-hero-split-media__description-group {
|
||||
gap: 40px;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
html.dark .bds-hero-split-media--accent .bds-hero-split-media__title,
|
||||
html.dark .bds-hero-split-media--accent .bds-hero-split-media__subtitle {
|
||||
color: #141414;
|
||||
}
|
||||
|
||||
html.light .bds-hero-split-media--accent .bds-hero-split-media__title,
|
||||
html.light .bds-hero-split-media--accent .bds-hero-split-media__subtitle {
|
||||
color: #141414;
|
||||
}
|
||||
|
||||
.bds-hero-split-media--title-only .bds-hero-split-media__content {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.bds-hero-split-media--no-description .bds-hero-split-media__description-group {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
color: #FFFFFF;
|
||||
background-color: #232325;
|
||||
|
||||
BIN
static/img/demo-bg.png
Normal file
BIN
static/img/demo-bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
@@ -96,6 +96,7 @@ $line-height-base: 1.5;
|
||||
@import "../shared/components/CardImage/CardImage.scss";
|
||||
@import "../shared/components/TileLogo/TileLogo.scss";
|
||||
@import "../shared/components/CardIcon/CardIcon.scss";
|
||||
@import "../shared/patterns/HeaderHeroSplitMedia/HeaderHeroSplitMedia.scss";
|
||||
@import "_code-tabs.scss";
|
||||
@import "_code-walkthrough.scss";
|
||||
@import "_diagrams.scss";
|
||||
|
||||
Reference in New Issue
Block a user