Skip to content

Commit

Permalink
[@mantine/core] Grid: Add auto and content spans (#2317)
Browse files Browse the repository at this point in the history
* [@mantine/core] Grid: Add auto and content spans

* Update demo copy

* Add width of auto to breakpoint styles
  • Loading branch information
leeweisberger committed Sep 8, 2022
1 parent 8528b3f commit 66386e4
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 23 deletions.
16 changes: 15 additions & 1 deletion docs/src/docs/core/Grid.mdx
Expand Up @@ -31,7 +31,7 @@ Use xs, sm, md, lg, xl values to set spacing from `theme.spacing` or number to s

## Grow

Set `grow` prop on Grid component to force last row take 100% of container width:
Set `grow` prop on Grid component to force all rows to take 100% of container width:

<Demo data={GridDemos.growConfigurator} />

Expand Down Expand Up @@ -70,6 +70,20 @@ In this example up to `md` there will be 1 column, from `md` to `lg` there will

<Demo data={GridDemos.responsive} />

## Auto sized columns

All columns in a row with `span` or a breakpoint of `auto` will have equal size, growing as much as they can to fill the row.

In this example, the second column takes up 50% of the row while the other two columns automatically resize to fill the remaining space:

<Demo data={GridDemos.auto} />

## Fit column content

If you set `span` or a breakpoint to `content`, the column's size will automatically adjust to match the width of its content:

<Demo data={GridDemos.content} />

## Change columns count

By default, grid uses 12 columns layout, you can change it by setting `columns` prop on Grid component.
Expand Down
54 changes: 40 additions & 14 deletions src/mantine-core/src/Grid/Col/Col.styles.ts
Expand Up @@ -6,6 +6,8 @@ import {
MantineTheme,
} from '@mantine/styles';

export type ColSpan = number | 'auto' | 'content';

interface ColStyles {
gutter: MantineNumberSize;
columns: number;
Expand All @@ -16,12 +18,12 @@ interface ColStyles {
offsetMd: number;
offsetLg: number;
offsetXl: number;
span: number;
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
span: ColSpan;
xs: ColSpan;
sm: ColSpan;
md: ColSpan;
lg: ColSpan;
xl: ColSpan;
order: React.CSSProperties['order'];
orderXs: React.CSSProperties['order'];
orderSm: React.CSSProperties['order'];
Expand All @@ -30,8 +32,29 @@ interface ColStyles {
orderXl: React.CSSProperties['order'];
}

const getColumnWidth = (colSpan: number, columns: number) =>
colSpan ? `${100 / (columns / colSpan)}%` : undefined;
const getColumnFlexBasis = (colSpan: ColSpan, columns: number) => {
if (colSpan === 'content') {
return 'auto';
}
if (colSpan === 'auto') {
return '0px';
}
return colSpan ? `${100 / (columns / colSpan)}%` : undefined;
};

const getColumnMaxWidth = (colSpan: ColSpan, columns: number, grow: boolean) => {
if (grow || colSpan === 'auto' || colSpan === 'content') {
return 'unset';
}
return getColumnFlexBasis(colSpan, columns);
};

const getColumnFlexGrow = (colSpan: ColSpan, grow: boolean) => {
if (!colSpan) {
return undefined;
}
return colSpan === 'auto' || grow ? 1 : 0;
};

const getColumnOffset = (offset: number, columns: number) =>
offset ? `${100 / (columns / offset)}%` : undefined;
Expand All @@ -44,7 +67,7 @@ function getBreakpointsStyles({
columns,
grow,
}: {
sizes: Record<MantineSize, number>;
sizes: Record<MantineSize, ColSpan>;
offsets: Record<MantineSize, number>;
orders: Record<MantineSize, React.CSSProperties['order']>;
grow: boolean;
Expand All @@ -54,10 +77,12 @@ function getBreakpointsStyles({
return MANTINE_SIZES.reduce((acc, size) => {
acc[`@media (min-width: ${theme.breakpoints[size] + 1}px)`] = {
order: orders[size],
flexBasis: getColumnWidth(sizes[size], columns),
flexBasis: getColumnFlexBasis(sizes[size], columns),
flexShrink: 0,
maxWidth: grow ? 'unset' : getColumnWidth(sizes[size], columns),
width: sizes[size] === 'content' ? 'auto' : undefined,
maxWidth: getColumnMaxWidth(sizes[size], columns, grow),
marginLeft: getColumnOffset(offsets[size], columns),
flexGrow: getColumnFlexGrow(sizes[size], grow),
};
return acc;
}, {});
Expand Down Expand Up @@ -92,13 +117,14 @@ export default createStyles(
) => ({
root: {
boxSizing: 'border-box',
flexGrow: grow ? 1 : 0,
flexGrow: getColumnFlexGrow(span, grow),
order,
padding: theme.fn.size({ size: gutter, sizes: theme.spacing }) / 2,
marginLeft: getColumnOffset(offset, columns),
flexBasis: getColumnWidth(span, columns),
flexBasis: getColumnFlexBasis(span, columns),
flexShrink: 0,
maxWidth: grow ? 'unset' : getColumnWidth(span, columns),
width: span === 'content' ? 'auto' : undefined,
maxWidth: getColumnMaxWidth(span, columns, grow),
...getBreakpointsStyles({
sizes: { xs, sm, md, lg, xl },
offsets: { xs: offsetXs, sm: offsetSm, md: offsetMd, lg: offsetLg, xl: offsetXl },
Expand Down
19 changes: 11 additions & 8 deletions src/mantine-core/src/Grid/Col/Col.tsx
Expand Up @@ -2,11 +2,11 @@ import React, { forwardRef } from 'react';
import { DefaultProps, useComponentDefaultProps } from '@mantine/styles';
import { Box } from '../../Box';
import { useGridContext } from '../Grid.context';
import useStyles from './Col.styles';
import useStyles, { ColSpan } from './Col.styles';

export interface ColProps extends DefaultProps, React.ComponentPropsWithoutRef<'div'> {
/** Default col span */
span?: number;
span?: ColSpan;

/** Column left offset */
offset?: number;
Expand Down Expand Up @@ -45,19 +45,19 @@ export interface ColProps extends DefaultProps, React.ComponentPropsWithoutRef<'
offsetXl?: number;

/** Col span at (min-width: theme.breakpoints.xs) */
xs?: number;
xs?: ColSpan;

/** Col span at (min-width: theme.breakpoints.sm) */
sm?: number;
sm?: ColSpan;

/** Col span at (min-width: theme.breakpoints.md) */
md?: number;
md?: ColSpan;

/** Col span at (min-width: theme.breakpoints.lg) */
lg?: number;
lg?: ColSpan;

/** Col span at (min-width: theme.breakpoints.xl) */
xl?: number;
xl?: ColSpan;
}

const defaultProps: Partial<ColProps> = {
Expand All @@ -69,7 +69,10 @@ const defaultProps: Partial<ColProps> = {
offsetXl: 0,
};

function isValidSpan(span: number) {
function isValidSpan(span: ColSpan) {
if (span === 'auto' || span === 'content') {
return true;
}
return typeof span === 'number' && span > 0 && span % 1 === 0;
}

Expand Down
33 changes: 33 additions & 0 deletions src/mantine-demos/src/demos/core/Grid/Grid.demo.auto.tsx
@@ -0,0 +1,33 @@
import React from 'react';
import { Grid } from '@mantine/core';
import { ColWrapper as Col } from './_col-wrapper';

const code = `
import { Grid } from '@mantine/core';
function Demo() {
return (
<Grid>
<Col span="auto">span=auto</Col>
<Col span={6}>span=6</Col>
<Col span="auto">span=auto</Col>
</Grid>
);
}
`;

function Demo() {
return (
<Grid>
<Col span="auto">1</Col>
<Col span={6}>2</Col>
<Col span="auto">3</Col>
</Grid>
);
}

export const auto: MantineDemo = {
type: 'demo',
code,
component: Demo,
};
31 changes: 31 additions & 0 deletions src/mantine-demos/src/demos/core/Grid/Grid.demo.content.tsx
@@ -0,0 +1,31 @@
import React from 'react';
import { Grid } from '@mantine/core';
import { ColWrapper as Col } from './_col-wrapper';

const code = `
import { Grid } from '@mantine/core';
function Demo() {
return (
<Grid>
<Col span="content">fit content</Col>
<Col span={6}>2</Col>
</Grid>
);
}
`;

function Demo() {
return (
<Grid>
<Col span="content">fit content</Col>
<Col span={6}>2</Col>
</Grid>
);
}

export const content: MantineDemo = {
type: 'demo',
code,
component: Demo,
};
2 changes: 2 additions & 0 deletions src/mantine-demos/src/demos/core/Grid/index.ts
Expand Up @@ -6,3 +6,5 @@ export { rows } from './Grid.demo.rows';
export { flexConfigurator } from './Grid.demo.flexConfigurator';
export { responsive } from './Grid.demo.responsive';
export { columns } from './Grid.demo.columns';
export { auto } from './Grid.demo.auto';
export { content } from './Grid.demo.content';

0 comments on commit 66386e4

Please sign in to comment.