Skip to content

Commit 7f0f2ca

Browse files
Update Columns to accept oneThird, oneHalf, twoThirds array options (#8387)
### WHY are these changes introduced? ### WHAT is this pull request doing? Columns now accepts an array of aliases for common sizes in the admin. Note: the aliases are just that, aliases. If several are used that don't add up to an even 100, then the results may not be as expected. They are basically an easy way to set common column widths wrapped in `minmax()`. <details> <summary>Copy-paste this code in <code>playground/Playground.tsx</code>:</summary> ```jsx import React from 'react'; import {Box, Columns, Page} from '../src'; export function Playground() { return ( <Page title="Playground"> {/* Add the code you want to test in here */} <Columns> <Box background="surface">one</Box> <Box background="surface">two</Box> <Box background="surface">three</Box> <Box background="surface">four</Box> <Box background="surface">five</Box> <Box background="surface">six</Box> <Box background="surface">seven</Box> </Columns> <hr /> <Columns columns={['oneThird', 'twoThirds']}> <Box background="surface-attention">one</Box> <Box background="surface-attention">two</Box> <Box background="surface-attention">three</Box> <Box background="surface-attention">four</Box> <Box background="surface-attention">five</Box> <Box background="surface-attention">six</Box> <Box background="surface-attention">seven</Box> </Columns> <hr /> <Columns columns={{xs: 1, lg: ['twoThirds', 'oneThird']}}> <Box background="surface">one</Box> <Box background="surface">two</Box> <Box background="surface">three</Box> <Box background="surface">four</Box> <Box background="surface">five</Box> <Box background="surface">six</Box> <Box background="surface">seven</Box> </Columns> <hr /> <Columns columns={3}> <Box background="surface-attention">one</Box> <Box background="surface-attention">two</Box> <Box background="surface-attention">three</Box> <Box background="surface-attention">four</Box> <Box background="surface-attention">five</Box> <Box background="surface-attention">six</Box> <Box background="surface-attention">seven</Box> </Columns> <hr /> <Columns columns={['twoThirds', 'oneThird', 'oneHalf']}> <Box background="surface">one</Box> <Box background="surface">two</Box> <Box background="surface">three</Box> <Box background="surface">four</Box> <Box background="surface">five</Box> <Box background="surface">six</Box> <Box background="surface">seven</Box> </Columns> </Page> ); } ``` </details> --------- Co-authored-by: Aaron Casanova <32409546+aaronccasanova@users.noreply.github.com>
1 parent 3194791 commit 7f0f2ca

File tree

7 files changed

+1918
-1788
lines changed

7 files changed

+1918
-1788
lines changed

.changeset/clean-rivers-vanish.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@shopify/polaris': patch
3+
---
4+
5+
Updated `Columns` to accept columns aliases

polaris-react/src/components/Columns/Columns.scss

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,34 @@
44
@include responsive-props('columns', 'gap', 'gap');
55

66
// stylelint-disable -- Polaris component custom properties
7-
--pc-columns-xs: 6;
8-
--pc-columns-sm: var(--pc-columns-xs);
9-
--pc-columns-md: var(--pc-columns-sm);
10-
--pc-columns-lg: var(--pc-columns-md);
11-
--pc-columns-xl: var(--pc-columns-lg);
7+
--pc-columns-grid-template-columns-xs: initial;
8+
--pc-columns-grid-template-columns-sm: var(--pc-columns-grid-template-columns-xs);
9+
--pc-columns-grid-template-columns-md: var(--pc-columns-grid-template-columns-sm);
10+
--pc-columns-grid-template-columns-lg: var(--pc-columns-grid-template-columns-md);
11+
--pc-columns-grid-template-columns-xl: var(--pc-columns-grid-template-columns-lg);
1212
// stylelint-enable
1313
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
1414
display: grid;
1515
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
16-
grid-template-columns: var(--pc-columns-xs);
16+
grid-template-columns: var(--pc-columns-grid-template-columns-xs);
1717

1818
@media #{$p-breakpoints-sm-up} {
1919
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
20-
grid-template-columns: var(--pc-columns-sm);
20+
grid-template-columns: var(--pc-columns-grid-template-columns-sm);
2121
}
2222

2323
@media #{$p-breakpoints-md-up} {
2424
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
25-
grid-template-columns: var(--pc-columns-md);
25+
grid-template-columns: var(--pc-columns-grid-template-columns-md);
2626
}
2727

