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

293 lines
9.5 KiB
SCSS

// BDS CarouselCardList Pattern Styles
// Brand Design System - Horizontal scrolling carousel with CardOffgrid components
//
// Naming Convention: BEM with 'bds' namespace
// .bds-carousel-card-list - Base section container
// .bds-carousel-card-list--neutral - Neutral color variant
// .bds-carousel-card-list--green - Green color variant
// .bds-carousel-card-list__header - Header wrapper (title, subtitle, nav)
// .bds-carousel-card-list__header-content - Title and subtitle wrapper
// .bds-carousel-card-list__heading - Section heading (uses .h-md)
// .bds-carousel-card-list__description - Section description (uses .body-l)
// .bds-carousel-card-list__nav - Navigation buttons wrapper
// .bds-carousel-card-list__track-wrapper - Scroll container wrapper
// .bds-carousel-card-list__track - Horizontal scroll track
// .bds-carousel-card-list__card - Individual card wrapper
//
// Note: Navigation button styles are in shared/components/CarouselButton/CarouselButton.scss
// =============================================================================
// Design Tokens (from Figma)
// =============================================================================
// Note: Uses centralized spacing tokens from _spacing.scss.
// $bds-grid-gutter is defined in _spacing.scss (8px).
// Grid padding (matches PageGrid container padding)
$bds-carousel-grid-padding-sm: 18px; // Mobile (non-standard)
$bds-carousel-grid-padding-md: $bds-space-2xl; // 24px - spacing('2xl')
$bds-carousel-grid-padding-lg: $bds-space-3xl; // 32px - spacing('3xl')
$bds-carousel-grid-max-width: 1280px; // Max container width (per _breakpoints.scss $xl)
// Spacing - Header gap (between heading and description)
$bds-carousel-header-gap-sm: $bds-space-sm; // 8px - spacing('sm')
$bds-carousel-header-gap-md: $bds-space-sm; // 8px - spacing('sm')
$bds-carousel-header-gap-lg: $bds-space-lg; // 16px - spacing('lg')
// Spacing - Section gap (between header content and buttons row on mobile)
$bds-carousel-section-gap-sm: $bds-space-2xl; // 24px - spacing('2xl')
$bds-carousel-section-gap-md: $bds-space-3xl; // 32px - spacing('3xl')
$bds-carousel-section-gap-lg: $bds-space-4xl; // 40px - spacing('4xl')
// Spacing - Gap between header and cards
$bds-carousel-cards-gap-sm: $bds-space-2xl; // 24px - spacing('2xl')
$bds-carousel-cards-gap-md: $bds-space-3xl; // 32px - spacing('3xl')
$bds-carousel-cards-gap-lg: $bds-space-4xl; // 40px - spacing('4xl')
// Button gap (button styles are in shared/components/CarouselButton)
$bds-carousel-button-gap: $bds-space-sm; // 8px - spacing('sm')
// Card dimensions per breakpoint
$bds-carousel-card-width-sm: 343px; // Mobile
$bds-carousel-card-height-sm: 400px;
$bds-carousel-card-width-md: 356px; // Tablet
$bds-carousel-card-height-md: 440px;
$bds-carousel-card-width-lg: 400px; // Desktop
$bds-carousel-card-height-lg: 480px;
// Card padding per breakpoint
$bds-carousel-card-padding-sm: $bds-space-lg; // 16px - spacing('lg')
$bds-carousel-card-padding-md: $bds-space-xl; // 20px - spacing('xl')
$bds-carousel-card-padding-lg: $bds-space-2xl; // 24px - spacing('2xl')
// Transition
$bds-carousel-transition: 200ms cubic-bezier(0.98, 0.12, 0.12, 0.98);
// =============================================================================
// Section Container
// =============================================================================
.bds-carousel-card-list {
width: 100%;
// Constrain to max-width at xl breakpoint (per _breakpoints.scss)
@include media-breakpoint-up(xl) {
max-width: $bds-carousel-grid-max-width;
margin-left: auto;
margin-right: auto;
}
// Allow focus rings to be visible (no overflow:hidden)
}
// =============================================================================
// Header Section
// =============================================================================
.bds-carousel-card-list__header {
display: flex;
flex-direction: column;
gap: $bds-carousel-section-gap-sm;
// Apply same padding as track to align header with cards
padding-left: $bds-carousel-grid-padding-sm;
padding-right: $bds-carousel-grid-padding-sm;
@include media-breakpoint-up(md) {
gap: $bds-carousel-section-gap-md;
padding-left: $bds-carousel-grid-padding-md;
padding-right: $bds-carousel-grid-padding-md;
}
// Row layout only at desktop (lg and up)
@include media-breakpoint-up(lg) {
flex-direction: row;
justify-content: space-between;
align-items: flex-start;
gap: $bds-carousel-section-gap-lg;
padding-left: $bds-carousel-grid-padding-lg;
padding-right: $bds-carousel-grid-padding-lg;
}
}
.bds-carousel-card-list__header-content {
display: flex;
flex-direction: column;
gap: $bds-carousel-header-gap-sm;
// Full width on mobile and tablet
max-width: 100%;
@include media-breakpoint-up(md) {
gap: $bds-carousel-header-gap-md;
}
// Constrain heading/description to grid (8 columns at desktop)
@include media-breakpoint-up(lg) {
gap: $bds-carousel-header-gap-lg;
max-width: 808px; // Desktop: 8 columns
}
}
.bds-carousel-card-list__heading {
margin: 0;
// Typography handled by .h-md class from _font.scss
}
.bds-carousel-card-list__description {
margin: 0;
// Typography handled by .body-l class from _font.scss
}
// =============================================================================
// Navigation Buttons Container
// =============================================================================
.bds-carousel-card-list__nav {
display: flex;
gap: $bds-carousel-button-gap;
justify-content: flex-end;
flex-shrink: 0;
// Add padding to allow focus ring to be visible without clipping
padding: 4px;
margin: -4px;
}
// =============================================================================
// Scroll Track
// =============================================================================
.bds-carousel-card-list__track-wrapper {
margin-top: $bds-carousel-cards-gap-sm;
overflow: visible;
// Add left padding here so it's OUTSIDE the scrollable area
padding-left: $bds-carousel-grid-padding-sm;
@include media-breakpoint-up(md) {
margin-top: $bds-carousel-cards-gap-md;
padding-left: $bds-carousel-grid-padding-md;
}
@include media-breakpoint-up(lg) {
margin-top: $bds-carousel-cards-gap-lg;
padding-left: $bds-carousel-grid-padding-lg;
}
}
.bds-carousel-card-list__track {
display: flex;
gap: $bds-grid-gutter;
overflow-x: auto;
overflow-y: visible;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
// Hide scrollbar but keep functionality
scrollbar-width: none;
-ms-overflow-style: none;
&::-webkit-scrollbar {
display: none;
}
// Vertical padding to prevent focus ring clipping
padding-top: 4px;
padding-bottom: 4px;
margin-top: -4px;
margin-bottom: -4px;
// Focus outline for keyboard navigation
&:focus {
outline: none;
}
&:focus-visible {
outline: 2px solid $white;
outline-offset: 4px;
}
}
// =============================================================================
// Card Wrapper
// =============================================================================
.bds-carousel-card-list__card {
flex-shrink: 0;
scroll-snap-align: start;
// Override CardOffgrid dimensions for carousel
.bds-card-offgrid {
width: $bds-carousel-card-width-sm;
height: $bds-carousel-card-height-sm;
padding: $bds-carousel-card-padding-sm;
@include media-breakpoint-up(md) {
width: $bds-carousel-card-width-md;
height: $bds-carousel-card-height-md;
padding: $bds-carousel-card-padding-md;
}
@include media-breakpoint-up(lg) {
width: $bds-carousel-card-width-lg;
height: $bds-carousel-card-height-lg;
padding: $bds-carousel-card-padding-lg;
}
// Fix: Prevent unwanted hover styles from parent styles
// No text underline on hover
&:hover {
text-decoration: none;
}
// Ensure title and description never have underline
.bds-card-offgrid__title,
.bds-card-offgrid__description {
text-decoration: none;
&:hover {
text-decoration: none;
}
}
// Ensure icon does not change color on hover
.bds-card-offgrid__icon-container {
// Icon color is inherited from card text color, which CardOffgrid manages
// No additional color changes should happen on hover
> * {
transition: none;
}
}
}
}
// =============================================================================
// DARK MODE (Default) - Section Text Colors
// =============================================================================
// Section text colors - Dark Mode (applies to both neutral and green card variants)
.bds-carousel-card-list--neutral,
.bds-carousel-card-list--green {
.bds-carousel-card-list__heading,
.bds-carousel-card-list__description {
color: $white;
}
}
// =============================================================================
// LIGHT MODE (html.light) - Color Variants
// =============================================================================
html.light {
.bds-carousel-card-list__track {
&:focus-visible {
outline-color: $gray-900;
}
}
// Section text colors - Light Mode
.bds-carousel-card-list--neutral,
.bds-carousel-card-list--green {
.bds-carousel-card-list__heading,
.bds-carousel-card-list__description {
color: $black;
}
}
}