Skip to content

Commit ae75e2f

Browse files
tellthemachinessethrubenstein
authored andcommitted
Add block spacing and layout to Post Template (WordPress#49050)
* Add static column number option * Address feedback and fix Group placeholder * Revert non-responsive option * Try using grid layout in Post Template * Update Post Template to use auto-fill columns * Add block spacing to post template * Show gap control by default * Add unstable columns grid property * Rename layout column attribute. * Add a media query to reproduce current responsiveness * Move layout controls to Post Template block * Reduce max columns to 6. * Remove unstable prefix * fix cols breaking out of container * Try adding deprecation * Fix broken loop * Update fixtures * Code improvements * Add some comments to the CSS. * Add back deleted line * Remove legacy attributes in deprecation * Fix deprecation logic * Update fixtures * Fallback gap for classic themes * fix spacing * match old default value * Update PHP test strings. * Fix tag discrepancy in fixtures
1 parent 9834632 commit ae75e2f

31 files changed

+468
-147
lines changed

docs/reference-guides/core-blocks.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ Contains the block elements used to render a post, like the title, date, feature
600600
- **Name:** core/post-template
601601
- **Category:** theme
602602
- **Parent:** core/query
603-
- **Supports:** align (full, wide), anchor, color (background, gradients, link, text), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
603+
- **Supports:** align (full, wide), anchor, color (background, gradients, link, text), spacing (blockGap), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~
604604
- **Attributes:**
605605

606606
## Post Terms
@@ -656,7 +656,7 @@ An advanced block that allows displaying post types based on different query par
656656
- **Name:** core/query
657657
- **Category:** theme
658658
- **Supports:** align (full, wide), anchor, ~~html~~
659-
- **Attributes:** displayLayout, namespace, query, queryId, tagName
659+
- **Attributes:** namespace, query, queryId, tagName
660660

661661
## No results
662662

lib/block-supports/layout.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,19 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
280280
}
281281
}
282282
} elseif ( 'grid' === $layout_type ) {
283-
$minimum_column_width = ! empty( $layout['minimumColumnWidth'] ) ? $layout['minimumColumnWidth'] : '12rem';
283+
if ( ! empty( $layout['columnCount'] ) ) {
284+
$layout_styles[] = array(
285+
'selector' => $selector,
286+
'declarations' => array( 'grid-template-columns' => 'repeat(' . $layout['columnCount'] . ', minmax(0, 1fr))' ),
287+
);
288+
} else {
289+
$minimum_column_width = ! empty( $layout['minimumColumnWidth'] ) ? $layout['minimumColumnWidth'] : '12rem';
284290

285-
$layout_styles[] = array(
286-
'selector' => $selector,
287-
'declarations' => array( 'grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))' ),
288-
);
291+
$layout_styles[] = array(
292+
'selector' => $selector,
293+
'declarations' => array( 'grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))' ),
294+
);
295+
}
289296

290297
if ( $has_block_gap_support && isset( $gap_value ) ) {
291298
$combined_gap_value = '';

lib/class-wp-theme-json-gutenberg.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,11 +1073,13 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets'
10731073
}
10741074
$stylesheet .= $this->get_block_classes( $style_nodes );
10751075
} elseif ( in_array( 'base-layout-styles', $types, true ) ) {
1076-
$root_selector = static::ROOT_BLOCK_SELECTOR;
1077-
$columns_selector = '.wp-block-columns';
1076+
$root_selector = static::ROOT_BLOCK_SELECTOR;
1077+
$columns_selector = '.wp-block-columns';
1078+
$post_template_selector = '.wp-block-post-template';
10781079
if ( ! empty( $options['scope'] ) ) {
1079-
$root_selector = static::scope_selector( $options['scope'], $root_selector );
1080-
$columns_selector = static::scope_selector( $options['scope'], $columns_selector );
1080+
$root_selector = static::scope_selector( $options['scope'], $root_selector );
1081+
$columns_selector = static::scope_selector( $options['scope'], $columns_selector );
1082+
$post_template_selector = static::scope_selector( $options['scope'], $post_template_selector );
10811083
}
10821084
if ( ! empty( $options['root_selector'] ) ) {
10831085
$root_selector = $options['root_selector'];
@@ -1094,6 +1096,11 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets'
10941096
'selector' => $columns_selector,
10951097
'name' => 'core/columns',
10961098
),
1099+
array(
1100+
'path' => array( 'styles', 'blocks', 'core/post-template' ),
1101+
'selector' => $post_template_selector,
1102+
'name' => 'core/post-template',
1103+
),
10971104
);
10981105

