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

Expose before filter hook in useSettings for injecting block settings in the editor #45089

Merged
merged 35 commits into from
Dec 6, 2022
Merged

Expose before filter hook in useSettings for injecting block settings in the editor #45089

merged 35 commits into from
Dec 6, 2022

Conversation

ingeniumed
Copy link
Contributor

@ingeniumed ingeniumed commented Oct 19, 2022

What?

This is a combined PR from @alecgeatches and I, that works on the feedback provided to us on our original governance PR.

We have added in a client-side hook in useSetting per @mcsf's recommendation to provide block settings to the editor before it renders.

Why?

This PR is meant to help solve this issue around governance. @dabowman has done a great job explaining this within this issue.

Our previous PR had tried to implement a solution to this issue by baking everything into Gutenberg itself. The feedback that we received on this PR was to minimize the changes that we are proposing into Gutenberg, as the use case that we are trying to solve is not something that a majority of users would take advantage of. In addition there are other issues associated with trying to figure out the best UI to drive this feature as well.

As a result, we went back to work to try to come up with a much simpler solution that tries to minimize the changes going into Gutenberg while still allowing us to be able to solve the original issue. This is that PR as it allows us to make a plugin to get this feature in, without imposing too many changes into Gutenberg.

How?

Creating a new filter blockEditor.useSetting.before: This allows the injection of block settings into the block editor before everything is rendered, so we are able to customize the settings available for a block however we want.

Testing Instructions

We have added in two tests (scaled down from the previous PR test changes) that test the new hook addition. There's some select( blockEditorStore ) mocking necessary to unit test useSetting(). Hopefully these tests provide some value, but we'd love to know if there's a better way to approach tests here. These can be run via:

npm run test:unit -- use-setting/test/index.js

alecgeatches and others added 22 commits September 20, 2022 17:03
Add blockEditor.useSetting.before hook to useSetting
Add support for adding in a filter for sanitize/CSS selectors for blocks
Make get_blocks_metadata() public for selector access
Remove the previous way of doing the nesting via filters
@codesandbox
Copy link

codesandbox bot commented Oct 19, 2022

CodeSandbox logoCodeSandbox logo  Open in CodeSandbox Web Editor | VS Code | VS Code Insiders

@github-actions github-actions bot added the First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository label Oct 19, 2022
@github-actions
Copy link

👋 Thanks for your first Pull Request and for helping build the future of Gutenberg and WordPress, @ingeniumed! In case you missed it, we'd love to have you join us in our Slack community, where we hold regularly weekly meetings open to anyone to coordinate with each other.

If you want to learn more about WordPress development in general, check out the Core Handbook full of helpful information.

@ingeniumed
Copy link
Contributor Author

Thanks for breaking down the expectations you have for the filter being introduced in this PR, so we can be sure that we are on the same page!

If role-based data means enable/disable settings based on the author's role, there may be an alternate path you can use now. Did you take a look at the existing filters introduced in WordPress 6.1 https://make.wordpress.org/core/2022/10/10/filters-for-theme-json-data/ In the server, hooking into wp_theme_json_data_user and provide new settings based on the user's role should be enough.

Thank you for that suggestion! That's a good idea for our role use-case. In general, we do want to allow the consumer to have different settings for different block_instances. We would also like to consider surrounding context like the before/after block for this, which would also be block instance specific. We'd love your input as we work out other use-cases to understand server-side ways to accomplish our needs, but right now it unlocks a lot of powerful per-instance customization.

Copy link
Member

@oandregal oandregal left a comment

Choose a reason for hiding this comment

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

I've pushed a modification for the filter to be the first step, and nothing else to be executed if a match is found. Thanks for your patience and contribution!

@ingeniumed
Copy link
Contributor Author

Thanks for all your feedback and help, it's much appreciated by @alecgeatches and I!

Copy link
Contributor

@aaronrobertshaw aaronrobertshaw left a comment

Choose a reason for hiding this comment

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

Thanks for all the iteration on this one @ingeniumed & @alecgeatches 👍

Given the approach of adding the before filter to useSetting has already been accepted on the original issue and via @oandregal's review, I think this PR is very close to landing.

✅ Tests for useSetting pass
✅ No issues spotted in the code changes or when testing in the editor

Before we merge this PR, it would be great if you could update the PR description first so that it matches the reduced scope of changes.

packages/block-editor/src/components/use-setting/index.js Outdated Show resolved Hide resolved
@ingeniumed
Copy link
Contributor Author

Thanks a lot for the feedback, and for pointing that out. That should indeed have been updated when the scope was reduced. I have updated the PR description to reflect this, lemme know if you think it needs to be changed further!

@aaronrobertshaw aaronrobertshaw merged commit 1c0d02f into WordPress:trunk Dec 6, 2022
@github-actions
Copy link

github-actions bot commented Dec 6, 2022

