gutenberg icon indicating copy to clipboard operation
gutenberg copied to clipboard

Block.json: Refactor and stabilize selectors API

Open aaronrobertshaw opened this issue 2 years ago • 8 comments

Related:

  • https://github.com/WordPress/gutenberg/issues/45194
  • https://github.com/WordPress/gutenberg/pull/46579

What?

Refactors the block.json selectors API.

  • Moves the __experimentalSelector props within supports into their own selectors config.
  • The block's primary __experiementalSelector prop is merged into the new selectors config via the root prop.
  • The selectors API is stabilized as part of this refactor
  • Adds greater flexibility allowing individual styles within block support features to be applied to arbitrary selectors
  • Allows fallback to appropriate "root" selectors if the individual style isn't set in the selectors config
  • Allows entire block support feature to have a single selector applied via a simple string value

Why?

The experimental selectors have been around for a while now and are beginning to be relied upon more. There's also an increasing need for greater flexibility in setting selectors for individual block support styles.

For more info and history see: https://github.com/WordPress/gutenberg/issues/45194

How?

https://github.com/WordPress/gutenberg/pull/46496/commits/698f705c28dc4fb1f58238547b2d5ff7e730cb1b

Updates Gutenberg’s block registration to polyfill the selectors prop until it is included in the server-provided definitions. Temporary unit test added for the polyfill.

https://github.com/WordPress/gutenberg/pull/46496/commits/e53f168fb331b05d22b89030b37d69642a5a33b1

Adds theme.json unit tests for stylesheet generation using blocks leveraging the new selectors API. The old feature selectors test is maintained and could be deprecated as blocks migrate to the stabilised API.

Due to the updated block metadata, a test block needs to be registered during the phpunit bootstrap so that it is present before WordPress runs and the theme.json block metadata is cached.

A follow-up is currently looking at if we can invalidate the metadata cache and move the test block registrations to their respective tests.

https://github.com/WordPress/gutenberg/pull/46496/commits/a2a91ef597b6e21dbccd7441f8cd638cc7dce701

This commit contains the bulk of the updates and overrides to the theme.json class to allow the processing of selectors and using them in generating styles for blocks.

https://github.com/WordPress/gutenberg/pull/46496/commits/e46856188a878960035a8b32587befb4df22fb2a

Adds the selectors to the block.json schema. The available shape for the selectors API almost matches that of the block supports.

An important difference is that it will accept a root selectors which replace the old __experimentalSelector for the block as a whole as well as act as generic selector for each feature e.g. color, typography etc.

https://github.com/WordPress/gutenberg/pull/46496/commits/8b9d0b190c518edcf2cced04684de15068cdb768

Updates the Image block.json to use the new selectors API instead of __experimentalBorder.__experimentalSelector.

https://github.com/WordPress/gutenberg/pull/46496/commits/323f931a536df2480ced5f790f17a9040047aa0e

Add a global function that can be leveraged to retrieve selectors for specific block types and feature/subfeature.

https://github.com/WordPress/gutenberg/pull/46496/commits/0e08b6cf6b81e21c2f330cc4e70e040de8e85073

Update theme.json class to leverage the new block CSS selector function.

https://github.com/WordPress/gutenberg/pull/46496/commits/2be12429c67cb3889d6905264f6bd49f21b2f7fc

Adds a block_type_metadata_settings filter to the lib/compat/wordpress-6.2/blocks.php file ensuring that the selectors metadata is present in the block type settings. This will be required until the minimum supported WP version is >= 6.2.

Testing Instructions

  1. Confirm theme.json tests pass: npm run test:unit:php -- --filter WP_Theme_JSON_Gutenberg_Test
  2. Confirm JS block registration tests pass: npm run test:unit packages/blocks/src/api/test/registration
  3. In your theme.json add some border styles for the core/image block.
  4. Load the editor, add an Image block, and confirm those styles are still correctly displayed.
  5. Begin cropping the image and ensure that border styles are still applied.
  6. Cancel cropping, save the post, and confirm the border on the frontend.

