Skip to content

Commit 5ae17f7

Browse files
Try adding layout classnames to inner block wrapper (#44600)
* Try adding layout support to Cover block. * Try adding layout classnames to inner block wrapper. * Make it work in the editor * Use WP_HTML_Tag_Processor to add layout classnames * Use WP_HTML_Tag_Processor to identify inner wrapper classnames * Improvements to inner content classname logic * Only add layout classnames to inner blocks * Manually add layout classnames to Gallery and Post Content edit * Add comment to inner content classnames logic. * Mark layoutClassnames unstable * Add classnames to container in a loop. * Remove layout support for Cover block. * Apply layout to outer wrapper if legacy Group * Off switch for layout classes in inner wrapper * Change unstable prop name
1 parent 99ad274 commit 5ae17f7

File tree

8 files changed

+71
-29
lines changed

8 files changed

+71
-29
lines changed

lib/block-supports/layout.php

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,23 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
291291
return '';
292292
}
293293

294+
/**
295+
* Gets classname from last tag in a string of HTML.
296+
*
297+
* @param string $html markup to be processed.
298+
* @return string String of inner wrapper classnames.
299+
*/
300+
function gutenberg_get_classnames_from_last_tag( $html ) {
301+
$tags = new WP_HTML_Tag_Processor( $html );
302+
$last_classnames = '';
303+
304+
while ( $tags->next_tag() ) {
305+
$last_classnames = $tags->get_attribute( 'class' );
306+
}
307+
308+
return $last_classnames;
309+
}
310+
294311
/**
295312
* Renders the layout config to the block wrapper.
296313
*
@@ -320,7 +337,6 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
320337

321338
$class_names = array();
322339
$layout_definitions = _wp_array_get( $global_layout_settings, array( 'definitions' ), array() );
323-
$block_classname = wp_get_block_default_classname( $block['blockName'] );
324340
$container_class = wp_unique_id( 'wp-container-' );
325341
$layout_classname = '';
326342

@@ -397,7 +413,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
397413
$should_skip_gap_serialization = gutenberg_should_skip_block_supports_serialization( $block_type, 'spacing', 'blockGap' );
398414

399415
$style = gutenberg_get_layout_style(
400-
".$block_classname.$container_class",
416+
".$container_class.$container_class",
401417
$used_layout,
402418
$has_block_gap_support,
403419
$gap_value,
@@ -412,16 +428,22 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
412428
}
413429
}
414430

415-
/*
416-
* This assumes the hook only applies to blocks with a single wrapper.
417-
* A limitation of this hook is that nested inner blocks wrappers are not yet supported.
418-
*/
419-
$content = preg_replace(
420-
'/' . preg_quote( 'class="', '/' ) . '/',
421-
'class="' . esc_attr( implode( ' ', $class_names ) ) . ' ',
422-
$block_content,
423-
1
424-
);
431+
/**
432+
* The first chunk of innerContent contains the block markup up until the inner blocks start.
433+
* We want to target the opening tag of the inner blocks wrapper, which is the last tag in that chunk.
434+
*/
435+
$inner_content_classnames = isset( $block['innerContent'][0] ) && 'string' === gettype( $block['innerContent'][0] ) ? gutenberg_get_classnames_from_last_tag( $block['innerContent'][0] ) : '';
436+
437+
$content = new WP_HTML_Tag_Processor( $block_content );
438+
if ( $inner_content_classnames ) {
439+
$content->next_tag( array( 'class_name' => $inner_content_classnames ) );
440+
foreach ( $class_names as $class_name ) {
441+
$content->add_class( $class_name );
442+
}
443+
} else {
444+
$content->next_tag();
445+
$content->add_class( implode( ' ', $class_names ) );
446+
}
425447

426448
return $content;
427449
}
@@ -433,6 +455,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
433455
'register_attribute' => 'gutenberg_register_layout_support',
434456
)
435457
);
458+
436459
if ( function_exists( 'wp_render_layout_support_flag' ) ) {
437460
remove_filter( 'render_block', 'wp_render_layout_support_flag' );
438461
}

packages/block-editor/src/components/block-edit/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ import { BlockEditContextProvider, useBlockEditContext } from './context';
2020
export { useBlockEditContext };
2121

