feature/feature/IO-3554-Form-Row-Layout - Responsive overhaul
This commit is contained in:
@@ -7,7 +7,7 @@ export default function LayoutFormRow({
|
||||
children,
|
||||
grow = false,
|
||||
noDivider = false,
|
||||
gutter = [16, 16],
|
||||
gutter = [16, 16], // Responsive gutter: horizontal, vertical
|
||||
rowProps,
|
||||
|
||||
// Optional overrides if you ever need per-section customization
|
||||
@@ -63,30 +63,60 @@ export default function LayoutFormRow({
|
||||
}
|
||||
|
||||
const count = items.length;
|
||||
const spanFor = (min) => Math.max(min, Math.floor(24 / count));
|
||||
|
||||
// Mobile-first: stack on xs
|
||||
const baseCol = {
|
||||
xs: { span: 24 },
|
||||
sm: { span: grow ? spanFor(12) : 12 },
|
||||
md: { span: grow ? spanFor(8) : 8 },
|
||||
lg: { span: grow ? spanFor(6) : 6 },
|
||||
xl: { span: grow ? spanFor(4) : 4 },
|
||||
xxl: { span: grow ? spanFor(4) : 4 }
|
||||
};
|
||||
// Modern responsive strategy leveraging Ant Design 6:
|
||||
// - xs (phone <576px): Always stack vertically
|
||||
// - sm (tablet 576-768px): 2 columns for better readability
|
||||
// - md (tablet 768-992px): 3 columns for tablets
|
||||
// - lg+ (desktop >992px): Dynamic flex-based columns that adapt to screen width
|
||||
// Target: 1366px → 4 cols, 1920px → 6 cols, 2560px → 8 cols, 4K → capped at 8-9 cols
|
||||
// Note: xxl uses higher min-width to naturally cap maximum columns
|
||||
const baseCol = (() => {
|
||||
if (grow) {
|
||||
// Grow mode: use flex with reasonable min-widths
|
||||
return {
|
||||
xs: 24,
|
||||
sm: 12, // Fixed 2 cols on small tablets
|
||||
md: 8, // Fixed 3 cols on large tablets
|
||||
lg: { flex: `1 1 320px` }, // Dynamic: ~3 cols at 1200px
|
||||
xl: { flex: `1 1 280px` }, // Dynamic: ~4 cols at 1366px, ~6 cols at 1920px
|
||||
xxl: { flex: `1 1 380px` } // Dynamic: ~6 cols at 2560px, ~9 cols at 4K (capped)
|
||||
};
|
||||
} else {
|
||||
// Fixed mode: Use flex without grow to maintain uniform widths across rows
|
||||
// xxl uses larger min-width to cap maximum columns on 4K/ultrawide
|
||||
const minWidthLg = count <= 2 ? 500 : count === 3 ? 380 : 320; // 3 cols at 1200px
|
||||
const minWidthXl = count <= 2 ? 480 : count === 3 ? 360 : 280; // 4 cols at 1366px, ~6 at 1920px
|
||||
const minWidthXxl = count <= 2 ? 500 : count === 3 ? 400 : 380; // ~6 cols at 2560px, ~9 at 4K (natural cap)
|
||||
|
||||
return {
|
||||
xs: 24,
|
||||
sm: 12, // Fixed 2 columns on tablet
|
||||
md: count === 1 ? 24 : count === 2 ? 12 : 8, // Fixed 1-3 cols on large tablet
|
||||
lg: count === 1 ? 24 : { flex: `0 0 ${minWidthLg}px` }, // Fixed width on desktop
|
||||
xl: count === 1 ? 24 : { flex: `0 0 ${minWidthXl}px` }, // Fixed width on large desktop
|
||||
xxl: count === 1 ? 24 : { flex: `0 0 ${minWidthXxl}px` } // Fixed width on ultrawide
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
const getColPropsForChild = (child) => {
|
||||
if (!isValidElement(child)) return baseCol;
|
||||
|
||||
// Back-compat with old pattern: child.props.span can override Col sizing
|
||||
// Back-compat: child.props.span can override Col sizing
|
||||
const spanOverride = child.props?.span;
|
||||
if (typeof spanOverride === "number") return { span: spanOverride };
|
||||
if (spanOverride && typeof spanOverride === "object") return spanOverride;
|
||||
|
||||
// Optional explicit override: <Field col={{ md:{span:12}, ... }} />
|
||||
// Explicit override: <Field col={{ md:{span:12}, ... }} />
|
||||
const colOverride = child.props?.col;
|
||||
if (colOverride && typeof colOverride === "object") {
|
||||
return { ...baseCol, ...colOverride };
|
||||
// Deep merge: allow partial overrides while keeping baseCol defaults
|
||||
const merged = { ...baseCol };
|
||||
Object.keys(colOverride).forEach((bp) => {
|
||||
merged[bp] = typeof colOverride[bp] === "object" ? { ...baseCol[bp], ...colOverride[bp] } : colOverride[bp];
|
||||
});
|
||||
return merged;
|
||||
}
|
||||
|
||||
return baseCol;
|
||||
|
||||
Reference in New Issue
Block a user