Next Steps

If the current approach is accepted we'll need a small patch to core to update the allowed properties during block registration.

diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php
index 29e375ab89..cd651808bf 100644
--- a/src/wp-includes/blocks.php
+++ b/src/wp-includes/blocks.php
@@ -378,6 +378,7 @@ function register_block_type_from_metadata( $file_or_folder, $args = array() ) {
 		'attributes'      => 'attributes',
 		'providesContext' => 'provides_context',
 		'usesContext'     => 'uses_context',
+		'selectors'       => 'selectors',
 		'supports'        => 'supports',
 		'styles'          => 'styles',
 		'variations'      => 'variations',

Trac Ticket: TBA GitHub PR: TBA

aaronrobertshaw avatar Dec 13 '22 08:12 aaronrobertshaw

Size Change: +67 B (0%)

Total Size: 1.34 MB

Filename Size Change
build/block-library/index.min.js 201 kB +20 B (0%)
build/blocks/index.min.js 51.1 kB +47 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 993 B
build/annotations/index.min.js 2.78 kB
build/api-fetch/index.min.js 2.27 kB
build/autop/index.min.js 2.15 kB
build/blob/index.min.js 483 B
build/block-directory/index.min.js 7.2 kB
build/block-directory/style-rtl.css 1.04 kB
build/block-directory/style.css 1.04 kB
build/block-editor/content-rtl.css 4.11 kB
build/block-editor/content.css 4.1 kB
build/block-editor/default-editor-styles-rtl.css 403 B
build/block-editor/default-editor-styles.css 403 B
build/block-editor/index.min.js 197 kB
build/block-editor/style-rtl.css 14.4 kB
build/block-editor/style.css 14.4 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 138 B
build/block-library/blocks/audio/theme.css 138 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 91 B
build/block-library/blocks/avatar/style.css 91 B
build/block-library/blocks/block/editor-rtl.css 305 B
build/block-library/blocks/block/editor.css 305 B
build/block-library/blocks/button/editor-rtl.css 587 B
build/block-library/blocks/button/editor.css 587 B
build/block-library/blocks/button/style-rtl.css 628 B
build/block-library/blocks/button/style.css 627 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 239 B
build/block-library/blocks/calendar/style.css 239 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 100 B
build/block-library/blocks/categories/style.css 100 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 406 B
build/block-library/blocks/columns/style.css 406 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 199 B
build/block-library/blocks/comment-template/style.css 198 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 612 B
build/block-library/blocks/cover/editor.css 613 B
build/block-library/blocks/cover/style-rtl.css 1.6 kB
build/block-library/blocks/cover/style.css 1.59 kB
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 138 B
build/block-library/blocks/embed/theme.css 138 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 265 B
build/block-library/blocks/file/style.css 265 B
build/block-library/blocks/file/view.min.js 353 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 984 B
build/block-library/blocks/gallery/editor.css 988 B
build/block-library/blocks/gallery/style-rtl.css 1.55 kB
build/block-library/blocks/gallery/style.css 1.55 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 654 B
build/block-library/blocks/group/editor.css 654 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/html/editor-rtl.css 332 B
build/block-library/blocks/html/editor.css 333 B
build/block-library/blocks/image/editor-rtl.css 830 B
build/block-library/blocks/image/editor.css 829 B
build/block-library/blocks/image/style-rtl.css 652 B
build/block-library/blocks/image/style.css 652 B
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/latest-comments/style-rtl.css 357 B
build/block-library/blocks/latest-comments/style.css 357 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 478 B
build/block-library/blocks/latest-posts/style.css 478 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 507 B
build/block-library/blocks/media-text/style.css 505 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 716 B
build/block-library/blocks/navigation-link/editor.css 715 B
build/block-library/blocks/navigation-link/style-rtl.css 115 B
build/block-library/blocks/navigation-link/style.css 115 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 299 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation/editor-rtl.css 2.13 kB
build/block-library/blocks/navigation/editor.css 2.14 kB
build/block-library/blocks/navigation/style-rtl.css 2.22 kB
build/block-library/blocks/navigation/style.css 2.2 kB
build/block-library/blocks/navigation/view-modal.min.js 2.81 kB
build/block-library/blocks/navigation/view.min.js 447 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 401 B
build/block-library/blocks/page-list/editor.css 401 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 174 B
build/block-library/blocks/paragraph/editor.css 174 B
build/block-library/blocks/paragraph/style-rtl.css 279 B
build/block-library/blocks/paragraph/style.css 281 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 501 B
build/block-library/blocks/post-comments-form/style.css 501 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 B
build/block-library/blocks/post-excerpt/editor-rtl.css 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 134 B
build/block-library/blocks/post-excerpt/style.css 134 B
build/block-library/blocks/post-featured-image/editor-rtl.css 586 B
build/block-library/blocks/post-featured-image/editor.css 584 B
build/block-library/blocks/post-featured-image/style-rtl.css 322 B
build/block-library/blocks/post-featured-image/style.css 322 B
build/block-library/blocks/post-navigation-link/style-rtl.css 153 B
build/block-library/blocks/post-navigation-link/style.css 153 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 282 B
build/block-library/blocks/post-template/style.css 282 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 326 B
build/block-library/blocks/pullquote/style.css 325 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 288 B
build/block-library/blocks/query-pagination/style.css 284 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/query/editor-rtl.css 463 B
build/block-library/blocks/query/editor.css 463 B
build/block-library/blocks/quote/style-rtl.css 222 B
build/block-library/blocks/quote/style.css 222 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/read-more/style-rtl.css 132 B
build/block-library/blocks/read-more/style.css 132 B
build/block-library/blocks/rss/editor-rtl.css 149 B
build/block-library/blocks/rss/editor.css 149 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 409 B
build/block-library/blocks/search/style.css 406 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 234 B
build/block-library/blocks/separator/style.css 234 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 474 B
build/block-library/blocks/shortcode/editor.css 474 B
build/block-library/blocks/site-logo/editor-rtl.css 489 B
build/block-library/blocks/site-logo/editor.css 489 B
build/block-library/blocks/site-logo/style-rtl.css 203 B
build/block-library/blocks/site-logo/style.css 203 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.4 kB
build/block-library/blocks/social-links/style.css 1.39 kB
build/block-library/blocks/spacer/editor-rtl.css 332 B
build/block-library/blocks/spacer/editor.css 332 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 433 B
build/block-library/blocks/table/editor.css 433 B
build/block-library/blocks/table/style-rtl.css 651 B
build/block-library/blocks/table/style.css 650 B
build/block-library/blocks/table/theme-rtl.css 157 B
build/block-library/blocks/table/theme.css 157 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 404 B
build/block-library/blocks/template-part/editor.css 404 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 99 B
build/block-library/blocks/verse/style.css 99 B
build/block-library/blocks/video/editor-rtl.css 552 B
build/block-library/blocks/video/editor.css 555 B
build/block-library/blocks/video/style-rtl.css 179 B
build/block-library/blocks/video/style.css 179 B
build/block-library/blocks/video/theme-rtl.css 139 B
build/block-library/blocks/video/theme.css 139 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.11 kB
build/block-library/common.css 1.11 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 11.6 kB
build/block-library/editor.css 11.6 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/style-rtl.css 12.7 kB
build/block-library/style.css 12.7 kB
build/block-library/theme-rtl.css 698 B
build/block-library/theme.css 703 B
build/block-serialization-default-parser/index.min.js 1.13 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/components/index.min.js 208 kB
build/components/style-rtl.css 11.7 kB
build/components/style.css 11.7 kB
build/compose/index.min.js 12.4 kB
build/core-data/index.min.js 16.3 kB
build/customize-widgets/index.min.js 12.2 kB
build/customize-widgets/style-rtl.css 1.41 kB
build/customize-widgets/style.css 1.41 kB
build/data-controls/index.min.js 663 B
build/data/index.min.js 8.58 kB
build/date/index.min.js 40.4 kB
build/deprecated/index.min.js 518 B
build/dom-ready/index.min.js 336 B
build/dom/index.min.js 4.72 kB
build/edit-post/classic-rtl.css 571 B
build/edit-post/classic.css 571 B
build/edit-post/index.min.js 34.8 kB
build/edit-post/style-rtl.css 7.55 kB
build/edit-post/style.css 7.54 kB
build/edit-site/index.min.js 65.3 kB
build/edit-site/style-rtl.css 10.2 kB
build/edit-site/style.css 10.2 kB
build/edit-widgets/index.min.js 17.3 kB
build/edit-widgets/style-rtl.css 4.56 kB
build/edit-widgets/style.css 4.56 kB
build/editor/index.min.js 45.8 kB
build/editor/style-rtl.css 3.54 kB
build/editor/style.css 3.53 kB
build/element/index.min.js 4.95 kB
build/escape-html/index.min.js 548 B
build/format-library/index.min.js 7.26 kB
build/format-library/style-rtl.css 557 B
build/format-library/style.css 556 B
build/hooks/index.min.js 1.66 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.79 kB
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.79 kB
build/keycodes/index.min.js 1.94 kB
build/list-reusable-blocks/index.min.js 2.14 kB
build/list-reusable-blocks/style-rtl.css 865 B
build/list-reusable-blocks/style.css 865 B
build/media-utils/index.min.js 2.99 kB
build/notices/index.min.js 977 B
build/plugins/index.min.js 1.95 kB
build/preferences-persistence/index.min.js 2.23 kB
build/preferences/index.min.js 1.35 kB
build/primitives/index.min.js 960 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 937 B
build/react-i18n/index.min.js 702 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.75 kB
build/reusable-blocks/index.min.js 2.26 kB
build/reusable-blocks/style-rtl.css 265 B
build/reusable-blocks/style.css 265 B
build/rich-text/index.min.js 11 kB
build/server-side-render/index.min.js 2.09 kB
build/shortcode/index.min.js 1.52 kB
build/style-engine/index.min.js 1.53 kB
build/token-list/index.min.js 650 B
build/url/index.min.js 3.74 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.8 kB
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 1.09 kB
build/warning/index.min.js 280 B
build/widgets/index.min.js 7.3 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.18 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

github-actions[bot] avatar Dec 13 '22 09:12 github-actions[bot]

I've updated this PR to be based on top of the work being done to bundle WP_Theme_JSON instead of inheriting per WordPress version.

I'll be AFK for a couple of weeks although @glendaviesnz graciously offered to help keep this moving along. 🙇

aaronrobertshaw avatar Dec 16 '22 05:12 aaronrobertshaw

When the base branch was switched to trunk it didn't clear all the commits belonging to the try/bundle-theme-json-class. I've rebased this and removed them.

oandregal avatar Dec 27 '22 11:12 oandregal

Flaky tests detected in 8aa8f2405f994fdfc134f0dc9a12d301066f9b98. Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/4463329303 📝 Reported issues:

  • #42245 in /test/e2e/specs/site-editor/template-part.spec.js
  • #47747 in /test/e2e/specs/site-editor/template-part.spec.js
  • #44341 in specs/editor/plugins/cpt-locking.test.js

github-actions[bot] avatar Jan 17 '23 04:01 github-actions[bot]

I'll do a full review tomorrow, but one thing I was thinking about was how the duotone filter previously expected just the __experimentalDuotone supports string to enable it, but now that the string is nested under selectors, we should probably add a duotone boolean to supports for enabling it in addition to the selector like the rest of the supports.

ajlende avatar Jan 27 '23 06:01 ajlende

I really appreciate the feedback @gziolo, it's great to have you back online!

It's going to be a bit more work inside WordPress core. All top-level block-type properties need to be included in the WP_Block_Type class and exposed through the REST API endpoint for block types. Once you land this PR in Gutenberg, I'll be happy to help with all the necessary changes.

I was actually just in the process of submitting a core patch (https://github.com/WordPress/wordpress-develop/pull/3942) with the additional scope you've suggested. Please let me know if I've missed anything 🙏

I also encourage you to document the new API at least inside Metadata in block.json document so everyone can see whether the name selectors is the best way to express its intent compared to all other top-level settings.

Will do. Thanks for the suggestion. I'll put something together and update this PR accordingly.

aaronrobertshaw avatar Jan 30 '23 10:01 aaronrobertshaw

Some draft documentation has been added via https://github.com/WordPress/gutenberg/pull/46496/commits/ce4754d9e2cfdbf7d37f1e65d042ba6476f4db65 to get the discussion started. I'm out of time today but will come back and refine it into something more readable tomorrow.

aaronrobertshaw avatar Jan 30 '23 11:01 aaronrobertshaw

@aaronrobertshaw, that was an instant response to the feedback. I will have a closer look later this week, but it seems like you covered all that I shared 💯

gziolo avatar Jan 30 '23 11:01 gziolo

Thanks for taking the time to review this @gziolo 🙇

I believe I've addressed all the current feedback here and on the core patch. I ultimately decided to make the selectors prop default to an empty array on the server and tweaked some checks for it in this PR (https://github.com/WordPress/gutenberg/pull/46496/commits/7f3571e1c62f5ace4f70d3d7815b89caf7b14b21). Happy to change it again if we decide that is better.

In addition, I also relocated the new global function to retrieve a CSS selector for a block to the lib/compat/wordpress-6.3 folder (https://github.com/WordPress/gutenberg/pull/46496/commits/bd73e185324c453cc298e57bebb8dfff22976bb1).

I've given this another test following the instructions in the PR, and it's still working well for me. Hopefully, this should be getting pretty close now.

aaronrobertshaw avatar Feb 14 '23 06:02 aaronrobertshaw

I believe I've addressed all the current feedback here and on the core patch. I ultimately decided to make the selectors prop default to an empty array on the server and tweaked some checks for it in this PR (https://github.com/WordPress/gutenberg/commit/7f3571e1c62f5ace4f70d3d7815b89caf7b14b21). Happy to change it again if we decide that is better.

Yes, everything looks good regarding that. Excellent work covering all aspects of promoting an experimental API to something that becomes official!

I marked the core patch as ready to commit, but we need to wait for that part until the release cycle for WordPress 6.2 is finished. I'm unfamiliar with the implementation of selectors and their integration with theme.json, so I will leave that part to other reviewers.

gziolo avatar Feb 14 '23 08:02 gziolo

I know this feedback is coming very late, and I am probably missing important context, but what do you think about the selector living within the supports key, as was done with the __experimentalSelector, something like this:

	"supports": {
		"color": {
			"selector": "img, .wp-block-post-featured-image__placeholder, .components-placeholder__illustration, .components-placeholder::before",
			"text": false,
			"background": false
		},
		"__experimentalBorder": {
			"color": true,
			"radius": true,
			"width": true,
			"Selector": "img, .block-editor-media-placeholder, .wp-block-post-featured-image__overlay",
		},
	},

scruffian avatar Feb 22 '23 13:02 scruffian

I know this feedback is coming very late, and I am probably missing important context, but what do you think about the selector living within the supports key, as was done with the __experimentalSelector, something like this:

The potential shape and location of the API was discussed in https://github.com/WordPress/gutenberg/issues/45194.

A few of the reasons for making the selectors API a first-class citizen of the block.json API were:

  • To make it easier to grok and see at a glance custom selectors for the block, especially with regards to falling back to broader scope selectors
  • Compared with the suggested shape here it allows for sub-features e.g. font size and text decoration to target different selectors.
  • Selectors aren't really a flag to state something is supported or not and don't really conceptually fit under supports

aaronrobertshaw avatar Feb 22 '23 23:02 aaronrobertshaw

I thought of another consideration that I haven't seen discussed yet. The post featured image block adds the placeholder selector to the list for duotone so the filter can be seen on the preview placeholder in the editor.

This placeholder isn't used on the final page, but the selectors are still there. Would it be a good idea to support a separate editor-only selector in the stabilized API?

ajlende avatar Feb 28 '23 16:02 ajlende

Would it be a good idea to support a separate editor-only selector in the stabilized API?

Thanks for raising this @ajlende 👍

I'd definitely like to see something like this offered. In addition to the Post Featured Image placeholder example, the Image block has a selector targeting the image cropper which is editor only.

What do people think of adding editor as a top-level property in the selectors object?

An incomplete example for the Image block and its borders could be:

{
	"selectors": {
		"border": ".wp-block-image img",
		"editor": {
			"border": ".wp-block-image img, .wp-block-image .wp-block-image__crop-area"
		}
	}
}

Another question might be should the selectors within such an editor object override or be merged within the normal selectors? Having them override the selector for the editor context would be explicit and allow completely different selectors between the editor and frontend. The downside is if you want both, it's slightly more verbose.

Either way, I think I'd like to explore the potential for editor-only selectors in a follow-up once we land this initial MVP.

aaronrobertshaw avatar Mar 06 '23 08:03 aaronrobertshaw

We can land changes in WordPress core after WP 6.2 RC1 that happened yesterday. Whenever you are ready with the Gutenberg part, I can take care of the core part.

gziolo avatar Mar 10 '23 11:03 gziolo

I have one question about the whole selector feature 🤔

Are there any plans to also make this work for dynamic blocks? Currently if you opt into a block support like for example spacing, all the styles get added as line styles to the element which gets the get_block_wrapper_attributes added to it.

It would be cool if the styles would either get output via the global styles engine into a style tag which then targets the correct selector, or if there were more additional PHP functions to apply various supports to various elements. :)

Thanks in advance :)

fabiankaegy avatar Mar 10 '23 11:03 fabiankaegy

What do people think of adding editor as a top-level property in the selectors object?

@aaronrobertshaw I would prefer to not mix the block supports keys with a special editor key.

It might be better if could have a top level editorSelectors that would match the styles and editorStyles pattern that we already have.

{
	"selectors": {
		"border": ".wp-block-image img"
	},
	"editorSelectors": {
		"border": ".wp-block-image img, .wp-block-image .wp-block-image__crop-area"
	}
}

Or we could add a { "selector": "", "editorSelector": "" } option at each leaf.

{
	"selectors": {
		"border": {
			"selector": ".wp-block-image img",
			"editorSelector": ".wp-block-image img, .wp-block-image .wp-block-image__crop-area"
		}
	}
}

Both of those options, I think could be okay. The first seems easier, especially since the API currently supports situations where you could have a string or object already for sub-features.

ajlende avatar Mar 10 '23 16:03 ajlende

I have one question about the whole selector feature 🤔

Thanks for the question @fabiankaegy 👍

Are there any plans to also make this work for dynamic blocks?

The generation of theme.json and global styles using this selectors API works independently of whether or not a block is dynamic.

It would be cool if the styles would either get output via the global styles engine into a style tag which then targets the correct selector, or if there were more additional PHP functions to apply various supports to various elements. :)

