Skip to content

Commit

Permalink
Try "constrained" content width as new layout type (#42763)
Browse files Browse the repository at this point in the history
* Try content width column as new layout type

* Consolidate root selector rules.

* Undo rebase weirdness

* Add deprecation and server-side legacy support

* Change group block approach

* Fix buggy align behaviour

* Alignments should work for classic themes

* Set output to empty string.

* Add layout type fallback for alignments

* Regenerate fixtures

* Update snapshots

* Change nested blocks to buttons

* Fix php test diffs

* Fix rebase inconsistency in layout

* Add test for content size variable output

* Add test for column layout.

* Fix loss of layout attributes.

* Make layout changes work for blocks without deprecation

* Fix custom content size controls

* Fix post title

* Update new e2e snapshots

* Change layout type name to "constrained"

* Update snapshots for new tests.

* Content size variables should be output in the site editor.

* Fix custom content sizes in editor.

* Tidy up PHP.

* Add deprecation fixtures

* Fixed duplicated code after rebase hack job. Sorry!
Fixed incoming failing test (formatted only).

* Increase block gap selector specificity.

Co-authored-by: ramonjd <ramonjd@gmail.com>
  • Loading branch information
tellthemachines and ramonjd authored Aug 22, 2022
1 parent 112305c commit 93e29bb
Show file tree
Hide file tree
Showing 54 changed files with 961 additions and 292 deletions.
2 changes: 1 addition & 1 deletion docs/reference-guides/core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ Gather blocks in a layout container. ([Source](https://github.com/WordPress/gute
- **Name:** core/group
- **Category:** design
- **Supports:** align (full, wide), anchor, ariaLabel, color (background, gradients, link, text), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~
- **Attributes:** tagName, templateLock
- **Attributes:** layout, tagName, templateLock

## Heading

Expand Down
32 changes: 31 additions & 1 deletion lib/block-supports/layout.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,31 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
$layout_type = isset( $layout['type'] ) ? $layout['type'] : 'default';
$layout_styles = array();
if ( 'default' === $layout_type ) {
if ( $has_block_gap_support ) {
if ( is_array( $gap_value ) ) {
$gap_value = isset( $gap_value['top'] ) ? $gap_value['top'] : null;
}
if ( $gap_value && ! $should_skip_gap_serialization ) {
array_push(
$layout_styles,
array(
'selector' => "$selector > *",
'declarations' => array(
'margin-block-start' => '0',
'margin-block-end' => '0',
),
),
array(
'selector' => "$selector$selector > * + *",
'declarations' => array(
'margin-block-start' => $gap_value,
'margin-block-end' => '0',
),
)
);
}
}
} elseif ( 'constrained' === $layout_type ) {
$content_size = isset( $layout['contentSize'] ) ? $layout['contentSize'] : '';
$wide_size = isset( $layout['wideSize'] ) ? $layout['wideSize'] : '';

Expand Down Expand Up @@ -254,11 +279,11 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
$has_block_gap_support = isset( $block_gap ) ? null !== $block_gap : false;
$default_block_layout = _wp_array_get( $block_type->supports, array( '__experimentalLayout', 'default' ), array() );
$used_layout = isset( $block['attrs']['layout'] ) ? $block['attrs']['layout'] : $default_block_layout;

if ( isset( $used_layout['inherit'] ) && $used_layout['inherit'] ) {
if ( ! $global_layout_settings ) {
return $block_content;
}
$used_layout = $global_layout_settings;
}

$class_names = array();
Expand All @@ -268,6 +293,11 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
$layout_classname = '';
$use_global_padding = gutenberg_get_global_settings( array( 'useRootPaddingAwareAlignments' ) ) && ( isset( $used_layout['inherit'] ) && $used_layout['inherit'] || isset( $used_layout['contentSize'] ) && $used_layout['contentSize'] );

// Set the correct layout type for blocks using legacy content width.
if ( isset( $used_layout['inherit'] ) && $used_layout['inherit'] || isset( $used_layout['contentSize'] ) && $used_layout['contentSize'] ) {
$used_layout['type'] = 'constrained';
}

if ( $use_global_padding ) {
$class_names[] = 'has-global-padding';
}
Expand Down
43 changes: 30 additions & 13 deletions lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php
Original file line number Diff line number Diff line change
Expand Up @@ -758,18 +758,6 @@ function( $pseudo_selector ) use ( $selector ) {
}
}

/*
* Reset default browser margin on the root body element.
* This is set on the root selector **before** generating the ruleset
* from the `theme.json`. This is to ensure that if the `theme.json` declares
* `margin` in its `spacing` declaration for the `body` element then these
* user-generated values take precedence in the CSS cascade.
* @link https://github.com/WordPress/gutenberg/issues/36147.
*/
if ( static::ROOT_BLOCK_SELECTOR === $selector ) {
$block_rules .= 'body { margin: 0; }';
}

// 2. Generate and append the rules that use the general selector.
$block_rules .= static::to_ruleset( $selector, $declarations );

Expand All @@ -793,6 +781,34 @@ function( $pseudo_selector ) use ( $selector ) {
}

if ( static::ROOT_BLOCK_SELECTOR === $selector ) {
/*
* Reset default browser margin on the root body element.
* This is set on the root selector **before** generating the ruleset
* from the `theme.json`. This is to ensure that if the `theme.json` declares
* `margin` in its `spacing` declaration for the `body` element then these
* user-generated values take precedence in the CSS cascade.
* @link https://github.com/WordPress/gutenberg/issues/36147.
*/
$block_rules .= 'body { margin: 0;';

/*
* If there are content and wide widths in theme.json, output them
* as custom properties on the body element so all blocks can use them.
*/
if ( isset( $settings['layout']['contentSize'] ) || isset( $settings['layout']['wideSize'] ) ) {
$content_size = isset( $settings['layout']['contentSize'] ) ? $settings['layout']['contentSize'] : $settings['layout']['wideSize'];
$content_size = static::is_safe_css_declaration( 'max-width', $content_size ) ? $content_size : 'initial';
$wide_size = isset( $settings['layout']['wideSize'] ) ? $settings['layout']['wideSize'] : $settings['layout']['contentSize'];
$wide_size = static::is_safe_css_declaration( 'max-width', $wide_size ) ? $wide_size : 'initial';
$block_rules .= '--wp--style--global--content-size: ' . $content_size . ';';
$block_rules .= '--wp--style--global--wide-size: ' . $wide_size . ';';
}

$block_rules .= '}';
}

if ( static::ROOT_BLOCK_SELECTOR === $selector ) {

if ( $use_root_padding ) {
$block_rules .= '.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }';
$block_rules .= '.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }';
Expand All @@ -804,6 +820,7 @@ function( $pseudo_selector ) use ( $selector ) {
$block_rules .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }';
$block_rules .= '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';

$block_gap_value = _wp_array_get( $this->theme_json, array( 'styles', 'spacing', 'blockGap' ), '0.5em' );
$has_block_gap_support = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'blockGap' ) ) !== null;
if ( $has_block_gap_support ) {
$block_gap_value = static::get_property_value( $this->theme_json, array( 'styles', 'spacing', 'blockGap' ) );
Expand Down Expand Up @@ -1295,7 +1312,7 @@ protected function get_layout_styles( $block_metadata ) {
$has_fallback_gap_support = ! $has_block_gap_support; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback gap styles support.
$node = _wp_array_get( $this->theme_json, $block_metadata['path'], array() );
$layout_definitions = _wp_array_get( $this->theme_json, array( 'settings', 'layout', 'definitions' ), array() );
$layout_selector_pattern = '/^[a-zA-Z0-9\-\.\ *+>]*$/'; // Allow alphanumeric classnames, spaces, wildcard, sibling, and child combinator selectors.
$layout_selector_pattern = '/^[a-zA-Z0-9\-\.\ *+>:\(\)]*$/'; // Allow alphanumeric classnames, spaces, wildcard, sibling, child combinator and pseudo class selectors.

// Gap styles will only be output if the theme has block gap support, or supports a fallback gap.
// Default layout gap styles will be skipped for themes that do not explicitly opt-in to blockGap with a `true` or `false` value.
Expand Down
60 changes: 60 additions & 0 deletions lib/compat/wordpress-6.1/theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,66 @@
}
]
},
"constrained": {
"name": "constrained",
"slug": "constrained",
"className": "is-layout-constrained",
"baseStyles": [
{
"selector": " > .alignleft",
"rules": {
"float": "left",
"margin-inline-start": "0",
"margin-inline-end": "2em"
}
},
{
"selector": " > .alignright",
"rules": {
"float": "right",
"margin-inline-start": "2em",
"margin-inline-end": "0"
}
},
{
"selector": " > .aligncenter",
"rules": {
"margin-left": "auto !important",
"margin-right": "auto !important"
}
},
{
"selector": " > :where(:not(.alignleft):not(.alignright):not(.alignfull))",
"rules": {
"max-width": "var(--wp--style--global--content-size)",
"margin-left": "auto !important",
"margin-right": "auto !important"
}
},
{
"selector": " > .alignwide",
"rules": {
"max-width": "var(--wp--style--global--wide-size)"
}
}
],
"spacingStyles": [
{
"selector": " > *",
"rules": {
"margin-block-start": "0",
"margin-block-end": "0"
}
},
{
"selector": " > * + *",
"rules": {
"margin-block-start": null,
"margin-block-end": "0"
}
}
]
},
"flex": {
"name": "flex",
"slug": "flex",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default function useAvailableAlignments( controls = DEFAULT_CONTROLS ) {
}

// Starting here, it's the fallback for themes not supporting the layout config.
if ( layoutType.name !== 'default' ) {
if ( layoutType.name !== 'default' && layoutType.name !== 'constrained' ) {
return [];
}
const { alignments: availableAlignments = DEFAULT_CONTROLS } = layout;
Expand Down
59 changes: 45 additions & 14 deletions packages/block-editor/src/hooks/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,25 +110,37 @@ function LayoutPanel( { setAttributes, attributes, name: blockName } ) {

// Only show the inherit toggle if it's supported,
// a default theme layout is set (e.g. one that provides `contentSize` and/or `wideSize` values),
// and that the default / flow layout type is in use, as this is the only one that supports inheritance.
// and either the default / flow or the constrained layout type is in use, as the toggle switches from one to the other.
const showInheritToggle = !! (
allowInheriting &&
!! defaultThemeLayout &&
( ! layout?.type || layout?.type === 'default' || layout?.inherit )
( ! layout?.type ||
layout?.type === 'default' ||
layout?.type === 'constrained' ||
layout?.inherit )
);

const usedLayout = layout || defaultBlockLayout || {};
const { inherit = false, type = 'default' } = usedLayout;
const {
inherit = false,
type = 'default',
contentSize = null,
} = usedLayout;
/**
* `themeSupportsLayout` is only relevant to the `default/flow`
* layout and it should not be taken into account when other
* `themeSupportsLayout` is only relevant to the `default/flow` or
* `constrained` layouts and it should not be taken into account when other
* `layout` types are used.
*/
if ( type === 'default' && ! themeSupportsLayout ) {
if (
( type === 'default' || type === 'constrained' ) &&
! themeSupportsLayout
) {
return null;
}
const layoutType = getLayoutType( type );

const constrainedType = getLayoutType( 'constrained' );

const onChangeType = ( newType ) =>
setAttributes( { layout: { type: newType } } );
const onChangeLayout = ( newLayout ) =>
Expand All @@ -141,18 +153,29 @@ function LayoutPanel( { setAttributes, attributes, name: blockName } ) {
{ showInheritToggle && (
<>
<ToggleControl
label={ __( 'Inner blocks use full width' ) }
checked={ ! inherit }
label={ __(
'Inner blocks respect content width'
) }
checked={
layoutType?.name === 'constrained' ||
!! inherit ||
!! contentSize
}
onChange={ () =>
setAttributes( {
layout: {
inherit: ! inherit,
type:
layoutType?.name ===
'constrained'
? 'default'
: 'constrained',
},
} )
}
/>
<p className="block-editor-hooks__layout-controls-helptext">
{ !! inherit
{ !! inherit ||
layoutType?.name === 'constrained'
? __(
'Nested blocks use theme content width with options for full and wide widths.'
)
Expand All @@ -170,13 +193,20 @@ function LayoutPanel( { setAttributes, attributes, name: blockName } ) {
/>
) }

{ ! inherit && layoutType && (
{ layoutType && layoutType.name !== 'default' && (
<layoutType.inspectorControls
layout={ usedLayout }
onChange={ onChangeLayout }
layoutBlockSupport={ layoutBlockSupport }
/>
) }
{ constrainedType && !! contentSize && (
<constrainedType.inspectorControls
layout={ usedLayout }
onChange={ onChangeLayout }
layoutBlockSupport={ layoutBlockSupport }
/>
) }
</PanelBody>
</InspectorControls>
{ ! inherit && layoutType && (
Expand Down Expand Up @@ -280,9 +310,10 @@ export const withLayoutStyles = createHigherOrderComponent(
const { layout } = attributes;
const { default: defaultBlockLayout } =
getBlockSupport( name, layoutBlockSupportKey ) || {};
const usedLayout = layout?.inherit
? defaultThemeLayout
: layout || defaultBlockLayout || {};
const usedLayout =
layout?.inherit || layout?.contentSize || layout?.wideSize
? { ...layout, type: 'constrained' }
: layout || defaultBlockLayout || {};
const layoutClasses = hasLayoutBlockSupport
? useLayoutClasses( usedLayout, defaultThemeLayout?.definitions )
: null;
Expand Down
Loading

0 comments on commit 93e29bb

Please sign in to comment.