2828
@media #{$p-breakpoints-lg-up} {
2929
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
30-
grid-template-columns: var(--pc-columns-lg);
30+
grid-template-columns: var(--pc-columns-grid-template-columns-lg);
3131
}
3232

3333
@media #{$p-breakpoints-xl-up} {
3434
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
35-
grid-template-columns: var(--pc-columns-xl);
35+
grid-template-columns: var(--pc-columns-grid-template-columns-xl);
3636
}
3737
}

polaris-react/src/components/Columns/Columns.stories.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,26 @@ export function WithFreeAndFixedWidths() {
104104
</Page>
105105
);
106106
}
107+
108+
export function WithResponsiveColumns() {
109+
return (
110+
<Page fullWidth>
111+
<Columns columns={{xs: 1, sm: 3}} gap="4">
112+
<div style={{background: 'aquamarine'}}>Column one</div>
113+
<div style={{background: 'aquamarine'}}>Column two</div>
114+
<div style={{background: 'aquamarine'}}>Column three</div>
115+
</Columns>
116+
</Page>
117+
);
118+
}
119+
120+
export function WithResponsiveColumnAlisases() {
121+
return (
122+
<Page fullWidth>
123+
<Columns columns={['oneThird', 'twoThirds']} gap="4">
124+
<div style={{background: 'aquamarine'}}>Column one</div>
125+
<div style={{background: 'aquamarine'}}>Column two</div>
126+
</Columns>
127+
</Page>
128+
);
129+
}
Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
import React from 'react';
2-
import type {
3-
BreakpointsAlias,
4-
SpacingSpaceScale,
5-
} from '@shopify/polaris-tokens';
2+
import type {SpacingSpaceScale} from '@shopify/polaris-tokens';
63

74
import {
85
getResponsiveProps,
6+
getResponsiveValue,
97
sanitizeCustomProperties,
8+
ResponsiveValue,
109
} from '../../utilities/css';
1110
import type {ResponsiveProp} from '../../utilities/css';
1211

1312
import styles from './Columns.scss';
1413

15-
type Columns = {
16-
[Breakpoint in BreakpointsAlias]?: number | string;
17-
};
18-
14+
type ColumnsAlias = 'oneThird' | 'oneHalf' | 'twoThirds';
15+
type ColumnsType = number | string | ColumnsAlias[];
16+
type Columns = ResponsiveProp<ColumnsType>;
1917
type Gap = ResponsiveProp<SpacingSpaceScale>;
2018