At this stage, the stabilization of the Selectors API is focused primarily on its existing use. However, as you note, being able to determine what a block's selector should be for a given feature opens up new possibilities that we can explore.

One catch though with the proposal to output individual block styles via classes and a style tag is that themes can add styles in various ways. When a user makes a selection for an individual block, that selection needs to be honoured. I believe that is a major factor in why inline styles or CSS classes with (unfortunate) ! important rules are needed for the time being.

This selectors API might well end up being a useful piece to the puzzle in cleaning up the application of individual block styles. I see that overall goal though being more under the banner of the style engine which you can follow progress on in https://github.com/WordPress/gutenberg/issues/38167.

aaronrobertshaw avatar Mar 13 '23 08:03 aaronrobertshaw

@ajlende I've updated this PR to include support for editor-only selectors and the revised location for duotone (filters.duotone) if you'd like to take it for a spin.

The related core patch has also been updated to add editor selectors to block types.

If everyone is happy with the shape of the selectors & editorSelectors objects and how editor selectors override normal ones, we can look to get this all merged.

aaronrobertshaw avatar Mar 16 '23 07:03 aaronrobertshaw

This PR is open for quite some time already, so it's been on my mind while doing different things. I run into Element styles that you can define in theme.json:

https://github.com/WordPress/gutenberg/blob/b1dce4e1320cf4bb723cf9f162013d4881d7c0ba/docs/how-to-guides/themes/theme-json.md?plain=1#L974-L1041

