-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Warn if a template does not have one main element #68656
base: trunk
Are you sure you want to change the base?
Conversation
Adds a new component that checks if a template has exactly one main HTML element, and creates a warning notice if the main HTML element is used incorrectly.
This is only one possible approach. Another alternative would be to display the warning in the document outline when editing a template. Copying this from the issue:
|
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 If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
<EditorNotices /> | ||
<> | ||
<EditorNotices /> | ||
<MainElementWarnings /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was not sure about this and would welcome suggestions for better places to trigger the check from.
Size Change: +193 B (+0.01%) Total Size: 1.84 MB
ℹ️ View Unchanged
|
I personally would vote for the Document Outline approach. Here's why:
|
@@ -21,6 +21,7 @@ export { default as EntitiesSavedStates } from './entities-saved-states'; | |||
export { useIsDirty as useEntitiesSavedStatesIsDirty } from './entities-saved-states/hooks/use-is-dirty'; | |||
export { default as ErrorBoundary } from './error-boundary'; | |||
export { default as LocalAutosaveMonitor } from './local-autosave-monitor'; | |||
export { default as MainElementWarnings } from './main-element-warnings'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to make this component a public API? Probably better to have it for internal use only for now.
I agree it is prominent but the impact of not having the main is severe so I am not sure what the best balance is. In addition it is not a good user experience that the notice is showing on blank templates, that the user has not started adding blocks to yet. |
const checkMainTag = ( blocks, mainTagCount ) => { | ||
blocks.forEach( ( block ) => { | ||
if ( block.attributes.tagName === 'main' ) { | ||
mainTagCount++; | ||
} | ||
// If the block has innerBlocks, call the function again. | ||
if ( block.innerBlocks.length > 0 ) { | ||
mainTagCount = checkMainTag( block.innerBlocks, mainTagCount ); | ||
} | ||
} ); | ||
|
||
return mainTagCount; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the direction here. I think we could optimize this by switching to the for...of
loop and bailing out when count > 1
.
If I remember correctly, Array.forEach
doesn't allow the iteration execution to stop.
Here's what I've in mind:
// Returns 0, 1 or 2. 0 and 2 are in violation. 1 is correct.
function checkMainTagCount( blocks = [], count = 0 ) {
for ( const block of blocks ) {
if ( block.attributes.tagName === 'main' ) {
count++;
}
// Look no further; we've found a violation.
if ( count > 1 ) {
break;
}
// Check nested blocks.
if ( block.innerBlocks.length > 0 ) {
count = checkMainTagCount( block.innerBlocks, count );
}
}
return count;
}
const { getBlocks } = select( blockEditorStore ); | ||
return { | ||
type: postType, | ||
blocks: getBlocks(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could move the post type check here and only return the blocks
value when editing a template. This will avoid unnecessary tracking for other post types.
I know it's important, but how much bigger is the impact compared to headling level violations
I agree this could get annoying. There's also no way to know when the user finished adding layout blocks. |
Thank you for the reviews. I am changing this to draft while I am working on an alternative using the document outline. |
What?
Adds a new component that checks if a template has exactly one main HTML element, and creates a dismissible warning notice if the main HTML element is used incorrectly.
Closes #35354
Why?
Having a single
<main>
element in a template is important for accessibility, but also for the Zoom Out feature.The skip link feature is only enabled on templates that has a
<main>
element.See the issue for more details.
Testing Instructions
Activate a block theme
Go to Appearance > Editor and open any template.
If there is no warning message at the top of the editor, then the template has a
<main>
element.Locate the block with the
<main>
element: This is usually a group, but any block with thetagName
attribute could be using it.Duplicate the block with the
<main>
element and confirm if there is a warning at the top of the editor.Confirm that the warning can be dismissed.
Delete all blocks with a
<main>
element and confirm if there is a warning at the top of the editor.Screenshots or screencast