Skip to content

Add new HTMLElementControl component #69904

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

Merged

Conversation

Sukhendu2002
Copy link
Contributor

@Sukhendu2002 Sukhendu2002 commented Apr 15, 2025

What?

Closes: #69890

This PR introduces a new HTMLElementSelectControl component that replaces standard HTML element selection dropdowns across core blocks. The component includes built-in validation to prevent duplicate <main> elements within a document, improving accessibility and HTML standards compliance.

Testing Instructions

  1. Add or edit any of the supported blocks in the editor.
  2. Use the HTML element selection control in block settings.
  3. Attempt to assign the element to multiple blocks and verify that validation and warnings work as expected.

Screenshots or screencast

Screen.Recording.2025-04-15.at.3.48.45.PM.mov

@Mamaduka Mamaduka added [Type] Enhancement A suggestion for improvement. [Focus] Accessibility (a11y) Changes that impact accessibility and need corresponding review (e.g. markup changes). Needs Design Feedback Needs general design feedback. [Package] Block library /packages/block-library labels Apr 15, 2025
Copy link
Member

@Mamaduka Mamaduka left a comment

Choose a reason for hiding this comment

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

Nice work, @Sukhendu2002!

I left some initial feedback, but the implementation looks promising.

The blocks should also be able to opt out from main tag warning checks. Why?

  • Not every block provides an option to select the main tag. Examples: Comments and Spacer blocks.
  • The calculation inside the useSelect would be wasteful for these blocks.

@Sukhendu2002
Copy link
Contributor Author

Hi @Mamaduka, Thanks for the feedback! I’ve implemented all the updates — looking forward to your thoughts on the latest changes. Let me know if there’s anything else you'd like me to adjust!

@Sukhendu2002 Sukhendu2002 requested a review from Mamaduka April 16, 2025 07:16
@Sukhendu2002 Sukhendu2002 requested a review from Mamaduka April 16, 2025 10:09
@Mamaduka
Copy link
Member

@Sukhendu2002, please don't forget to mark PR as "Ready for review". Otherwise contributors might mistake it as "In Progress" work.

@Sukhendu2002 Sukhendu2002 marked this pull request as ready for review April 16, 2025 10:10
Copy link

github-actions bot commented Apr 16, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: Sukhendu2002 <sukhendu2002@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>
Co-authored-by: t-hamano <wildworks@git.wordpress.org>
Co-authored-by: skorasaurus <skorasaurus@git.wordpress.org>
Co-authored-by: carolinan <poena@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link
Member

@Mamaduka Mamaduka left a comment

Choose a reason for hiding this comment

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

Again, nice work @Sukhendu2002!

I haven't intensively tested this idea, but I think our useSelect here can be simplified further. Technically speaking, we only need to know one value - hasMainElementElsewhere and anything else can be derived.

Additionally, we could use Array.some instead of Array.filter, which should be slightly more performant when working with large datasets.

Here's what I'm thinking:

const hasMainElementElsewhere = useSelect(
	( select ) => {
		if ( ! checkForMainTag ) {
			return false;
		}

		const { getClientIdsWithDescendants, getBlockAttributes } =
			select( blockEditorStore );

		return getClientIdsWithDescendants().some( ( id ) => {
			// Skip the current block.
			if ( id === clientId ) {
				return false;
			}

			return getBlockAttributes( id )?.tagName === 'main';
		} );
	},
	[ clientId, checkForMainTag ]
);

cc @carolinan, @luminuu

@Sukhendu2002 Sukhendu2002 requested a review from Mamaduka April 18, 2025 11:49
@Mamaduka
Copy link
Member

Thanks for addressing the feedback, @Sukhendu2002!

It seems that failing mobile unit tests is caused by this change. Did you have time to investigate the problem?

@Mamaduka Mamaduka changed the title Add new HTMLElementSelectControl component Add new HTMLElementControl component Apr 22, 2025
@Sukhendu2002
Copy link
Contributor Author

Hi @Mamaduka, I'm not entirely sure, but it looks like HTMLElementControl might not be defined properly in the React Native context. Do you think we should:

  • Add a platform check like !Platform.isNative && <HTMLElementControl /> to avoid rendering it in native?
  • Create a separate edit.native.js implementation file?

What's your thoughts on this?

@Mamaduka
Copy link
Member

@Sukhendu2002, I think the new private component should also be listed in packages/block-editor/src/private-apis.native.js. I've not tested this, but I've seen similar resolutions in the past - #59632.

Copy link
Member

@Mamaduka Mamaduka left a comment

Choose a reason for hiding this comment

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

Thank you, @Sukhendu2002!