How much selectors differ conceptually from elements, other than the latter is a controlled predefined list? How selectors from block.json and elements from theme.json work together?

gziolo avatar Mar 16 '23 08:03 gziolo

Thanks for testing @ajlende 👍

Global styles image border seems to be working fine on the frontend, but it isn't showing up in the editor.

Global styles for the image border are working ok for me as per the video below.

Is there any chance you were testing with this suggestion applied? With that change, was the only way I could replicate the border not showing in the editor.

https://user-images.githubusercontent.com/60436221/225818643-707bee0c-1008-40c7-819f-926f22d9a032.mp4

Those changes will come in a follow-up PR that I can work on, so it shouldn't hold up this one.

Sounds like a plan 🙂

aaronrobertshaw avatar Mar 17 '23 05:03 aaronrobertshaw

How much selectors differ conceptually from elements, other than the latter is a controlled predefined list? How selectors from block.json and elements from theme.json work together?

Good questions @gziolo

I'll do my best to articulate an answer but there might be others that have a deeper understanding of the Elements API that can help paint a complete picture. cc @oandregal, @jorgefilipecosta

Elements API

The Elements API provides a mechanism to style elements (h1-h6, buttons, links etc) site-wide and across all blocks, regardless of what block supports they may adopt. Because this one-style fits all approach is unlikely to work in all cases, the Elements API can be leveraged on a per-block-type basis so the site-wide element styles can be overridden.

