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 a layout config to the group and theme.json and make alignments declarative #29335

Merged
merged 24 commits into from
Mar 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
732726b
Rethink FSE alignments
youknowriad Feb 25, 2021
8efe710
Move the style application to the server to keep the markup pure
youknowriad Feb 26, 2021
69945a7
Implement the layout addition to the group block as a support flag
youknowriad Mar 1, 2021
6ede44f
Only enable layouts for themes with theme.json
youknowriad Mar 1, 2021
192f069
Support post content layout
youknowriad Mar 2, 2021
21da8d4
Fix block name
youknowriad Mar 2, 2021
67f481c
Fix linting and unit tests
youknowriad Mar 3, 2021
8fdebe1
Update e2e tests snapshots
youknowriad Mar 3, 2021
2e59ef1
Document the default layout configuration
youknowriad Mar 4, 2021
e266b7c
Do not allow specific core/post-content layout config
youknowriad Mar 4, 2021
8565497
More stable multi-selection test
youknowriad Mar 4, 2021
f546bb5
Restore the group block inner container server side
youknowriad Mar 9, 2021
427c603
Tweak some verbiage.
jasmussen Mar 9, 2021
e34a2e1
Support inheriting global layout in the editor
youknowriad Mar 9, 2021
8957d68
Polish to match mockup.
jasmussen Mar 10, 2021
8ec5cc6
Prevent focus loss
youknowriad Mar 11, 2021
8d05994
Rename some classnames
youknowriad Mar 11, 2021
f4caae0
Tweak the verbiage.
jasmussen Mar 11, 2021
4499d1b
Remove BoxVisualizer from the group block
youknowriad Mar 16, 2021
a8000c7
Add floated block supports
youknowriad Mar 16, 2021
a457f79
Fix e2e tests
youknowriad Mar 16, 2021
f15a746
Add default margins for floated blocks
youknowriad Mar 16, 2021
01e434d
Fix failing image e2e test
youknowriad Mar 16, 2021
93f5e84
Cleanup per review
youknowriad Mar 18, 2021
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
76 changes: 36 additions & 40 deletions docs/how-to-guides/themes/block-based-themes.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ theme
|__ ...
```

The difference with existing WordPress themes is that the different templates in the template hierarchy, and template parts, are block templates instead of php files. In addition, this example includes an [`experimental-theme.json`](/docs/how-to-guides/themes/theme-json.md) file for some styles.
The difference with existing WordPress themes is that the different templates in the template hierarchy, and template parts, are block templates instead of php files. In addition, this example includes an [`experimental-theme.json`](/docs/how-to-guides/themes/theme-json.md) file for some styles.

## What is a block template?

Expand All @@ -50,20 +50,16 @@ Here's an example of a block template:

<!-- wp:group -->
<div class="wp-block-group">
<div class="wp-block-group__inner-container">
<!-- wp:post-title /-->
<!-- wp:post-content /-->
</div>
<!-- wp:post-title /-->
<!-- wp:post-content /-->
</div>
<!-- /wp:group -->

<!-- wp:group -->
<div class="wp-block-group">
<div class="wp-block-group__inner-container">
<!-- wp:heading -->
<h2>Footer</h2>
<!-- /wp:heading -->
</div>
<!-- wp:heading -->
<h2>Footer</h2>
<!-- /wp:heading -->
</div>
<!-- /wp:group -->
```
Expand All @@ -72,23 +68,23 @@ Here's an example of a block template:

Ultimately, any WordPress user with the correct capabilities (example: `administrator` WordPress role) will be able to access these templates in the WordPress admin, edit them in dedicated views and potentially export them as a theme.

As of Gutenberg 8.5, there are two ways to create and edit templates within Gutenberg.
As of Gutenberg 8.5, there are two ways to create and edit templates within Gutenberg.

### Edit templates within The "Appearance" section of WP-Admin

You can navigate to the temporary "Templates" admin menu under "Appearance" `wp-admin/edit.php?post_type=wp_template` and use this as a playground to edit your templates. Add blocks here and switch to the code editor mode to grab the HTML of the template when you are done. Afterwards, you can paste that markup into a file in your theme directory.

Please note that the "Templates" admin menu under "Appearance" will _not_ list templates that are bundled with your theme. It only lists new templates created by the specific WordPress site you're working on.
Please note that the "Templates" admin menu under "Appearance" will _not_ list templates that are bundled with your theme. It only lists new templates created by the specific WordPress site you're working on.