Congratulations on your first merged pull request, @ingeniumed! We'd like to credit you for your contribution in the post announcing the next WordPress release, but we can't find a WordPress.org profile associated with your GitHub account. When you have a moment, visit the following URL and click "link your GitHub account" under "GitHub Username" to link your accounts:

https://profiles.wordpress.org/me/profile/edit/

And if you don't have a WordPress.org account, you can create one on this page:

https://login.wordpress.org/register

Kudos!

@github-actions github-actions bot added this to the Gutenberg 14.8 milestone Dec 6, 2022
@ingeniumed ingeniumed deleted the add/nested-block-using-filters branch December 6, 2022 22:09
@ingeniumed ingeniumed changed the title Expose before filter hook in useSettings and the block metadata for CSS classes generation Expose before filter hook in useSettings for injecting block settings in the editor Dec 6, 2022
mpkelly pushed a commit to mpkelly/gutenberg that referenced this pull request Dec 7, 2022
@bph bph added the Needs Dev Note Requires a developer note for a major WordPress release cycle label Dec 12, 2022
@bph bph mentioned this pull request Feb 7, 2023
47 tasks
@adamziel
Copy link
Contributor

adamziel commented Feb 24, 2023

I drafted a dev note for this one. @oandregal @ingeniumed @aaronrobertshaw would you please review it?


Dev Note: Customize Settings For Any Block in WordPress 6.2

WordPress 6.2 introduces a new client-side filter that allows developers to modify block settings before the editor is rendered.

The filter is called blockEditor.useSetting.before and can be used in the JavaScript code as follows:

import { addFilter, removeFilter } from '@wordpress/hooks';

/**
 * Restrict the spacing units that can be
 * selected in the column block to pixels:
 */
addFilter(
	'blockEditor.useSetting.before',
	'myPlugin/useSetting.before',
	( settingValue, settingName, clientId, blockName ) => {
		if ( blockName === 'core/column' && settingName === 'spacing.units' ) {
			return [ 'px' ];
		}
		return settingValue;
	}
);

With this filter, developers have better control over what block settings are offered to the user, providing greater control over the editing experience in the Gutenberg editor.

@adamziel adamziel added has dev note when dev note is done (for upcoming WordPress release) and removed Needs Dev Note Requires a developer note for a major WordPress release cycle labels Feb 24, 2023
@alecgeatches
Copy link
Contributor

@adamziel This looks great to me! I also added a slightly more complex example to this discussion which provides behavior not possible with just theme.json if that's desired. Thank you for writing this up!

@ndiego
Copy link
Member

ndiego commented Feb 27, 2023

@adamziel @alecgeatches I expanded on the draft above with an additional example to show how to modify settings based on a block's location (thanks for the code @alecgeatches). I just wanted to make sure the dev note captures how powerful this filter can be. I am also planning some additional content on the subject. Let me know what you think. Thanks!


Dev Note: Customize Settings For Any Block in WordPress 6.2

WordPress 6.2 introduces a new client-side filter that allows developers to modify block settings before the editor is rendered.

The filter is called blockEditor.useSetting.before and can be used in the JavaScript code as follows:

import { addFilter } from '@wordpress/hooks';

/**
 * Restrict the spacing units that can be
 * selected in the Column block to pixels:
 */
addFilter(
	'blockEditor.useSetting.before',
	'myPlugin/useSetting.before',
	( settingValue, settingName, clientId, blockName ) => {
		if ( blockName === 'core/column' && settingName === 'spacing.units' ) {
			return [ 'px' ];
		}
		return settingValue;
	}
);

This example will restrict the available spacing units for the Column block to just pixels. A similar restriction could be applied using theme.json filters or directly in a theme's theme.json file using block-level settings.

That said, the blockEditor.useSetting.before filter is unique because it also allows developers to modify settings according to the block's location, neighboring blocks, the current user's role, and more. The possibilities for customization are extensive.

In the following example, text color controls are disabled for the Heading block whenever the block is placed inside of a Media & Text block.

import { addFilter } from '@wordpress/hooks';
import { getBlockName, getBlockParents } from  '@wordpress/block-editor';

/**
 * Disable text color controls on Heading blocks
 * when placed inside of Media & Text blocks.
 */
addFilter(
	'blockEditor.useSetting.before',
	'myPlugin/useSetting.before',
	( settingValue, settingName, clientId, blockName ) => {
		if ( blockName === 'core/heading' ) {
			const blockParents = getBlockParents( clientId, true );
			const inMediaText = blockParents.some( ( ancestorId ) => getBlockName( ancestorId ) === 'core/media-text' );

			if ( inMediaText && settingName === 'color.text' ) {
       				return false;
     			}
		}

		return settingValue;
	}
);

The addition of this filter provides developers with better control over what block settings are presented to the user, enabling them to curate the editor experience like never before.

@bph
Copy link
Contributor

bph commented Feb 27, 2023

Dev Note needs 1st review Thanks @ndiego for posting the draft.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json has dev note when dev note is done (for upcoming WordPress release)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants