Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[@mantine/core] Grid: Add auto and content spans #2317

Merged
merged 3 commits into from Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated - this documentation is incorrect. grow affects all rows, not just the last.


<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
53 changes: 39 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';
}
Comment on lines +36 to +38
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than using flex basis content, we're using flex basis auto together with a width of auto to support older browsers

image

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,11 @@ 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),
maxWidth: getColumnMaxWidth(sizes[size], columns, grow),
marginLeft: getColumnOffset(offsets[size], columns),
flexGrow: getColumnFlexGrow(sizes[size], grow),
};
return acc;
}, {});
Expand Down Expand Up @@ -92,13 +116,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';