10991106
foreach ( $base_styles_nodes as $base_style_node ) {
@@ -1298,7 +1305,7 @@ protected function get_layout_styles( $block_metadata ) {
12981305
if ( null !== $block_gap_value && false !== $block_gap_value && '' !== $block_gap_value ) {
12991306
foreach ( $layout_definitions as $layout_definition_key => $layout_definition ) {
13001307
// Allow outputting fallback gap styles for flex layout type when block gap support isn't available.
1301-
if ( ! $has_block_gap_support && 'flex' !== $layout_definition_key ) {
1308+
if ( ! $has_block_gap_support && 'flex' !== $layout_definition_key && 'grid' !== $layout_definition_key ) {
13021309
continue;
13031310
}
13041311

packages/block-editor/src/components/global-styles/use-global-styles-output.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,11 @@ export function getLayoutStyles( {
460460
Object.values( tree.settings.layout.definitions ).forEach(
461461
( { className, name, spacingStyles } ) => {
462462
// Allow outputting fallback gap styles for flex layout type when block gap support isn't available.
463-
if ( ! hasBlockGapSupport && 'flex' !== name ) {
463+
if (
464+
! hasBlockGapSupport &&
465+
'flex' !== name &&
466+
'grid' !== name
467+
) {
464468
return;
465469
}
466470

packages/block-editor/src/layouts/grid.js

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ export default {
3535
layout = {},
3636
onChange,
3737
} ) {
38-
return (
38+
return layout?.columnCount ? (
39+
<GridLayoutColumnsControl layout={ layout } onChange={ onChange } />
40+
) : (
3941
<GridLayoutMinimumWidthControl
4042
layout={ layout }
4143
onChange={ onChange }
@@ -53,7 +55,7 @@ export default {
5355
hasBlockGapSupport,
5456
layoutDefinitions,
5557
} ) {
56-
const { minimumColumnWidth = '12rem' } = layout;
58+
const { minimumColumnWidth = '12rem', columnCount = null } = layout;
5759

5860
// If a block's block.json skips serialization for spacing or spacing.blockGap,
5961
// don't apply the user-defined value to the styles.
@@ -66,7 +68,11 @@ export default {
6668
let output = '';
6769
const rules = [];
6870

69-
if ( minimumColumnWidth ) {
71+
if ( columnCount ) {
72+
rules.push(
73+
`grid-template-columns: repeat(${ columnCount }, minmax(0, 1fr))`
74+
);
75+
} else if ( minimumColumnWidth ) {
7076
rules.push(
7177
`grid-template-columns: repeat(auto-fill, minmax(min(${ minimumColumnWidth }, 100%), 1fr))`
7278
);
@@ -170,3 +176,23 @@ function GridLayoutMinimumWidthControl( { layout, onChange } ) {
170176
</fieldset>
171177
);
172178
}
179+
180+
// Enables setting number of grid columns
181+
function GridLayoutColumnsControl( { layout, onChange } ) {
182+
const { columnCount = 3 } = layout;
183+
184+
return (
185+
<RangeControl
186+
label={ __( 'Columns' ) }
187+
value={ columnCount }
188+
onChange={ ( value ) =>
189+
onChange( {
190+
...layout,
191+
columnCount: value,
192+
} )
193+
}
194+
min={ 1 }
195+
max={ 6 }
196+
/>
197+
);
198+
}

packages/block-library/src/post-template/block.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@
2020
"html": false,
2121
"align": [ "wide", "full" ],
2222
"anchor": true,
23-
"__experimentalLayout": {
24-
"allowEditing": false
25-
},
23+
"__experimentalLayout": true,
2624
"color": {
2725
"gradients": true,
2826
"link": true,
@@ -43,6 +41,14 @@
4341
"__experimentalDefaultControls": {
4442
"fontSize": true
4543
}
44+
},
45+
"spacing": {
46+
"blockGap": {
47+
"__experimentalDefault": "1.25em"
48+
},
49+
"__experimentalDefaultControls": {
50+
"blockGap": true
51+
}
4652
}
4753
},
4854
"style": "wp-block-post-template",

packages/block-library/src/post-template/edit.js

Lines changed: 66 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,16 @@ import { memo, useMemo, useState } from '@wordpress/element';
1010
import { useSelect } from '@wordpress/data';
1111
import { __ } from '@wordpress/i18n';
1212
import {
13+
BlockControls,
1314
BlockContextProvider,
1415
__experimentalUseBlockPreview as useBlockPreview,
1516
useBlockProps,
1617
useInnerBlocksProps,
1718
store as blockEditorStore,
1819
} from '@wordpress/block-editor';
19-
import { Spinner } from '@wordpress/components';
20+
import { Spinner, ToolbarGroup } from '@wordpress/components';
2021
import { store as coreStore } from '@wordpress/core-data';
22+
import { list, grid } from '@wordpress/icons';
2123

2224
const TEMPLATE = [
2325
[ 'core/post-title' ],
@@ -70,6 +72,7 @@ function PostTemplateBlockPreview( {
7072
const MemoizedPostTemplateBlockPreview = memo( PostTemplateBlockPreview );
7173

7274
export default function PostTemplateEdit( {
75+
setAttributes,
7376
clientId,
7477
context: {
7578
query: {
@@ -95,11 +98,13 @@ export default function PostTemplateEdit( {
9598
} = {},
9699
queryContext = [ { page: 1 } ],
97100
templateSlug,
98-
displayLayout: { type: layoutType = 'flex', columns = 1 } = {},
99101
previewPostType,
100102
},
103+
attributes: { layout },
101104
__unstableLayoutClassNames,
102105
} ) {
106+
const { type: layoutType, columnCount = 3 } = layout || {};
107+
103108
const [ { page } ] = queryContext;
104109
const [ activeBlockContextId, setActiveBlockContextId ] = useState();
105110
const { posts, blocks } = useSelect(
@@ -215,12 +220,9 @@ export default function PostTemplateEdit( {
215220
} ) ),
216221
[ posts ]
217222
);
218-
const hasLayoutFlex = layoutType === 'flex' && columns > 1;
223+
219224
const blockProps = useBlockProps( {
220-
className: classnames( __unstableLayoutClassNames, {
221-
'is-flex-container': hasLayoutFlex,
222-
[ `columns-${ columns }` ]: hasLayoutFlex,
223-
} ),
225+
className: classnames( __unstableLayoutClassNames ),
224226
} );
225227

226228
if ( ! posts ) {
@@ -235,35 +237,67 @@ export default function PostTemplateEdit( {
235237
return <p { ...blockProps }> { __( 'No results found.' ) }</p>;
236238
}
237239

240+
const setDisplayLayout = ( newDisplayLayout ) =>
241+
setAttributes( {
242+
layout: { ...layout, ...newDisplayLayout },
243+
} );
244+
245+
const displayLayoutControls = [
246+
{
247+
icon: list,
248+
title: __( 'List view' ),
249+
onClick: () => setDisplayLayout( { type: 'default' } ),
250+
isActive: layoutType === 'default' || layoutType === 'constrained',
251+
},
252+
{
253+
icon: grid,
254+
title: __( 'Grid view' ),
255+
onClick: () =>
256+
setDisplayLayout( {
257+
type: 'grid',
258+
columnCount,
259+
} ),
260+
isActive: layoutType === 'grid',
261+
},
262+
];
263+
238264
// To avoid flicker when switching active block contexts, a preview is rendered
239265
// for each block context, but the preview for the active block context is hidden.
240266
// This ensures that when it is displayed again, the cached rendering of the
241267
// block preview is used, instead of having to re-render the preview from scratch.
242268
return (
243-
<ul { ...blockProps }>
244-
{ blockContexts &&
245-
blockContexts.map( ( blockContext ) => (
246-
<BlockContextProvider
247-
key={ blockContext.postId }
248-
value={ blockContext }
249-
>
250-
{ blockContext.postId ===
251-
( activeBlockContextId ||
252-
blockContexts[ 0 ]?.postId ) ? (
253-
<PostTemplateInnerBlocks />
254-
) : null }
255-
<MemoizedPostTemplateBlockPreview
256-
blocks={ blocks }
257-
blockContextId={ blockContext.postId }
258-
setActiveBlockContextId={ setActiveBlockContextId }
259-
isHidden={
260-
blockContext.postId ===
261-
( activeBlockContextId ||
262-
blockContexts[ 0 ]?.postId )
263-
}
264-
/>
265-
</BlockContextProvider>
266-
) ) }
267-
</ul>
269+
<>
270+
<BlockControls>
271+
<ToolbarGroup controls={ displayLayoutControls } />
272+
</BlockControls>
273+
274+
<ul { ...blockProps }>
275+
{ blockContexts &&
276+
blockContexts.map( ( blockContext ) => (
277+
<BlockContextProvider
278+
key={ blockContext.postId }
279+
value={ blockContext }
280+
>
281+
{ blockContext.postId ===
282+
( activeBlockContextId ||
283+
blockContexts[ 0 ]?.postId ) ? (
284+
<PostTemplateInnerBlocks />
285+
) : null }
286+
<MemoizedPostTemplateBlockPreview
287+
blocks={ blocks }
288+
blockContextId={ blockContext.postId }
289+
setActiveBlockContextId={
290+
setActiveBlockContextId
291+
}
292+
isHidden={
293+
blockContext.postId ===
294+
( activeBlockContextId ||
295+
blockContexts[ 0 ]?.postId )
296+
}
297+
/>
298+
</BlockContextProvider>
299+
) ) }
300+
</ul>
301+
</>
268302
);
269303
}

packages/block-library/src/post-template/style.scss

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
&.wp-block-post-template {
1010
background: none;
1111
}
12-
12+
// These rules no longer apply but should be kept for backwards compatibility.
1313
&.is-flex-container {
1414
flex-direction: row;
1515
display: flex;
@@ -30,3 +30,10 @@
3030
}
3131
}
3232
}
33+
34+
@media ( max-width: $break-small ) {
35+
// Temporary specificity bump until "wp-container" layout specificity is revisited.
36+
.wp-block-post-template-is-layout-grid.wp-block-post-template-is-layout-grid.wp-block-post-template-is-layout-grid.wp-block-post-template-is-layout-grid {
37+
grid-template-columns: 1fr;
38+
}
39+
}

packages/block-library/src/query/block.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,6 @@
3232
"type": "string",
3333
"default": "div"
3434
},
35-
"displayLayout": {
36-
"type": "object",
37-
"default": {
38-
"type": "list"
39-
}
40-
},
4135
"namespace": {
4236
"type": "string"
4337
}

0 commit comments

Comments
 (0)