Due to the breadth of their potential impact, supported elements need to be rather restricted. Not all internal elements targetted by blocks using the Selectors API for Global Styles make sense to be styled site-wide. In addition, the current UI for elements is limited and only a subset of styles is intended to be supported for styling across all blocks.

Element styles also can't be overridden for an individual block only tweaked for all blocks of a given block type.

Selectors API

The Selectors API allows a block author to direct global styles to target specific elements in the block. This is needed to maintain visual consistency when a block skips serialization of block support styles on the wrapper and applies them manually to inner elements (see Image or Search blocks).

The inner elements that might be targeted by custom selectors could be anything; an element by class or id, something via various pseudo selectors e.g. :first-child, :nth-child etc. Maybe applying global styles based on context such as the inline image cropper in the editor, or when a block is nested within a specific block.

The Selectors API as proposed in this PR would also allow for subfeatures to target different elements e.g. applying text-decoration to links rather than the whole nav in order to avoid the fact that browsers paint that style differently.

Summary

I don't think we have enough alignment or overlap between the Elements and Selectors APIs to consolidate them. That could change in future as they are both evolving. For the time being, keeping the distinction between them due to their differing primary purposes might aid that evolution.

We also already effectively have the selectors API via the supports.__experimentalSelector properties that we need to support moving forward. I don't think stabilizing that now really prevents us from re-evaluating combining APIs down the road should it ever be possible.