2222
export default function BlockEdit( props ) {
23-
const { name, isSelected, clientId } = props;
23+
const { name, isSelected, clientId, __unstableLayoutClassNames } = props;
2424
const context = {
2525
name,
2626
isSelected,
2727
clientId,
28+
__unstableLayoutClassNames,
2829
};
2930
return (
3031
<BlockEditContextProvider

packages/block-editor/src/components/block-list/block.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ function BlockListBlock( {
8484
isSelected,
8585
isSelectionEnabled,
8686
className,
87+
__unstableLayoutClassNames: layoutClassNames,
8788
name,
8889
isValid,
8990
attributes,
@@ -146,6 +147,7 @@ function BlockListBlock( {
146147
clientId={ clientId }
147148
isSelectionEnabled={ isSelectionEnabled }
148149
toggleSelection={ toggleSelection }
150+
__unstableLayoutClassNames={ layoutClassNames }
149151
/>
150152
);
151153

packages/block-editor/src/components/inner-blocks/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,9 @@ const ForwardedInnerBlocks = forwardRef( ( props, ref ) => {
150150
* @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inner-blocks/README.md
151151
*/
152152
export function useInnerBlocksProps( props = {}, options = {} ) {
153-
const { clientId } = useBlockEditContext();
153+
const { __unstableDisableLayoutClassNames } = options;
154+
const { clientId, __unstableLayoutClassNames: layoutClassNames = '' } =
155+
useBlockEditContext();
154156
const isSmallScreen = useViewportMatch( 'medium', '<' );
155157
const { __experimentalCaptureToolbars, hasOverlay } = useSelect(
156158
( select ) => {
@@ -200,12 +202,14 @@ export function useInnerBlocksProps( props = {}, options = {} ) {
200202
innerBlocksProps.value && innerBlocksProps.onChange
201203
? ControlledInnerBlocks
202204
: UncontrolledInnerBlocks;
205+
203206
return {
204207
...props,
205208
ref,
206209
className: classnames(
207210
props.className,
208211
'block-editor-block-list__layout',
212+
__unstableDisableLayoutClassNames ? '' : layoutClassNames,
209213
{
210214
'has-overlay': hasOverlay,
211215
}

packages/block-editor/src/hooks/layout.js

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ import { kebabCase } from 'lodash';
99
*/
1010
import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
1111
import { addFilter } from '@wordpress/hooks';
12-
import {
13-
getBlockDefaultClassName,
14-
getBlockSupport,
15-
hasBlockSupport,
16-
} from '@wordpress/blocks';
12+
import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks';
1713
import { useSelect } from '@wordpress/data';
1814
import {
1915
Button,
@@ -366,9 +362,8 @@ export const withLayoutStyles = createHigherOrderComponent(
366362
const layoutClasses = hasLayoutBlockSupport
367363
? useLayoutClasses( block )
368364
: null;
369-
const selector = `.${ getBlockDefaultClassName(
370-
name
371-
) }.wp-container-${ id }`;
365+
// Higher specificity to override defaults from theme.json.
366+
const selector = `.wp-container-${ id }.wp-container-${ id }`;
372367
const blockGapSupport = useSetting( 'spacing.blockGap' );
373368
const hasBlockGapSupport = blockGapSupport !== null;
374369

@@ -413,7 +408,10 @@ export const withLayoutStyles = createHigherOrderComponent(
413408
/>,
414409
element
415410
) }
416-
<BlockListBlock { ...props } className={ className } />
411+
<BlockListBlock
412+
{ ...props }
413+
__unstableLayoutClassNames={ className }
414+
/>
417415
</>
418416
);
419417
}

packages/block-library/src/gallery/gallery.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const Gallery = ( props ) => {
2626
mediaPlaceholder,
2727
insertBlocksAfter,
2828
blockProps,
29+
__unstableLayoutClassNames: layoutClassNames,
2930
} = props;
3031

3132
const { align, columns, caption, imageCrop } = attributes;
@@ -42,6 +43,7 @@ export const Gallery = ( props ) => {
4243
{ ...innerBlocksProps }
4344
className={ classnames(
4445
blockProps.className,
46+
layoutClassNames,
4547
'blocks-gallery-grid',
4648
{
4749
[ `align${ align }` ]: align,

packages/block-library/src/group/edit.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@ const htmlElementMessages = {
3535
),
3636
};
3737

38-
function GroupEdit( { attributes, setAttributes, clientId } ) {
38+
function GroupEdit( {
39+
attributes,
40+
setAttributes,
41+
clientId,
42+
__unstableLayoutClassNames: layoutClassNames,
43+
} ) {
3944
const { hasInnerBlocks, themeSupportsLayout } = useSelect(
4045
( select ) => {
4146
const { getBlock, getSettings } = select( blockEditorStore );
@@ -55,7 +60,9 @@ function GroupEdit( { attributes, setAttributes, clientId } ) {
5560
const { type = 'default' } = usedLayout;
5661
const layoutSupportEnabled = themeSupportsLayout || type === 'flex';
5762

58-
const blockProps = useBlockProps();
63+
const blockProps = useBlockProps( {
64+
className: ! layoutSupportEnabled ? layoutClassNames : null,
65+
} );
5966

6067
const innerBlocksProps = useInnerBlocksProps(
6168
layoutSupportEnabled
@@ -67,6 +74,7 @@ function GroupEdit( { attributes, setAttributes, clientId } ) {
6774
? undefined
6875
: InnerBlocks.ButtonBlockAppender,
6976
__experimentalLayout: layoutSupportEnabled ? usedLayout : undefined,
77+
__unstableDisableLayoutClassNames: ! layoutSupportEnabled,
7078
}
7179
);
7280

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ function Content( props ) {
8484
);
8585
}
8686

87-
function Placeholder() {
88-
const blockProps = useBlockProps();
87+
function Placeholder( { layoutClassNames } ) {
88+
const blockProps = useBlockProps( { className: layoutClassNames } );
8989
return (
9090
<div { ...blockProps }>
9191
<p>
@@ -118,7 +118,11 @@ function RecursionError() {
118118
);
119119
}
120120

121-
export default function PostContentEdit( { context, attributes } ) {
121+
export default function PostContentEdit( {
122+
context,
123+
attributes,
124+
__unstableLayoutClassNames: layoutClassNames,
125+
} ) {
122126
const { postId: contextPostId, postType: contextPostType } = context;
123127
const { layout = {} } = attributes;
124128
const hasAlreadyRendered = useHasRecursion( contextPostId );
@@ -132,7 +136,7 @@ export default function PostContentEdit( { context, attributes } ) {
132136
{ contextPostId && contextPostType ? (
133137
<Content context={ context } layout={ layout } />
134138
) : (
135-
<Placeholder />
139+
<Placeholder layoutClassNames={ layoutClassNames } />
136140
) }
137141
</RecursionProvider>
138142
);

0 commit comments

Comments
 (0)