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

Add block spacing gap config to theme.json and add support for this CSS variable to the "flow/default" layout. #33812

Merged
merged 17 commits into from
Aug 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/how-to-guides/themes/theme-json.md
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ Each block declares which style properties it exposes via the [block supports me
"text": "value"
},
"spacing": {
"blockGap": "value",
"margin": {
"top": "value",
"right": "value",
Expand Down Expand Up @@ -684,6 +685,7 @@ Each block declares which style properties it exposes via the [block supports me
"text": "value"
},
"spacing": {
"blockGap": "value",
"margin": {
"top": "value",
"right": "value",
Expand Down
16 changes: 10 additions & 6 deletions lib/block-supports/layout.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,21 @@ function gutenberg_get_layout_style( $selector, $layout ) {
$style .= '}';

$style .= "$selector > .alignwide { max-width: " . esc_html( $wide_max_width_value ) . ';}';

$style .= "$selector .alignfull { max-width: none; }";
}

$style .= "$selector .alignleft { float: left; margin-right: 2em; }";
$style .= "$selector .alignright { float: right; margin-left: 2em; }";
$style .= "$selector > * + * { margin-top: var( --wp--style--block-gap ); margin-bottom: 0; }";
Copy link
Member

Choose a reason for hiding this comment

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

Not related to this PR but a possible improvement for the future: Rules like $selector .alignleft { float: left; margin-right: 2em; }, and $selector > * + * { margin-top: var( --wp--style--block-gap ); margin-bottom: 0; } etc don't rely on any user value. If we have 10 group blocks on a page all with the same layout we repeat these rules as inline styles 10 times. Could we just have a class with these styles not relying on user values one time and then just inject the class when needed? The way the styles would only be added one time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought about this a few time it would force us to have generic .container-flow classNames. Worth a try I think but we should be careful about these extra classes.

} elseif ( 'flex' === $layout_type ) {
$style = "$selector {";
Copy link
Member

Choose a reason for hiding this comment

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

In my tests the block gap works inside a group block with the default layout but not with the flex layout I think it is expected for now given the PR title. But I guess we can easily also add a rule on the flex layout that uses the --wp--style--block-gap variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I actually added it to the client but forgot to add it to the server :)

$style .= 'display: flex;';
$style .= 'column-gap: 0.5em;';
$style .= 'gap: var( --wp--style--block-gap, 0.5em );';
$style .= 'flex-wrap: wrap;';
$style .= 'align-items: center;';
$style .= '}';

$style .= "$selector > * { margin: 0; }";
}

return $style;
Expand All @@ -83,13 +86,14 @@ function gutenberg_get_layout_style( $selector, $layout ) {
* @return string Filtered block content.
*/
function gutenberg_render_layout_support_flag( $block_content, $block ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$support_layout = gutenberg_block_has_support( $block_type, array( '__experimentalLayout' ), false );
if ( ! $support_layout || ! isset( $block['attrs']['layout'] ) ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$support_layout = gutenberg_block_has_support( $block_type, array( '__experimentalLayout' ), false );
$has_innner_blocks = count( $block['innerBlocks'] ) > 0;
if ( ! $support_layout && ! $has_innner_blocks ) {
return $block_content;
}

$used_layout = $block['attrs']['layout'];
$used_layout = isset( $block['attrs']['layout'] ) ? $block['attrs']['layout'] : array();
if ( isset( $used_layout['inherit'] ) && $used_layout['inherit'] ) {
$tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( array(), 'theme' );
$default_layout = _wp_array_get( $tree->get_settings(), array( 'layout' ) );
Expand Down
10 changes: 8 additions & 2 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ class WP_Theme_JSON_Gutenberg {
'text' => null,
),
'spacing' => array(
'margin' => null,
'padding' => null,
'margin' => null,
'padding' => null,
'blockGap' => null,
),
'typography' => array(
'fontFamily' => null,
Expand Down Expand Up @@ -233,6 +234,7 @@ class WP_Theme_JSON_Gutenberg {
'padding-right' => array( 'spacing', 'padding', 'right' ),
'padding-bottom' => array( 'spacing', 'padding', 'bottom' ),
'padding-left' => array( 'spacing', 'padding', 'left' ),
'--wp--style--block-gap' => array( 'spacing', 'blockGap' ),
Copy link
Member

Choose a reason for hiding this comment

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

The gap works a little bit differently from the other properties because there is inheritance. If I apply margin to a block the descendent blocks don't get that margin but if I apply a gap the descendants even if not direct descendants get that gap because of how CSS variables work. I guess we should probably document somewhere that gap is inherited/propagated contrary to what happens with a margin or padding.

Copy link
Contributor Author

@youknowriad youknowriad Aug 18, 2021

Choose a reason for hiding this comment

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

Good observation, I went back and forth here. I think inheriting is good here but I'm still hesitant a bit.. WDYT? Agreed about the documentation.

Copy link
Member

Choose a reason for hiding this comment

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

I think for this case inheritance makes sense, otherwise, something like a global gap would have almost no noticeable effect. As the direct descendants in a global context are header a content area and a footer most of the time.
I guess we can document and set that expectation for the gap and see what feedback we get.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

unless I'm missing something, I didn't find a reference for all the styles that we can add the theme.json configs. Maybe we should consider creating one separately.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, I think that would be a good place for it.

'text-decoration' => array( 'typography', 'textDecoration' ),
'text-transform' => array( 'typography', 'textTransform' ),
);
Expand Down Expand Up @@ -835,6 +837,10 @@ private function get_block_styles( $style_nodes, $setting_nodes ) {
$selector = $metadata['selector'];
$declarations = self::compute_style_properties( $node );
$block_rules .= self::to_ruleset( $selector, $declarations );

if ( self::ROOT_BLOCK_SELECTOR === $selector ) {
$block_rules .= '.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); margin-bottom: 0; }';
jorgefilipecosta marked this conversation as resolved.
Show resolved Hide resolved
}
}

$preset_rules = '';
Expand Down
3 changes: 3 additions & 0 deletions lib/theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -236,5 +236,8 @@
}
}
}
},
"styles": {
"spacing": { "blockGap": "24px" }
Copy link
Member

Choose a reason for hiding this comment

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

I'm noticing an issue if I set a gap for 60px. And I add two top-level paragraphs in a post. On the front end, the gap between paragraphs is 60px, on the template editor too but on the post editor, the gap is not the 60px.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Which theme are you using, I can take a look.

Copy link
Member

Choose a reason for hiding this comment

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

The tt1-blocks from theme-experiments repo.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For me it works properly 🤔

}
}
26 changes: 15 additions & 11 deletions packages/block-editor/src/hooks/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,25 +166,29 @@ export const withInspectorControls = createHigherOrderComponent(
*/
export const withLayoutStyles = createHigherOrderComponent(
( BlockListBlock ) => ( props ) => {
const { name, attributes } = props;
const { name, attributes, clientId } = props;
const supportLayout = hasBlockSupport( name, layoutBlockSupportKey );
const id = useInstanceId( BlockListBlock );
const defaultLayout = useSetting( 'layout' ) || {};
if ( ! supportLayout ) {
return <BlockListBlock { ...props } />;
}
const { layout = {} } = attributes;
const usedLayout = !! layout && layout.inherit ? defaultLayout : layout;
const className = classnames(
props?.className,
`wp-container-${ id }`
const hasInnerBlocks = useSelect(
( select ) => {
const { getBlockCount } = select( blockEditorStore );
return getBlockCount( clientId ) > 0;
},
[ clientId ]
);

const element = useContext( Head.context );
const shouldRenderLayoutStyles = supportLayout || hasInnerBlocks;
const { layout = {} } = attributes;
const usedLayout = !! layout && layout.inherit ? defaultLayout : layout;
const className = classnames( props?.className, {
[ `wp-container-${ id }` ]: shouldRenderLayoutStyles,
} );

return (
<>
{ element &&
{ shouldRenderLayoutStyles &&
element &&
createPortal(
<LayoutStyle
selector={ `.wp-container-${ id }` }
Expand Down
17 changes: 12 additions & 5 deletions packages/block-editor/src/layouts/flex.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,18 @@ export default {

save: function FlexLayoutStyle( { selector } ) {
return (
<style>{ `${ appendSelectors( selector ) } {
display: flex;
column-gap: 0.5em;
align-items: center;
}` }</style>
<style>{ `
${ appendSelectors( selector ) } {
display: flex;
gap: var( --wp--style--block-gap, 0.5em );
flex-wrap: wrap;
align-items: center;
}

${ appendSelectors( selector, '> *' ) } {
margin: 0;
}
` }</style>
);
},

Expand Down
5 changes: 5 additions & 0 deletions packages/block-editor/src/layouts/flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ export default {
float: right;
margin-left: 2em;
}

${ appendSelectors( selector, '> * + *' ) } {
margin-top: var( --wp--style--block-gap );
margin-bottom: 0;
}
`;

return <style>{ style }</style>;
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/group/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"style": true,
"width": true
},
"__experimentalLayout": true
"__experimentalLayout": {}
},
"editorStyle": "wp-block-group-editor",
"style": "wp-block-group"
Expand Down
2 changes: 0 additions & 2 deletions packages/block-library/src/group/theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,5 @@
&.has-background {
// Matches paragraph Block padding
padding: $block-bg-padding--v $block-bg-padding--h;
margin-top: 0;
margin-bottom: 0;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was conflicting with the this consistent margin styling. @jasmussen maybe you know where in our code base we define the block margins and whether we should move these to classic.css now.

}
}
3 changes: 3 additions & 0 deletions packages/blocks/src/api/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = {
value: [ 'typography', 'letterSpacing' ],
support: [ '__experimentalLetterSpacing' ],
},
'--wp--style--block-gap': {
value: [ 'spacing', 'blockGap' ],
},
};

export const __EXPERIMENTAL_ELEMENTS = {
Expand Down
9 changes: 8 additions & 1 deletion packages/edit-post/src/components/visual-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,14 @@ export default function VisualEditor( { styles } ) {
</div>
) }
<RecursionProvider>
<BlockList __experimentalLayout={ layout } />
<BlockList
Copy link
Member

Choose a reason for hiding this comment

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

I'm catching up on some layout/template editor things so I may miss tons of context: the effect of this seems that we'll show the block gap everywhere (front, site editor, post editor with template editor) except in the post editor when the theme doesn't have a theme.json file (classic theme). Is this reading correct?

Copy link
Contributor Author

@youknowriad youknowriad Aug 10, 2021

Choose a reason for hiding this comment

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

the idea of the change here is that the editor Dom should mimic the frontend and in the case of the "post editor", when we're in "template mode" we're showing the whole template meaning the canvas wrapper need to have the wp-site-blocks className like the frontend.

Incidentally, this has the effect of making sure the newly added style targeting the top level items to apply the "gap" get applied properly in the template mode.

className={
isTemplateMode
? 'wp-site-blocks'
: undefined
}
__experimentalLayout={ layout }
/>
</RecursionProvider>
</MaybeIframe>
</motion.div>
Expand Down
2 changes: 1 addition & 1 deletion packages/edit-site/src/components/block-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export default function BlockEditor( { setIsInserterOpen } ) {
contentRef={ mergedRefs }
>
<BlockList
className="edit-site-block-editor__block-list"
className="edit-site-block-editor__block-list wp-site-blocks"
__experimentalLayout={ LAYOUT }
/>
</Iframe>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,8 @@ export const toStyles = ( tree, blockSelectors ) => {
const nodesWithStyles = getNodesWithStyles( tree, blockSelectors );
const nodesWithSettings = getNodesWithSettings( tree, blockSelectors );

let ruleset = '';
let ruleset =
'.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); margin-bottom: 0; }';
nodesWithStyles.forEach( ( { selector, styles } ) => {
const declarations = getStylesDeclarations( styles );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ describe( 'global styles renderer', () => {
};

expect( toStyles( tree, blockSelectors ) ).toEqual(
'body{background-color: red;margin: 10px;padding: 10px;}h1{font-size: 42px;}.wp-block-group{margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}h1,h2,h3,h4,h5,h6{color: orange;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: hotpink;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}'
'.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); margin-bottom: 0; }body{background-color: red;margin: 10px;padding: 10px;}h1{font-size: 42px;}.wp-block-group{margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}h1,h2,h3,h4,h5,h6{color: orange;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: hotpink;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}'
);
} );
} );
Expand Down
4 changes: 2 additions & 2 deletions phpunit/class-wp-theme-json-schema-v0-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -471,11 +471,11 @@ function test_get_stylesheet() {
);

$this->assertEquals(
'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}body{color: var(--wp--preset--color--grey);}a{color: #111;}h1{font-size: 1em;}h2{font-size: 2em;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #333;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: #222;}.wp-block-post-title{font-size: 5em;}.wp-block-post-title a{color: #555;}.wp-block-query-title{font-size: 5em;}.wp-block-query-title a{color: #555;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}',
'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}body{color: var(--wp--preset--color--grey);}.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); margin-bottom: 0; }a{color: #111;}h1{font-size: 1em;}h2{font-size: 2em;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #333;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: #222;}.wp-block-post-title{font-size: 5em;}.wp-block-post-title a{color: #555;}.wp-block-query-title{font-size: 5em;}.wp-block-query-title a{color: #555;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}',
$theme_json->get_stylesheet()
);
$this->assertEquals(
'body{color: var(--wp--preset--color--grey);}a{color: #111;}h1{font-size: 1em;}h2{font-size: 2em;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #333;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: #222;}.wp-block-post-title{font-size: 5em;}.wp-block-post-title a{color: #555;}.wp-block-query-title{font-size: 5em;}.wp-block-query-title a{color: #555;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}',
'body{color: var(--wp--preset--color--grey);}.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); margin-bottom: 0; }a{color: #111;}h1{font-size: 1em;}h2{font-size: 2em;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #333;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: #222;}.wp-block-post-title{font-size: 5em;}.wp-block-post-title a{color: #555;}.wp-block-query-title{font-size: 5em;}.wp-block-query-title a{color: #555;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}',
$theme_json->get_stylesheet( 'block_styles' )
);
$this->assertEquals(
Expand Down
Loading