TL;DR

Ultimately, I'd say the conceptual difference between the elements and selectors APIs is;

  • Elements API allows styling of elements independent of blocks and is applied site-wide in general
  • Selectors API helps a block ensure global styles generated for it, target the appropriate elements within the block matching its use of block supports

I hope that helps at least a little 🙂

aaronrobertshaw avatar Mar 17 '23 06:03 aaronrobertshaw

I'll do my best to articulate an answer but there might be others that have a deeper understanding of the Elements API that can help paint a complete picture.

That’s an excellent summary which I hope we can incorporate in the future in the handbook. Thank you so much for the effort to put it together. I don’t I’m the only person who is going to wonder what’s the relationship between these concepts that are similar at first glance. It looks like had a quite good understanding of the differences between both APIs but it might not be so clear for everyone.

gziolo avatar Mar 21 '23 10:03 gziolo

Thanks for the feedback and reviews everyone.

With that said, I plan to study this week the difference between the shape of objects used for selectors and elements...I will get back with any ideas I would come up with.

I'll still aim to get this merged soon and iterate on it from there so long as there are no objections to that.

In fact, the comment https://github.com/WordPress/gutenberg/issues/49070#issuecomment-1474044191 from @scruffian pictures the idea that I was contemplating

I did reply to that comment. I don't think we should be nesting elements under selectors but instead, follow the now-established pattern and introduce something like elementSelectors. That would fit alongside the current selectors/editorSelectors, and style/editorStyle metadata properties in block.json.