### Edit Templates within the Full-site Editor

To begin, create a blank template file within your theme. For example: `mytheme/block-templates/index.html`. Afterwards, open the Full-site editor. Your new template should appear as the active template, and should be blank. Add blocks as you normally would using Gutenberg. You can add and create template parts directly using the "Template Parts" block.
To begin, create a blank template file within your theme. For example: `mytheme/block-templates/index.html`. Afterwards, open the Full-site editor. Your new template should appear as the active template, and should be blank. Add blocks as you normally would using Gutenberg. You can add and create template parts directly using the "Template Parts" block.

Repeat for any additional templates you'd like to bundle with your theme.
Repeat for any additional templates you'd like to bundle with your theme.

When you're done, click the "Export Theme" option in the "Tools" (ellipsis) menu of the site editor. This will provide you with a ZIP download of all the templates and template parts you've created in the site editor. These new HTML files can be placed directly into your theme.
When you're done, click the "Export Theme" option in the "Tools" (ellipsis) menu of the site editor. This will provide you with a ZIP download of all the templates and template parts you've created in the site editor. These new HTML files can be placed directly into your theme.

Note that when you export template parts this way, the template part block markup will include a `postID` attribute that can be safely removed when distributing your theme.
Note that when you export template parts this way, the template part block markup will include a `postID` attribute that can be safely removed when distributing your theme.

## Templates CPT

Expand All @@ -102,33 +98,33 @@ Note that it won't take precedence over any of your theme's templates with highe

Some blocks have been made specifically for block-based themes. For example, you'll most likely use the **Site Title** block in your site's header while your **single** block template will most likely include a **Post Title** and a **Post Content** block.

As we're still early in the process, the number of blocks specifically dedicated to these block templates is relatively small but more will be added as we move forward with the project. As of Gutenberg 8.5, the following blocks are currently available:

- Site Title
- Template Part
- Query
- Query Loop
- Query Pagination
- Post Title
- Post Content
- Post Author
- Post Comment
- Post Comment Author
- Post Comment Date
- Post Comments
- Post Comments Count
- Post Comments Form
- Post Date
- Post Excerpt
- Post Featured Image
- Post Hierarchical Terms
- Post Tags
As we're still early in the process, the number of blocks specifically dedicated to these block templates is relatively small but more will be added as we move forward with the project. As of Gutenberg 8.5, the following blocks are currently available:

- Site Title
- Template Part
- Query
- Query Loop
- Query Pagination
- Post Title
- Post Content
- Post Author
- Post Comment
- Post Comment Author
- Post Comment Date
- Post Comments
- Post Comments Count
- Post Comments Form
- Post Date
- Post Excerpt
- Post Featured Image
- Post Hierarchical Terms
- Post Tags

## Styling

One of the most important aspects of themes (if not the most important) is the styling. While initially you'll be able to provide styles and enqueue them using the same hooks themes have always used, the [Global Styles](/docs/how-to-guides/themes/theme-json.md) effort will provide a scaffolding for adding many theme styles in the future.
One of the most important aspects of themes (if not the most important) is the styling. While initially you'll be able to provide styles and enqueue them using the same hooks themes have always used, the [Global Styles](/docs/how-to-guides/themes/theme-json.md) effort will provide a scaffolding for adding many theme styles in the future.

## Resources