2119
export interface ColumnsProps {
2220
children?: React.ReactNode;
23-
/** The number of columns to display
24-
* @default {xs: 6, sm: 6, md: 6, lg: 6, xl: 6}
21+
/** The number of columns to display. Accepts either a single value or an object of values for different screen sizes.
22+
* @example
23+
* columns={6}
24+
* columns={{xs: 1, sm: 1, md: 3, lg: 6, xl: 6}}
2525
*/
2626
columns?: Columns;
2727
/** The spacing between children. Accepts a spacing token or an object of spacing tokens for different screen sizes.
@@ -35,11 +35,11 @@ export interface ColumnsProps {
3535

3636
export function Columns({children, columns, gap = '4'}: ColumnsProps) {
3737
const style = {
38-
'--pc-columns-xs': formatColumns(columns?.xs || 6),
39-
'--pc-columns-sm': formatColumns(columns?.sm),
40-
'--pc-columns-md': formatColumns(columns?.md),
41-
'--pc-columns-lg': formatColumns(columns?.lg),
42-
'--pc-columns-xl': formatColumns(columns?.xl),
38+
...getResponsiveValue(
39+
'columns',
40+
'grid-template-columns',
41+
formatColumns(columns),
42+
),
4343
...getResponsiveProps('columns', 'gap', 'space', gap),
4444
} as React.CSSProperties;
4545

@@ -50,10 +50,42 @@ export function Columns({children, columns, gap = '4'}: ColumnsProps) {
5050
);
5151
}
5252

53-
function formatColumns(columns?: number | string) {
53+
function formatColumns(columns?: Columns): ResponsiveValue {
54+
if (
55+
typeof columns === 'object' &&
56+
columns !== null &&
57+
!Array.isArray(columns)
58+
) {
59+
return Object.fromEntries(
60+
Object.entries(columns).map(([breakpointAlias, breakpointColumns]) => [
61+
breakpointAlias,
62+
getColumnValue(breakpointColumns),
63+
]),
64+
);
65+
}
66+
67+
return getColumnValue(columns);
68+
}
69+
70+
function getColumnValue(columns?: ColumnsType) {
5471
if (!columns) return undefined;
5572

56-
return typeof columns === 'number'
57-
? `repeat(${columns}, minmax(0, 1fr))`
58-
: columns;
73+
if (typeof columns === 'string') return columns;
74+
75+
if (typeof columns === 'number') {
76+
return `repeat(${columns}, minmax(0, 1fr))`;
77+
}
78+
79+
return columns
80+
.map((column) => {
81+
switch (column) {
82+
case 'oneThird':
83+
return 'minmax(0, 1fr)';
84+
case 'oneHalf':
85+
return 'minmax(0, 1fr)';
86+
case 'twoThirds':
87+
return 'minmax(0, 2fr)';
88+
}
89+
})
90+
.join(' ');
5991
}

polaris-react/src/components/Columns/tests/Columns.test.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ describe('Columns', () => {
99

1010
expect(columns).toContainReactComponent('div', {
1111
style: {
12-
'--pc-columns-xs': 'repeat(6, minmax(0, 1fr))',
1312
'--pc-columns-gap-xs': 'var(--p-space-4)',
1413
} as React.CSSProperties,
1514
});
@@ -20,7 +19,6 @@ describe('Columns', () => {
2019

2120
expect(columns).toContainReactComponent('div', {
2221
style: {
23-
'--pc-columns-xs': 'repeat(6, minmax(0, 1fr))',
2422
'--pc-columns-gap-md': 'var(--p-space-1)',
2523
} as React.CSSProperties,
2624
});
@@ -33,8 +31,8 @@ describe('Columns', () => {
3331

3432
expect(columns).toContainReactComponent('div', {
3533
style: {
36-
'--pc-columns-xs': '1fr 1fr',
37-
'--pc-columns-lg': '1.5fr 0.5fr',
34+
'--pc-columns-grid-template-columns-xs': '1fr 1fr',
35+
'--pc-columns-grid-template-columns-lg': '1.5fr 0.5fr',
3836
'--pc-columns-gap-xs': 'var(--p-space-4)',
3937
} as React.CSSProperties,
4038
});
@@ -45,8 +43,26 @@ describe('Columns', () => {
4543

4644
expect(columns).toContainReactComponent('div', {
4745
style: {
48-
'--pc-columns-xs': 'repeat(1, minmax(0, 1fr))',
49-
'--pc-columns-md': 'repeat(4, minmax(0, 1fr))',
46+
'--pc-columns-grid-template-columns-xs': 'repeat(1, minmax(0, 1fr))',
47+
'--pc-columns-grid-template-columns-md': 'repeat(4, minmax(0, 1fr))',
48+
'--pc-columns-gap-xs': 'var(--p-space-4)',
49+
} as React.CSSProperties,
50+
});
51+
});
52+
53+
it('formats alias columns', () => {
54+
const columns = mountWithApp(
55+
<Columns
56+
columns={{xs: ['oneHalf', 'oneHalf'], md: ['oneThird', 'twoThirds']}}
57+
/>,
58+
);
59+
60+
expect(columns).toContainReactComponent('div', {
61+
style: {
62+
'--pc-columns-grid-template-columns-xs':
63+
'minmax(0, 1fr) minmax(0, 1fr)',
64+
'--pc-columns-grid-template-columns-md':
65+
'minmax(0, 1fr) minmax(0, 2fr)',
5066
'--pc-columns-gap-xs': 'var(--p-space-4)',
5167
} as React.CSSProperties,
5268
});

polaris-react/src/utilities/css.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,31 @@ export function getResponsiveProps(
5151
]),
5252
);
5353
}
54+
55+
export type ResponsiveValue =
56+
| undefined
57+
| string
58+
| {
59+
[Breakpoint in BreakpointsAlias]?: string;
60+
};
61+
62+
export function getResponsiveValue(
63+
componentName: string,
64+
componentProp: string,
65+
responsiveProp?: ResponsiveValue,
66+
) {
67+
if (!responsiveProp) return {};
68+
69+
if (typeof responsiveProp === 'string') {
70+
return {
71+
[`--pc-${componentName}-${componentProp}-xs`]: responsiveProp,
72+
};
73+
}
74+
75+
return Object.fromEntries(
76+
Object.entries(responsiveProp).map(([breakpointAlias, responsiveValue]) => [
77+
`--pc-${componentName}-${componentProp}-${breakpointAlias}`,
78+
responsiveValue,
79+
]),
80+
);
81+
}

0 commit comments

Comments
 (0)