It would also have the added benefit of isolating the element selectors changes and facilitate working on it as a follow-up to this.

aaronrobertshaw avatar Mar 22 '23 01:03 aaronrobertshaw

I'll still aim to get this merged soon and iterate on it from there so long as there are no objections to that.

I thought I said it clearly enough you should land it. We might never need any follow-up PRs. Async communication is hard 😃

I don't think we should be nesting elements under selectors but instead, follow the now-established pattern and introduce something like elementSelectors.

That makes sense. I didn't refer to that though. Instead, I expressed that having a different syntax for selectors could be easier to follow for devs familiar with theme.json, but it's really a speculation as I don't even know if that is even technically possible (or makes sense):

 {
 	"selectors": {
 		".my-custom-block-selector": "root",
 		".my-custom-block-selector p": {
 		    "color": {
 			"text": true
                    }
 		},
                ".my-custom-block-selector > h2": {
 		    "typography": "root"
                 },
                ".my-custom-block-selector > h2 span": {
                    "typography": {
 			"text-decoration": true
                    }
 		}
 	}
 }

gziolo avatar Mar 22 '23 07:03 gziolo

I thought I said it clearly enough you should land it.

Thanks, you did. What I should have added was that I'd had a discussion yesterday with other team members and was giving them the opportunity for a final code review before merging today or tomorrow.