Everything works as expected ✅

@carolinan, @luminuu, @t-hamano, do you have any notes before merging this enhancement?

@Sukhendu2002 Sukhendu2002 requested a review from t-hamano April 24, 2025 10:00
@Mamaduka
Copy link
Member

All the feedback appears to have been addressed. I'm going to merge this.

@Mamaduka Mamaduka merged commit 01a1f97 into WordPress:trunk Apr 25, 2025
60 checks passed
@github-actions github-actions bot added this to the Gutenberg 20.8 milestone Apr 25, 2025
@luminuu
Copy link
Member

luminuu commented Apr 25, 2025

@Mamaduka Sorry for the late feedback here. I think it's overall a good implementation, there's just two things I've come across I'd like to mention:

The first one is probably a smaller one as it's a design issue, there's not enough space after the warning if there's a following element, same goes if there's no warning and just the select, there's also no space:
CleanShot 2025-04-25 at 14 57 40@2x

The second thing is, and I'm not sure if there's a solution for this: When I have a template, where the Content block is already in a Group with the HTML Tag set to main (like the Default Themes) and I have a block within my content that is set to main as well, the warning message does not show up when Show template is deactivated. I assume this is to what the check is iterating over. It also gets more confusing when the template is shown, because the surrounding group block around the content is not shown in the list view, despite it's there. I've made a ticket for this separate issue already: #67621

One suggestion for making it at least clearer to the user is to communicate that the template may contain the main tag as well. Otherwise people might look for it and are not able to find it, despite the warning is correct. I know this will bloat the warning message but I'm not sure if any other solution would bring more of an advantage.

@Mamaduka
Copy link
Member

When I have a template, where the Content block is already in a Group with the HTML Tag set to main (like the Default Themes) and I have a block within my content that is set to main as well, the warning message does not show up when Show template is deactivated.

Unfortunately, this would be hard to resolve. The editor only has details for the blocks that are rendered on the canvas. When "Show template" is deactivated, we can only check the post content blocks.

Maybe this is something we can improve by clear messaging.

@t-hamano
Copy link
Contributor

there's not enough space after the warning if there's a following element, same goes if there's no warning and just the select, there's also no space:

I think this is because the HTMLElementControl component is not based on BaseControl. I think the following CSS is required:

diff --git a/packages/block-editor/src/components/block-inspector/style.scss b/packages/block-editor/src/components/block-inspector/style.scss
index dd9d8f254f..4913b4c5f8 100644
--- a/packages/block-editor/src/components/block-inspector/style.scss
+++ b/packages/block-editor/src/components/block-inspector/style.scss
@@ -11,7 +11,8 @@
        }
 
        .components-base-control,
-       .components-radio-control {
+       .components-radio-control,
+       .block-editor-html-element-control {
                &:where(:not(:last-child)) {
                        margin-bottom: $grid-unit-20;
                }
@@ -20,7 +21,8 @@
        // Reset unwanted margin-bottom from being applied to BaseControls within certain components.
        .components-focal-point-picker-control,
        .components-query-controls,
-       .components-range-control {
+       .components-range-control,
+       .block-editor-html-element-control {
                .components-base-control {
                        margin-bottom: 0;
                }
diff --git a/packages/block-editor/src/components/html-element-control/index.js b/packages/block-editor/src/components/html-element-control/index.js
index 3024301f19..a3dc68f7ee 100644
--- a/packages/block-editor/src/components/html-element-control/index.js
+++ b/packages/block-editor/src/components/html-element-control/index.js
@@ -86,7 +86,7 @@ export default function HTMLElementControl( {
        } );
 
        return (
-               <VStack spacing={ 2 }>
+               <VStack spacing={ 2 } className="block-editor-html-element-control">
Before After
image image
image image

See #49520 (comment) for why such an approach is necessary.

@Sukhendu2002
Copy link
Contributor Author

Thanks @t-hamano — that makes a lot of sense. I'll start working on the fix!

chriszarate pushed a commit to chriszarate/gutenberg that referenced this pull request Jul 1, 2025
Co-authored-by: Sukhendu2002 <sukhendu2002@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>
Co-authored-by: t-hamano <wildworks@git.wordpress.org>
Co-authored-by: skorasaurus <skorasaurus@git.wordpress.org>
Co-authored-by: carolinan <poena@git.wordpress.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Focus] Accessibility (a11y) Changes that impact accessibility and need corresponding review (e.g. markup changes). Needs Design Feedback Needs general design feedback. [Package] Block library /packages/block-library [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Prevent duplicate main HTML elements when using the HTML Element option
4 participants