Show yoast in elements tab in elementor#22697
Conversation
Pull Request Test Coverage Report for Build f4eb7abaa7b8ccd4b1aa81addbe1c84e83f3b585Warning: This coverage report may be inaccurate.This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.
Details
💛 - Coveralls |
…Yoast/wordpress-seo into show-yoast-in-elements-tab-in-elementor
…Yoast/wordpress-seo into show-yoast-in-elements-tab-in-elementor
…Yoast/wordpress-seo into show-yoast-in-elements-tab-in-elementor
…t-in-elements-tab-in-elementor
…Yoast/wordpress-seo into show-yoast-in-elements-tab-in-elementor
There was a problem hiding this comment.
Pull Request Overview
This PR enhances the discoverability of Yoast SEO's Elementor integration by adding the Yoast SEO tab to the Elements panel sidebar, in addition to the existing Post Settings location. The introduction notification has also been relocated to point to this new tab location.
Key Changes:
- Added Yoast SEO tab to Elementor's Elements panel navigation alongside Widgets and Globals tabs
- Updated introduction notification to target the new Elements panel tab location instead of Post Settings
- Introduced DOM manipulation to inject the Yoast tab button and manage panel content display
Reviewed Changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/integrations/third-party/elementor.php | Adds output buffering hooks to inject Yoast SEO tab button via regex replacement |
| packages/js/src/elementor/initializers/render-sidebar.js | Extends React root to support portal rendering in both tab and panel locations |
| packages/js/src/elementor/initializers/panel.js | Implements panel initialization logic, tab registration, and content display management |
| packages/js/src/elementor/initializers/introduction-editor-v2.js | Refactors introduction notification to target new Elements panel tab with improved positioning |
| packages/js/src/elementor/initialize.js | Integrates panel initialization into main initialization flow |
| packages/js/src/elementor/components/YoastPanelView.js | Defines Marionette view for Yoast panel content rendering |
| css/src/elementor.css | Adds styling for panel content container and icon display |
| config/webpack/webpack.config.base.js | Configures Marionette as external dependency mapped to Elementor's global |
| admin/class-admin-asset-manager.php | Extracts Elementor dependencies into reusable method including Marionette |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } ); | ||
|
|
||
| // Auto-dismiss when switching to preview mode, and the Elements panel is hidden. | ||
| window.elementor.channels.dataEditMode.on( "switch", function( activeMode ) { |
There was a problem hiding this comment.
[nitpick] Inconsistent arrow function usage: This callback uses a traditional function while other callbacks in the same file use arrow functions (e.g., line 60). Consider using an arrow function for consistency unless this binding is specifically needed.
| window.elementor.channels.dataEditMode.on( "switch", function( activeMode ) { | |
| window.elementor.channels.dataEditMode.on( "switch", ( activeMode ) => { |
| export const YoastPanelView = Marionette.ItemView.extend( { | ||
| template: false, | ||
| id: "yoast-elementor-react-panel", | ||
| className: "yoast yoast-elementor-panel__fills", | ||
| initialize() { | ||
| jQuery( "#elementor-panel-elements-search-area" ).hide(); | ||
| }, | ||
| onShow() { | ||
| showYoastPanelAnalysis(); | ||
| }, | ||
| onDestroy() { | ||
| jQuery( "#elementor-panel-elements-search-area" ).show(); |
There was a problem hiding this comment.
Duplicated jQuery selectors: The selector #elementor-panel-elements-search-area is used in both initialize() and onDestroy(). Consider storing it as a constant at the module level (similar to other constants in panel.js) to avoid duplication and improve maintainability.
| export const YoastPanelView = Marionette.ItemView.extend( { | |
| template: false, | |
| id: "yoast-elementor-react-panel", | |
| className: "yoast yoast-elementor-panel__fills", | |
| initialize() { | |
| jQuery( "#elementor-panel-elements-search-area" ).hide(); | |
| }, | |
| onShow() { | |
| showYoastPanelAnalysis(); | |
| }, | |
| onDestroy() { | |
| jQuery( "#elementor-panel-elements-search-area" ).show(); | |
| const ELEMENTS_SEARCH_AREA_SELECTOR = "#elementor-panel-elements-search-area"; | |
| export const YoastPanelView = Marionette.ItemView.extend( { | |
| template: false, | |
| id: "yoast-elementor-react-panel", | |
| className: "yoast yoast-elementor-panel__fills", | |
| initialize() { | |
| jQuery( ELEMENTS_SEARCH_AREA_SELECTOR ).hide(); | |
| }, | |
| onShow() { | |
| showYoastPanelAnalysis(); | |
| }, | |
| onDestroy() { | |
| jQuery( ELEMENTS_SEARCH_AREA_SELECTOR ).show(); |
| * @return void | ||
| */ | ||
| public function inject_yoast_tab() { | ||
| $output = \ob_get_clean(); |
There was a problem hiding this comment.
Complex regex pattern is fragile and hard to maintain. The pattern relies on specific HTML structure and class ordering which could break if Elementor changes their markup. Consider adding a comment explaining why regex is necessary here instead of a more robust DOM manipulation approach, or document the Elementor version this pattern is tested against.
| $output = \ob_get_clean(); | |
| $output = \ob_get_clean(); | |
| /** | |
| * NOTE: We use a regex here to inject the Yoast SEO tab into the Elementor panel. | |
| * This pattern relies on the specific HTML structure and class ordering output by Elementor. | |
| * Using a DOM parser in PHP is not practical in this context due to performance and complexity. | |
| * If Elementor changes their markup, this pattern may break and will need to be updated. | |
| * Tested against Elementor version 3.13.0. | |
| */ |
| contentContainer.className = YOAST_PANEL_CONTENT_CLASS; | ||
|
|
||
| // Insert it after the navigation. | ||
| elementsNavigation.parentNode.insertBefore( contentContainer, elementsNavigation.nextSibling ); |
There was a problem hiding this comment.
Missing null check for parentNode: While elementsNavigation is checked for existence, parentNode could theoretically be null. Consider adding a null check for elementsNavigation.parentNode before calling insertBefore().
| elementsNavigation.parentNode.insertBefore( contentContainer, elementsNavigation.nextSibling ); | |
| if ( elementsNavigation.parentNode ) { | |
| elementsNavigation.parentNode.insertBefore( contentContainer, elementsNavigation.nextSibling ); | |
| } else { | |
| // If parentNode is null, do not attempt to insert. Optionally, log or handle this case. | |
| return; | |
| } |
There was a problem hiding this comment.
Unnecessary, we already verify that elementsNavigation element exists in the DOM in line 27.
| flex-direction: column; | ||
| } | ||
|
|
||
|
|
There was a problem hiding this comment.
[nitpick] Extra blank line should be removed for consistency with the rest of the stylesheet.
|
AT ✅ CR ✅ |
Context
Post Settingsmenu in Elementor, which made the feature not very visible for the users. We want to also show the Yoast SEO tab in the Elements side bar for better discoverability.Summary
This PR can be summarized in the following changelog entry:
Relevant technical choices:
Test instructions
Test instructions for the acceptance test before the PR gets merged
This PR can be acceptance tested by following these steps:
The Yoast SEO tab should be rendered under Elements panel
Screenshot
Yoast SEOtabScreenshot
Switching between tabs in Elements panel
Yoast SEOtab in Elements panelYoast SEObutton tab is active and the other buttons (Widgets and Globals) are not activeelementor-activeclassTest the introduction notification
Clicking on "Got it" button should dismiss the notification
elementor_introductionvalue in yourwp_usermetadatabaseClicking on Yoast SEO tab should dismiss the notification
elementor_introductionvalue in yourwp_usermetadatabaseCollapsing/Hiding the Elements panel in the editor should dismiss the notification
elementor_introductionvalue in yourwp_usermetadatabaseToggle
The notification should be dismissed when other panel is clicked
elementor_introductionvalue in yourwp_usermetadatabaseThe notification should not be shown anymore once it's dismissed
elementor_introductionvalue in yourwp_usermetadatabaseTest in RTL language
Relevant test scenarios
Test instructions for QA when the code is in the RC
QA can test this PR by following these steps:
Impact check
This PR affects the following parts of the plugin, which may require extra testing:
Other environments
[shopify-seo], added test instructions for Shopify and attached theShopifylabel to this PR.Documentation
Quality assurance
Innovation
innovationlabel.Fixes https://github.com/Yoast/reserved-tasks/issues/814