Instead, I expressed that having a different syntax for selectors could be easier to follow for devs familiar with theme.json

Ah ok, I misunderstood. Appreciate the clarification and example. Given this PR got merged overnight, we can explore that in a follow-up if desired.

One goal of the selectors object was for 3rd parties to be able to easily determine what the selector was for a particular feature. Keying by the feature probably makes that a lot easier.

aaronrobertshaw avatar Mar 23 '23 00:03 aaronrobertshaw

One goal of the selectors object was for 3rd parties to be able to easily determine what the selector was for a particular feature. Keying by the feature probably makes that a lot easier.

One way to verify is to open a follow-up PR that refactors all usage of __experimentalSelector. A quick search in the repository shows that isn't a widely popular feature at the moment. Maybe it doesn't matter that much after all 😄

gziolo avatar Mar 23 '23 05:03 gziolo

In this PR I missed updating the useGlobalOutput JS hook to use the new selectors API. In addition, while it was awaiting review, the new style variations via Global Styles leveraged the feature selectors. After rebasing this PR, the processing of style variations wasn't updated and no unit tests caught it being broken.

I'll put together a tracking issue shortly to collect what's missing and needs fixing. From there we can assess whether this PR should be reverted in the short term or not.

aaronrobertshaw avatar Mar 27 '23 08:03 aaronrobertshaw

It looks like I merged this PR prematurely - sorry about that. I have created a revert here since the revert button didn't work: https://github.com/WordPress/gutenberg/pull/49372. Feel free to update/merge it if its helpful.

scruffian avatar Mar 27 '23 15:03 scruffian

As per this discussion, I've created a draft PR (https://github.com/WordPress/gutenberg/pull/49393) to fix the Selectors API and remove the editor-only selectors functionality.

aaronrobertshaw avatar Mar 28 '23 07:03 aaronrobertshaw