Files
xrpl-dev-portal/shared/sections/HeaderHeroSplitMedia/HeaderHeroSplitMedia.scss
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

430 lines
15 KiB
SCSS

// 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)
// Note: Uses centralized spacing tokens from _spacing.scss.
$bds-hero-desktop-container-py: $bds-space-4xl; // 40px - spacing('4xl')
$bds-hero-desktop-title-surface-pt: $bds-space-lg; // 16px - spacing('lg')
$bds-hero-desktop-title-surface-px: $bds-space-lg; // 16px - spacing('lg')
$bds-hero-desktop-title-surface-pb: $bds-space-2xl; // 24px - spacing('2xl')
$bds-hero-desktop-title-gap: $bds-space-lg; // 16px - spacing('lg')
$bds-hero-desktop-description-gap: $bds-space-4xl; // 40px - spacing('4xl')
$bds-hero-desktop-cta-gap: $bds-space-2xl; // 24px - spacing('2xl')
$bds-hero-desktop-content-gap: $bds-space-sm; // 8px - spacing('sm')
// Spacing - Tablet (576px - 991px)
// Base values for DEFAULT surface
$bds-hero-tablet-container-py: $bds-space-3xl; // 32px - spacing('3xl')
$bds-hero-tablet-title-surface-pt: $bds-space-lg; // 16px - spacing('lg')
$bds-hero-tablet-title-surface-px: $bds-space-lg; // 16px - spacing('lg')
$bds-hero-tablet-title-surface-pb: $bds-space-2xl; // 24px - spacing('2xl')
$bds-hero-tablet-title-gap: $bds-space-sm; // 8px - spacing('sm')
$bds-hero-tablet-description-gap: $bds-space-3xl; // 32px - spacing('3xl')
$bds-hero-tablet-cta-gap: $bds-space-lg; // 16px - spacing('lg')
$bds-hero-tablet-content-gap: $bds-space-3xl; // 32px - spacing('3xl')
// Accent-specific tablet spacing
$bds-hero-tablet-accent-title-gap: $bds-space-lg; // 16px - spacing('lg')
$bds-hero-tablet-accent-description-gap: $bds-space-2xl; // 24px - spacing('2xl')
$bds-hero-tablet-accent-content-gap: $bds-space-4xl; // 40px - spacing('4xl')
// Spacing - Mobile (<576px)
$bds-hero-mobile-container-py: $bds-space-2xl; // 24px - spacing('2xl')
$bds-hero-mobile-title-surface-pt: $bds-space-sm; // 8px - spacing('sm')
$bds-hero-mobile-title-surface-px: $bds-space-sm; // 8px - spacing('sm')
$bds-hero-mobile-title-surface-pb: $bds-space-lg; // 16px - spacing('lg')
$bds-hero-mobile-title-gap: $bds-space-sm; // 8px - spacing('sm')
$bds-hero-mobile-description-gap: $bds-space-2xl; // 24px - spacing('2xl')
$bds-hero-mobile-cta-gap: $bds-space-lg; // 16px - spacing('lg')
$bds-hero-mobile-content-gap: $bds-space-3xl; // 32px - spacing('3xl')
// =============================================================================
// 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 - 16:9 aspect ratio based on 8-column grid width
@include media-breakpoint-up(md) {
aspect-ratio: 16 / 9;
}
// 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, align title to top
.bds-hero-split-media--title-only {
.bds-hero-split-media__content {
justify-content: flex-start;
}
}
// 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;
}
}