Skip to content
This repository was archived by the owner on Feb 23, 2024. It is now read-only.

Commit e470bdb

Browse files
authored
Product Collection - shrink columns to fit (#11320)
* Add Toggle to inspector controls allowing shrinking number of columns * Add logic to allow columns to shrink in Product Collection * Rename SCSS variable * Make sure the value provided to component is a boolean * Rename onChange callback name to better reflect its purpose
1 parent 7ccc39b commit e470bdb

File tree

6 files changed

+114
-36
lines changed

6 files changed

+114
-36
lines changed

assets/js/blocks/product-collection/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export const DEFAULT_ATTRIBUTES: Partial< ProductCollectionAttributes > = {
5858
displayLayout: {
5959
type: LayoutOptions.GRID,
6060
columns: 3,
61+
shrinkColumns: false,
6162
},
6263
};
6364

assets/js/blocks/product-collection/inspector-controls/columns-control.tsx

Lines changed: 73 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import { __ } from '@wordpress/i18n';
55
import {
66
RangeControl,
7+
ToggleControl,
78
// @ts-expect-error Using experimental features
89
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
910
__experimentalToolsPanelItem as ToolsPanelItem,
@@ -12,44 +13,86 @@ import {
1213
/**
1314
* Internal dependencies
1415
*/
15-
import { DisplayLayoutControlProps } from '../types';
16+
import { DisplayLayoutToolbarProps } from '../types';
1617
import { getDefaultDisplayLayout } from '../constants';
1718

18-
const ColumnsControl = ( props: DisplayLayoutControlProps ) => {
19-
const { type, columns } = props.displayLayout;
19+
const toggleLabel = __(
20+
'Shrink columns to fit',
21+
'woo-gutenberg-products-block'
22+
);
23+
24+
const toggleHelp = __(
25+
'Reduce the number of columns to better fit smaller screens and spaces.',
26+
'woo-gutenberg-products-block'
27+
);
28+
29+
const getColumnsLabel = ( shrinkColumns: boolean ) =>
30+
shrinkColumns
31+
? __( 'Max Columns', 'woo-gutenberg-products-block' )
32+
: __( 'Columns', 'woo-gutenberg-products-block' );
33+
34+
const ColumnsControl = ( props: DisplayLayoutToolbarProps ) => {
35+
const { type, columns, shrinkColumns } = props.displayLayout;
2036
const showColumnsControl = type === 'flex';
2137

2238
const defaultLayout = getDefaultDisplayLayout();
2339

40+
const onShrinkColumnsToggleChange = ( value: boolean ) => {
41+
props.setAttributes( {
42+
displayLayout: {
43+
...props.displayLayout,
44+
shrinkColumns: value,
45+
},
46+
} );
47+
};
48+
49+
const onPanelDeselect = () => {
50+
props.setAttributes( {
51+
displayLayout: defaultLayout,
52+
} );
53+
};
54+
55+
const onColumnsChange = ( value: number ) =>
56+
props.setAttributes( {
57+
displayLayout: {
58+
...props.displayLayout,
59+
columns: value,
60+
},
61+
} );
62+
2463
return showColumnsControl ? (
25-
<ToolsPanelItem
26-
label={ __( 'Columns', 'woo-gutenberg-products-block' ) }
27-
hasValue={ () =>
28-
defaultLayout?.columns !== columns ||
29-
defaultLayout?.type !== type
30-
}
31-
isShownByDefault
32-
onDeselect={ () => {
33-
props.setAttributes( {
34-
displayLayout: defaultLayout,
35-
} );
36-
} }
37-
>
38-
<RangeControl
39-
label={ __( 'Columns', 'woo-gutenberg-products-block' ) }
40-
value={ columns }
41-
onChange={ ( value: number ) =>
42-
props.setAttributes( {
43-
displayLayout: {
44-
...props.displayLayout,
45-
columns: value,
46-
},
47-
} )
64+
<>
65+
<ToolsPanelItem
66+
hasValue={ () =>
67+
defaultLayout?.shrinkColumns !== shrinkColumns
68+
}
69+
isShownByDefault
70+
onDeselect={ onPanelDeselect }
71+
>
72+
<ToggleControl
73+
checked={ !! shrinkColumns }
74+
label={ toggleLabel }
75+
help={ toggleHelp }
76+
onChange={ onShrinkColumnsToggleChange }
77+
/>
78+
</ToolsPanelItem>
79+
<ToolsPanelItem
80+
hasValue={ () =>
81+
defaultLayout?.columns !== columns ||
82+
defaultLayout?.type !== type
4883
}
49-
min={ 2 }
50-
max={ Math.max( 6, columns ) }
51-
/>
52-
</ToolsPanelItem>
84+
isShownByDefault
85+
onDeselect={ onPanelDeselect }
86+
>
87+
<RangeControl
88+
label={ getColumnsLabel( !! shrinkColumns ) }
89+
onChange={ onColumnsChange }
90+
value={ columns }
91+
min={ 2 }
92+
max={ Math.max( 6, columns ) }
93+
/>
94+
</ToolsPanelItem>
95+
</>
5396
) : null;
5497
};
5598

assets/js/blocks/product-collection/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export enum LayoutOptions {
2525
export interface ProductCollectionDisplayLayout {
2626
type: LayoutOptions;
2727
columns: number;
28+
shrinkColumns?: boolean;
2829
}
2930

3031
export interface ProductCollectionQuery {

assets/js/blocks/product-template/edit.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,10 @@ const ProductTemplateEdit = ( {
8787
},
8888
queryContext = [ { page: 1 } ],
8989
templateSlug,
90-
displayLayout: { type: layoutType, columns } = {
90+
displayLayout: { type: layoutType, columns, shrinkColumns } = {
9191
type: 'flex',
9292
columns: 3,
93+
shrinkColumns: false,
9394
},
9495
},
9596
__unstableLayoutClassNames,
@@ -203,15 +204,21 @@ const ProductTemplateEdit = ( {
203204
} ) ),
204205
[ products ]
205206
);
207+
206208
const hasLayoutFlex = layoutType === 'flex' && columns > 1;
209+
let customClassName = '';
210+
if ( hasLayoutFlex ) {
211+
const dynamicGrid = `wc-block-product-template__responsive columns-${ columns }`;
212+
const staticGrid = `is-flex-container columns-${ columns }`;
213+
214+
customClassName = shrinkColumns ? dynamicGrid : staticGrid;
215+
}
216+
207217
const blockProps = useBlockProps( {
208218
className: classnames(
209219
__unstableLayoutClassNames,
210220
'wc-block-product-template',
211-
{
212-
'is-flex-container': hasLayoutFlex,
213-
[ `columns-${ columns }` ]: hasLayoutFlex,
214-
}
221+
customClassName
215222
),
216223
} );
217224

assets/js/blocks/product-template/style.scss

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
$break-small: 600px;
22

3+
$grid-gap: 1.25em;
4+
$min-product-width: 150px;
5+
36
@mixin break-small() {
47
@media (min-width: #{ ($break-small) }) {
58
@content;
@@ -39,6 +42,25 @@ $break-small: 600px;
3942
}
4043
}
4144
}
45+
46+
&__responsive {
47+
display: grid;
48+
grid-gap: $grid-gap;
49+
50+
@for $i from 2 through 6 {
51+
$gap-count: calc(#{ $i } - 1);
52+
$total-gap-width: calc(#{ $gap-count } * #{ $grid-gap });
53+
$max-product-width: calc((100% - #{ $total-gap-width }) / #{ $i });
54+
55+
&.columns-#{ $i } {
56+
grid-template-columns: repeat(auto-fill, minmax(max(#{ $min-product-width }, #{ $max-product-width }), 1fr));
57+
}
58+
}
59+
60+
> li {
61+
margin-block-start: 0;
62+
}
63+
}
4264
}
4365

4466
/**

src/BlockTypes/ProductTemplate.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@ protected function render( $attributes, $content, $block ) {
6161
$classnames = '';
6262
if ( isset( $block->context['displayLayout'] ) && isset( $block->context['query'] ) ) {
6363
if ( isset( $block->context['displayLayout']['type'] ) && 'flex' === $block->context['displayLayout']['type'] ) {
64-
$classnames = "is-flex-container columns-{$block->context['displayLayout']['columns']}";
64+
if ( $block->context['displayLayout']['shrinkColumns'] ) {
65+
$classnames = "wc-block-product-template__responsive columns-{$block->context['displayLayout']['columns']}";
66+
} else {
67+
$classnames = "is-flex-container columns-{$block->context['displayLayout']['columns']}";
68+
}
6569
}
6670
}
6771
if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) {

0 commit comments

Comments
 (0)