- [Full Site Editing](https://github.com/WordPress/gutenberg/labels/%5BFeature%5D%20Full%20Site%20Editing) label.
- [Theme Experiments](https://github.com/WordPress/theme-experiments) repository, full of block-based theme examples created by the WordPress community.
- [Full Site Editing](https://github.com/WordPress/gutenberg/labels/%5BFeature%5D%20Full%20Site%20Editing) label.
- [Theme Experiments](https://github.com/WordPress/theme-experiments) repository, full of block-based theme examples created by the WordPress community.
15 changes: 13 additions & 2 deletions docs/how-to-guides/themes/theme-json.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,16 @@ The Block Editor API has evolved at different velocities and there are some grow

This describes the current efforts to consolidate the various APIs related to styles into a single point – a `experimental-theme.json` file that should be located inside the root of the theme directory.

### Global settings for the block editor

Instead of the proliferation of theme support flags or alternative methods, the `experimental-theme.json` files provides a canonical way to define the settings of the block editor. These settings includes things like:

- What customization options should be made available or hidden from the user.
- What are the default colors, font sizes... available to the user.
- Defines the default layout of the editor. (widths and available alignments).
### Settings can be controlled per block

The Block Editor already allows the control of specific settings such as alignment, drop cap, presets available, etc. All of these work at the block level. By using the `experimental-theme.json` we aim to allow themes to control these at a block level.
For more granularity, these settings also work at the block level in `experimental-theme.json`.

Examples of what can be achieved are:

Expand Down Expand Up @@ -156,7 +163,11 @@ The settings section has the following structure and default values:
```
{
"settings": {
"some/block": {
"defaults": {
youknowriad marked this conversation as resolved.
Show resolved Hide resolved
"layout": { /* Default layout to be used in the post editor */
"contentSize": "800px",
"wideSize": "1000px",
}
"border": {
"customRadius": false /* true to opt-in */
},
Expand Down
150 changes: 150 additions & 0 deletions lib/block-supports/layout.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
<?php
/**
* Layout block support flag.
*
* @package gutenberg
*/

/**
* Registers the layout block attribute for block types that support it.
*
* @param WP_Block_Type $block_type Block Type.
*/
function gutenberg_register_layout_support( $block_type ) {
$support_layout = false;
if ( property_exists( $block_type, 'supports' ) ) {
$support_layout = _wp_array_get( $block_type->supports, array( '__experimentalLayout' ), false );
}
if ( $support_layout ) {
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}

if ( ! array_key_exists( 'layout', $block_type->attributes ) ) {
youknowriad marked this conversation as resolved.
Show resolved Hide resolved
$block_type->attributes['layout'] = array(
'type' => 'object',
);
}
}
}

/**
* Renders the layout config to the block wrapper.
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @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 = false;
if ( $block_type && property_exists( $block_type, 'supports' ) ) {
$support_layout = _wp_array_get( $block_type->supports, array( '__experimentalLayout' ), false );
}
if ( ! $support_layout || ! isset( $block['attrs']['layout'] ) ) {
return $block_content;
}

$used_layout = $block['attrs']['layout'];
if ( isset( $used_layout['inherit'] ) && $used_layout['inherit'] ) {
$tree = WP_Theme_JSON_Resolver::get_merged_data( array(), 'theme' );
$default_layout = _wp_array_get( $tree->get_settings(), array( 'defaults', 'layout' ) );
if ( ! $default_layout ) {
return $block_content;
}
$used_layout = $default_layout;
}

$id = uniqid();
$content_size = isset( $used_layout['contentSize'] ) ? $used_layout['contentSize'] : null;
$wide_size = isset( $used_layout['wideSize'] ) ? $used_layout['wideSize'] : null;

$style = '';
if ( $content_size || $wide_size ) {
ob_start();
?>
<?php echo '.wp-container-' . $id; ?> > * {
max-width: <?php echo $content_size ? $content_size : $wide_size; ?>;
margin-left: auto;
margin-right: auto;
}

<?php echo '.wp-container-' . $id; ?> > .alignwide {
max-width: <?php echo $wide_size ? $wide_size : $content_size; ?>;
}

<?php echo '.wp-container-' . $id; ?> .alignfull {
max-width: none;
}
<?php
$style = ob_get_clean();
}

ob_start();
?>
<?php echo '.wp-container-' . $id; ?> .alignleft {
float: left;
margin-right: 2em;
}

<?php echo '.wp-container-' . $id; ?> .alignright {
float: right;
margin-left: 2em;
}
<?php
$style .= ob_get_clean();

// This assumes the hook only applys to blocks with a single wrapper.
// I think this is a reasonable limitation for that particular hoook.
$content = preg_replace(
'/' . preg_quote( 'class="', '/' ) . '/',
'class="wp-container-' . $id . ' ',
$block_content,
1
);

return $content . '<style>' . $style . '</style>';
Copy link
Member

Choose a reason for hiding this comment

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

@youknowriad Is there currently any API in PHP that we can use to combine all these styles at the start or end of the content?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we can potentially use wp_enqueue_style but I believe we do inline style tags already (lazy loading of styles), so it's not the only place we do that.

}

// Register the block support.
WP_Block_Supports::get_instance()->register(
'layout',
array(
'register_attribute' => 'gutenberg_register_layout_support',
)
);
add_filter( 'render_block', 'gutenberg_render_layout_support_flag', 10, 2 );
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mcsf same question as the other PR. Do we need to support this by default in the "block supports API"

Copy link
Contributor

Choose a reason for hiding this comment

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

(For reference, Riad is talking about the Duotone PR.)

I've been looking at this a bit, and I'm not sure. It's a departure from the explicit / get_block_wrapper_attributes. That's not necessarily bad, and this may be a necessary step, but it's worth discussing on its own. /cc @ajlende


/**
* For themes without theme.json file, make sure
* to restore the inner div for the group block
* to avoid breaking styles relying on that div.
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @return string Filtered block content.
*/
function gutenberg_restore_group_inner_container( $block_content, $block ) {
$group_with_inner_container_regex = '/(^(\s|\S)*<div\b[^>]*wp-block-group(\s|")[^>]*>)(([\s]|\S)*<div\b[^>]*wp-block-group__inner-container(\s|")[^>]*>)((.|\S|\s)*)/';

if (
'core/group' !== $block['blockName'] ||
WP_Theme_JSON_Resolver::theme_has_support() ||
1 === preg_match( $group_with_inner_container_regex, $block_content )
) {
return $block_content;
}

$replace_regex = '/(^(\s|\S)*<div\b[^>]*wp-block-group[^>]*>)((.|\S|\s)*)(<\/div>(\s|\S)*$)/m';
$updated_content = preg_replace_callback(
$replace_regex,
function( $matches ) {
return $matches[1] . '<div class="wp-block-group__inner-container">' . $matches[3] . '</div>' . $matches[5];
},
$block_content
);

return $updated_content;
}

add_filter( 'render_block', 'gutenberg_restore_group_inner_container', 10, 2 );
1 change: 1 addition & 0 deletions lib/class-wp-theme-json.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ class WP_Theme_JSON {
'customTextTransforms' => null,
),
'custom' => null,
'layout' => null,
youknowriad marked this conversation as resolved.
Show resolved Hide resolved
),
);

Expand Down
4 changes: 4 additions & 0 deletions lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,10 @@ function gutenberg_extend_block_editor_settings_with_default_editor_styles( $set
*/
function gutenberg_extend_block_editor_settings_with_fse_theme_flag( $settings ) {
$settings['isFSETheme'] = gutenberg_is_fse_theme();

// Enable the new layout options for themes with a theme.json file.
$settings['supportsLayout'] = WP_Theme_JSON_Resolver::theme_has_support();
youknowriad marked this conversation as resolved.
Show resolved Hide resolved

return $settings;
}
add_filter( 'block_editor_settings', 'gutenberg_extend_block_editor_settings_with_fse_theme_flag' );
Expand Down
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,4 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/block-supports/typography.php';
require __DIR__ . '/block-supports/custom-classname.php';
require __DIR__ . '/block-supports/border.php';
require __DIR__ . '/block-supports/layout.php';
18 changes: 0 additions & 18 deletions packages/base-styles/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -694,21 +694,3 @@
}
/* stylelint-enable function-comma-space-after */
}

/**
* These are default block editor widths in case the theme doesn't provide them.
*/
@mixin default-block-widths {

.wp-block {
max-width: $content-width;

&[data-align="wide"] {
max-width: $wide-content-width;
}

&[data-align="full"] {
max-width: none;
}
}
}
1 change: 1 addition & 0 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ _Type Definition_
_Properties_

- _alignWide_ `boolean`: Enable/Disable Wide/Full Alignments
- _supportsLayout_ `boolean`: Enable/disable layouts support in container blocks.
- _availableLegacyWidgets_ `Array`: Array of objects representing the legacy widgets available.
- _imageEditing_ `boolean`: Image Editing settings set to false to disable.
- _imageSizes_ `Array`: Available image sizes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
/**
* Internal dependencies
*/
import { useLayout } from '../inner-blocks/layout';
import { useLayout } from '../block-list/layout';
import { store as blockEditorStore } from '../../store';

const BLOCK_ALIGNMENTS_CONTROLS = {
Expand Down Expand Up @@ -70,11 +70,12 @@ function BlockAlignmentUI( {
if ( ! supportsAlignments ) {
return null;
}

const { alignments: availableAlignments = DEFAULT_CONTROLS } = layout;
const enabledControls = controls.filter(
( control ) =>
( wideControlsEnabled || ! WIDE_CONTROLS.includes( control ) ) &&
( layout.alignments || // Ignore the global wideAlignment check if the layout explicitely defines alignments.
wideControlsEnabled ||
! WIDE_CONTROLS.includes( control ) ) &&
availableAlignments.includes( control )
);

Expand Down
Loading