Merge pull request #3404 from XRPLF/grid-optimization

[fix] Grid optimization
This commit is contained in:
Calvin
2025-12-03 16:17:54 -08:00
committed by GitHub
5 changed files with 833 additions and 261 deletions

View File

@@ -3,37 +3,50 @@
// A namespaced grid layer that reuses Bootstrap's grid mixins while providing
// XRPL-specific gutters and container padding.
$xrpl-grid-gutter: 8px;
$bds-grid-gutter: 8px;
@mixin xrpl-grid-generate-cols($columns, $suffix: null) {
// Custom mixin that accounts for gap spacing in width calculations
@mixin bds-make-col($size, $columns) {
flex: 0 0 auto;
// Calculate width accounting for gap spacing
// Formula: width per column * span + gap spacing between spanned columns
// Total gaps in grid: ($columns - 1)
// Total available width: 100% - (gap * total gaps)
// Width per column: available width / columns
// For span of $size: (width per column * size) + (gap * (size - 1))
width: calc(((100% - (#{$bds-grid-gutter} * (#{$columns} - 1))) / #{$columns}) * #{$size} + (#{$bds-grid-gutter} * (#{$size} - 1)));
}
@mixin bds-grid-generate-cols($columns, $suffix: null) {
@for $i from 1 through $columns {
$selector: if($suffix, ".xrpl-grid__col-#{$suffix}-#{$i}", ".xrpl-grid__col-#{$i}");
$selector: if($suffix, ".bds-grid__col-#{$suffix}-#{$i}", ".bds-grid__col-#{$i}");
#{$selector} {
@include make-col($i, $columns);
@include bds-make-col($i, $columns);
}
}
}
@mixin xrpl-grid-generate-auto($suffix: null) {
$selector: if($suffix, ".xrpl-grid__col-#{$suffix}-auto", ".xrpl-grid__col-auto");
@mixin bds-grid-generate-auto($suffix: null) {
$selector: if($suffix, ".bds-grid__col-#{$suffix}-auto", ".bds-grid__col-auto");
#{$selector} {
@include make-col-auto();
}
}
@mixin xrpl-grid-generate-fill($suffix: null) {
$selector: if($suffix, ".xrpl-grid__col-#{$suffix}", ".xrpl-grid__col");
@mixin bds-grid-generate-fill($suffix: null) {
$selector: if($suffix, ".bds-grid__col-#{$suffix}-fill", ".bds-grid__col-fill");
#{$selector} {
flex: 1 0 0;
width: auto;
}
}
@mixin xrpl-grid-generate-offsets($columns, $suffix: null) {
@mixin bds-grid-generate-offsets($columns, $suffix: null) {
@for $i from 0 through ($columns - 1) {
$selector: if($suffix, ".xrpl-grid__offset-#{$suffix}-#{$i}", ".xrpl-grid__offset-#{$i}");
$selector: if($suffix, ".bds-grid__offset-#{$suffix}-#{$i}", ".bds-grid__offset-#{$i}");
#{$selector} {
@include make-col-offset($i, $columns);
@@ -41,7 +54,35 @@ $xrpl-grid-gutter: 8px;
}
}
.xrpl-grid {
// Mixin to generate responsive base column classes (1-12) with built-in breakpoint behavior
@mixin bds-grid-generate-responsive-base-cols() {
@for $i from 1 through 12 {
.bds-grid__col-#{$i} {
// Base breakpoint (4 columns): if span > 4, clamp to 4 (which gives 4/4 = 100%)
@if $i > 4 {
@include bds-make-col(4, 4);
} @else {
@include bds-make-col($i, 4);
}
// SM / MD breakpoint (8 columns): if span > 8, clamp to 8 (which gives 8/8 = 100%)
@include media-breakpoint-up(md) {
@if $i > 8 {
@include bds-make-col(8, 8);
} @else {
@include bds-make-col($i, 8);
}
}
// LG+ breakpoints (12 columns): always calculate based on 12 cols
@include media-breakpoint-up(lg) {
@include bds-make-col($i, 12);
}
}
}
}
.bds-grid {
&__container {
width: 100%;
margin-right: auto;
@@ -68,49 +109,50 @@ $xrpl-grid-gutter: 8px;
}
&__row {
@include make-row($xrpl-grid-gutter);
display: flex;
flex-wrap: wrap;
// Use gap for spacing - works with our calc-based column widths
gap: $bds-grid-gutter;
}
&__col {
@include make-col-ready();
box-sizing: border-box;
flex: auto;
flex-shrink: 0;
width: 100%;
max-width: 100%;
// No padding/margin for gutters - spacing handled by gap on row
// Column widths are calculated to account for gap spacing
// Padding can be added via style prop without affecting grid spacing
}
}
// Base (0 - 575px) — 4-column grid
@include xrpl-grid-generate-fill();
@include xrpl-grid-generate-cols(4);
@include xrpl-grid-generate-auto();
@include xrpl-grid-generate-offsets(4);
// Base (0 - 575px) — 4-column grid with responsive behavior built-in
@include bds-grid-generate-fill();
@include bds-grid-generate-responsive-base-cols();
@include bds-grid-generate-auto();
@include bds-grid-generate-offsets(4);
// Tablet (≥576px) — maintain 8-column grid across sm/md ranges
@include media-breakpoint-up(sm) {
@include xrpl-grid-generate-fill('sm');
@include xrpl-grid-generate-cols(8, 'sm');
@include xrpl-grid-generate-auto('sm');
@include xrpl-grid-generate-offsets(8, 'sm');
}
@include media-breakpoint-up(md) {
@include xrpl-grid-generate-fill('md');
@include xrpl-grid-generate-cols(8, 'md');
@include xrpl-grid-generate-auto('md');
@include xrpl-grid-generate-offsets(8, 'md');
@include bds-grid-generate-fill('md');
@include bds-grid-generate-cols(8, 'md');
@include bds-grid-generate-auto('md');
@include bds-grid-generate-offsets(8, 'md');
}
// Large (≥992px) — 12-column grid
@include media-breakpoint-up(lg) {
@include xrpl-grid-generate-fill('lg');
@include xrpl-grid-generate-cols(12, 'lg');
@include xrpl-grid-generate-auto('lg');
@include xrpl-grid-generate-offsets(12, 'lg');
@include bds-grid-generate-fill('lg');
@include bds-grid-generate-cols(12, 'lg');
@include bds-grid-generate-auto('lg');
@include bds-grid-generate-offsets(12, 'lg');
}
// XL (≥1280px) — retain 12-column grid with wider margins
@include media-breakpoint-up(xl) {
@include xrpl-grid-generate-fill('xl');
@include xrpl-grid-generate-cols(12, 'xl');
@include xrpl-grid-generate-auto('xl');
@include xrpl-grid-generate-offsets(12, 'xl');
}
@include bds-grid-generate-fill('xl');
@include bds-grid-generate-cols(12, 'xl');
@include bds-grid-generate-auto('xl');
@include bds-grid-generate-offsets(12, 'xl');
}

View File

@@ -228,22 +228,22 @@ Center content or create spacing with offsets:
The component generates the following CSS classes:
### Container
- `xrpl-grid__container`
- `bds-grid__container`
### Row
- `xrpl-grid__row`
- `bds-grid__row`
### Column Spans
- `xrpl-grid__col-{number}` (e.g., `xrpl-grid__col-6`)
- `xrpl-grid__col-auto`
- `xrpl-grid__col` (for fill)
- `xrpl-grid__col-{breakpoint}-{number}` (e.g., `xrpl-grid__col-md-6`)
- `xrpl-grid__col-{breakpoint}-auto`
- `xrpl-grid__col-{breakpoint}` (for fill)
- `bds-grid__col-{number}` (e.g., `bds-grid__col-6`)
- `bds-grid__col-auto`
- `bds-grid__col` (for fill)
- `bds-grid__col-{breakpoint}-{number}` (e.g., `bds-grid__col-md-6`)
- `bds-grid__col-{breakpoint}-auto`
- `bds-grid__col-{breakpoint}` (for fill)
### Column Offsets
- `xrpl-grid__offset-{number}` (e.g., `xrpl-grid__offset-2`)
- `xrpl-grid__offset-{breakpoint}-{number}` (e.g., `xrpl-grid__offset-md-2`)
- `bds-grid__offset-{number}` (e.g., `bds-grid__offset-2`)
- `bds-grid__offset-{breakpoint}-{number}` (e.g., `bds-grid__offset-md-2`)
## TypeScript Types

View File

@@ -35,19 +35,18 @@ const classForSpan = (prefix: string | null, value: PageGridSpanValue): string =
const prefixStr = prefix ? `-${prefix}` : "";
if (value === "auto") {
// Generates xrpl-grid__col-auto or xrpl-grid__col-md-auto
return `xrpl-grid__col${prefixStr}-auto`;
// Generates bds-grid__col-auto or bds-grid__col-md-auto
return `bds-grid__col${prefixStr}-auto`;
}
if (value === "fill") {
// Generates xrpl-grid__col or xrpl-grid__col-md (based on documentation)
// Note: The documentation states 'xrpl-grid__col' for fill, and 'xrpl-grid__col-{breakpoint}' for fill
// The implementation below aligns with the documentation's example logic:
return prefix ? `xrpl-grid__col${prefixStr}` : "xrpl-grid__col";
// Generates bds-grid__col-fill or bds-grid__col-md-fill
// This allows us to distinguish between "no span" and "span='fill'" in CSS
return `bds-grid__col${prefixStr}-fill`;
}
// Generates xrpl-grid__col-6 or xrpl-grid__col-md-6
return `xrpl-grid__col${prefixStr}-${value}`;
// Generates bds-grid__col-6 or bds-grid__col-md-6
return `bds-grid__col${prefixStr}-${value}`;
};
/**
@@ -59,15 +58,15 @@ const classForSpan = (prefix: string | null, value: PageGridSpanValue): string =
*/
const classForOffset = (prefix: string | null, value: PageGridOffsetValue): string => {
const prefixStr = prefix ? `-${prefix}` : "";
// Generates xrpl-grid__offset-2 or xrpl-grid__offset-md-2
return `xrpl-grid__offset${prefixStr}-${value}`;
// Generates bds-grid__offset-2 or bds-grid__offset-md-2
return `bds-grid__offset${prefixStr}-${value}`;
};
// --- PageGrid Root Component ---
const PageGridRoot = React.forwardRef<HTMLDivElement, PageGridProps>(
({ className, ...rest }, ref) => (
<div ref={ref} className={clsx("xrpl-grid__container", className)} {...rest} />
<div ref={ref} className={clsx("bds-grid__container", className)} {...rest} />
)
);
@@ -77,7 +76,7 @@ PageGridRoot.displayName = "PageGrid";
// --- PageGrid.Row Component ---
const PageGridRow = React.forwardRef<HTMLDivElement, PageGridRowProps>(
({ className, ...rest }, ref) => (
<div ref={ref} className={clsx("xrpl-grid__row", className)} {...rest} />
<div ref={ref} className={clsx("bds-grid__row", className)} {...rest} />
)
);
@@ -99,6 +98,10 @@ const PageGridCol = React.forwardRef<HTMLDivElement, PageGridColProps>((props, r
if (baseSpan) {
spanClasses.push(classForSpan(null, baseSpan));
} else {
// If no base span is provided, default to full width (4 columns for base breakpoint)
// This ensures columns are full width on mobile when only larger breakpoints are specified
spanClasses.push(classForSpan(null, 4));
}
// Handles sm, md, lg, xl breakpoints (with prefix)
@@ -106,7 +109,7 @@ const PageGridCol = React.forwardRef<HTMLDivElement, PageGridColProps>((props, r
const value = span[key];
if (value) {
// Generates classes like xrpl-grid__col-md-6
// Generates classes like bds-grid__col-md-6
spanClasses.push(classForSpan(key, value));
}
});
@@ -129,7 +132,7 @@ const PageGridCol = React.forwardRef<HTMLDivElement, PageGridColProps>((props, r
const value = offset[key];
if (value !== undefined) {
// Generates classes like xrpl-grid__offset-md-3
// Generates classes like bds-grid__offset-md-3
offsetClasses.push(classForOffset(key, value));
}
});
@@ -139,8 +142,8 @@ const PageGridCol = React.forwardRef<HTMLDivElement, PageGridColProps>((props, r
return (
<div
ref={ref}
// Note: Added "xrpl-grid__col" base class for consistent column initialization
className={clsx("xrpl-grid__col", className, spanClasses, offsetClasses)}
// Note: Added "bds-grid__col" base class for consistent column initialization
className={clsx("bds-grid__col", className, spanClasses, offsetClasses)}
{...rest}
/>
);