From 702a846ee8a58f703ca75fda8f7253e648a22a38 Mon Sep 17 00:00:00 2001 From: Netanel Baba Date: Sun, 16 Aug 2026 13:50:11 +0300 Subject: [PATCH 1/6] Internal: Add Upgrade to Pro button in Hello Theme top bar [TMZ-1067] The Hello Theme Home screen and its Upgrade to Pro banner were removed, leaving no upgrade CTA in the admin. Add one to the settings top bar, reusing the go.elementor.com/hello-upgrade-epro link the banner used. The upgrade URL is only localized when Elementor Pro is inactive, so the Pro check stays in PHP and the button renders from the config alone. Wrap the top bar root in the Elementor UI ThemeProvider, matching the settings and conversion banner entries. Without it the tree falls back to the default MUI theme, which has no promotion palette entry. Ref: TMZ-1067 Co-authored-by: Cursor --- .../js/components/top-bar/top-bar-content.js | 2 ++ .../js/components/top-bar/upgrade-button.js | 24 +++++++++++++++++++ .../assets/js/hello-elementor-topbar.js | 7 +++++- .../admin-home/components/admin-top-bar.php | 13 ++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 modules/admin-home/assets/js/components/top-bar/upgrade-button.js diff --git a/modules/admin-home/assets/js/components/top-bar/top-bar-content.js b/modules/admin-home/assets/js/components/top-bar/top-bar-content.js index 02ca8698..dd07af4c 100644 --- a/modules/admin-home/assets/js/components/top-bar/top-bar-content.js +++ b/modules/admin-home/assets/js/components/top-bar/top-bar-content.js @@ -1,6 +1,7 @@ import Stack from '@elementor/ui/Stack'; import DynamicIcon from '../dynamic-icon'; import Typography from '@elementor/ui/Typography'; +import { UpgradeButton } from './upgrade-button'; import { __ } from '@wordpress/i18n'; export const TopBarContent = ({ sx = {}, iconSize = 'medium' }) => { @@ -23,6 +24,7 @@ export const TopBarContent = ({ sx = {}, iconSize = 'medium' }) => { {__('Hello', 'hello-elementor')} + ); }; diff --git a/modules/admin-home/assets/js/components/top-bar/upgrade-button.js b/modules/admin-home/assets/js/components/top-bar/upgrade-button.js new file mode 100644 index 00000000..0faecacf --- /dev/null +++ b/modules/admin-home/assets/js/components/top-bar/upgrade-button.js @@ -0,0 +1,24 @@ +import Button from '@elementor/ui/Button'; +import CrownIcon from '@elementor/icons/CrownIcon'; +import { __ } from '@wordpress/i18n'; + +export const UpgradeButton = () => { + const upgradeUrl = window.ehpTopBarConfig?.upgradeUrl; + + if (!upgradeUrl) { + return null; + } + + return ( + + ); +}; diff --git a/modules/admin-home/assets/js/hello-elementor-topbar.js b/modules/admin-home/assets/js/hello-elementor-topbar.js index bd6db8b4..c787f4fc 100644 --- a/modules/admin-home/assets/js/hello-elementor-topbar.js +++ b/modules/admin-home/assets/js/hello-elementor-topbar.js @@ -1,8 +1,13 @@ import { createRoot } from 'react-dom/client'; +import { ThemeProvider } from '@elementor/ui/styles'; import { TopBar } from './components/top-bar/top-bar'; const App = () => { - return ; + return ( + + + + ); }; document.addEventListener('DOMContentLoaded', () => { diff --git a/modules/admin-home/components/admin-top-bar.php b/modules/admin-home/components/admin-top-bar.php index 7e6e7ddf..7b855505 100644 --- a/modules/admin-home/components/admin-top-bar.php +++ b/modules/admin-home/components/admin-top-bar.php @@ -11,6 +11,9 @@ class Admin_Top_Bar { + const CONFIG_OBJECT_NAME = 'ehpTopBarConfig'; + const UPGRADE_PRO_URL = 'https://go.elementor.com/hello-upgrade-epro/'; + private function render_admin_top_bar() { ?>
@@ -30,6 +33,16 @@ private function enqueue_scripts() { ); $script->enqueue(); + + if ( Utils::has_pro() ) { + return; + } + + wp_localize_script( + 'hello-elementor-topbar', + self::CONFIG_OBJECT_NAME, + [ 'upgradeUrl' => self::UPGRADE_PRO_URL ] + ); } public function __construct() { From b754ad9eb99326ec59dc8bbe2a2a8847a0b10af6 Mon Sep 17 00:00:00 2001 From: Netanel Baba Date: Sun, 16 Aug 2026 16:02:15 +0300 Subject: [PATCH 2/6] Internal: Hide the Settings submenu from the Hello menu [TMZ-1067] The Hello menu item already redirects to the settings page, so the Settings submenu entry was the only item in the flyout and duplicated that destination. Hide it with remove_submenu_page, which only unsets the display entry and leaves the page registered. The settings URL keeps working for existing links, the Finder entry, and the screen ID that gates the settings script enqueue. Ref: TMZ-1067 Co-authored-by: Cursor --- modules/admin-home/components/settings-controller.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/admin-home/components/settings-controller.php b/modules/admin-home/components/settings-controller.php index aa7b524b..cc30d110 100644 --- a/modules/admin-home/components/settings-controller.php +++ b/modules/admin-home/components/settings-controller.php @@ -142,6 +142,10 @@ public function register_settings_page( $parent_slug ): void { self::SETTINGS_PAGE_SLUG, [ $this, 'render_settings_page' ] ); + + // The Hello menu item already redirects here, so the entry is hidden while the page + // stays registered to keep the existing settings URL working. + remove_submenu_page( $parent_slug, self::SETTINGS_PAGE_SLUG ); } public function render_settings_page(): void { From 7797608eadc981c689b5985e5dfad1b013154bed Mon Sep 17 00:00:00 2001 From: Netanel Baba Date: Sun, 16 Aug 2026 16:04:31 +0300 Subject: [PATCH 3/6] No hover effect --- .../admin-home/assets/js/components/top-bar/upgrade-button.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/admin-home/assets/js/components/top-bar/upgrade-button.js b/modules/admin-home/assets/js/components/top-bar/upgrade-button.js index 0faecacf..3a3c39aa 100644 --- a/modules/admin-home/assets/js/components/top-bar/upgrade-button.js +++ b/modules/admin-home/assets/js/components/top-bar/upgrade-button.js @@ -17,6 +17,7 @@ export const UpgradeButton = () => { color="promotion" size="small" startIcon={} + sx={{ '&:hover': { backgroundColor: 'transparent' } }} > {__('Upgrade Now', 'hello-elementor')} From c4e55dd7f3b7ac3a6affd19bf1f70da6d86bf85c Mon Sep 17 00:00:00 2001 From: Netanel Baba Date: Sun, 16 Aug 2026 16:06:34 +0300 Subject: [PATCH 4/6] Internal: Fix settings page 403 when hiding the Settings submenu [TMZ-1067] Removing the submenu entry during admin_menu made the settings page return "Sorry, you are not allowed to access this page". WordPress resolves a plugin page's hook through get_admin_page_parent, which finds the parent by scanning the submenu globals. admin.php builds the menu before it resolves the hook, so the entry was already gone and the lookup failed. Move the removal to admin_head, which runs after the hook is resolved and before menu-header.php renders the sidebar. Ref: TMZ-1067 Co-authored-by: Cursor --- .../components/settings-controller.php | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/modules/admin-home/components/settings-controller.php b/modules/admin-home/components/settings-controller.php index cc30d110..e9e90d08 100644 --- a/modules/admin-home/components/settings-controller.php +++ b/modules/admin-home/components/settings-controller.php @@ -22,6 +22,8 @@ class Settings_Controller { 'HELLO_THEME' => '_hello_theme', ]; + private string $parent_slug = ''; + public static function get_settings_mapping(): array { return array_map( function ( $key ) { @@ -134,6 +136,8 @@ public function enqueue_hello_plus_settings_scripts() { } public function register_settings_page( $parent_slug ): void { + $this->parent_slug = $parent_slug; + add_submenu_page( $parent_slug, __( 'Settings', 'hello-elementor' ), @@ -142,10 +146,17 @@ public function register_settings_page( $parent_slug ): void { self::SETTINGS_PAGE_SLUG, [ $this, 'render_settings_page' ] ); + } - // The Hello menu item already redirects here, so the entry is hidden while the page - // stays registered to keep the existing settings URL working. - remove_submenu_page( $parent_slug, self::SETTINGS_PAGE_SLUG ); + /** + * The Hello menu item redirects to this page, so its submenu entry is redundant. + * + * Removing it during `admin_menu` would also make the page unreachable, because + * WordPress resolves a plugin page's hook by looking the slug up in the submenu + * globals. `admin_head` runs after that lookup and before the menu is rendered. + */ + public function hide_settings_submenu_item(): void { + remove_submenu_page( $this->parent_slug, self::SETTINGS_PAGE_SLUG ); } public function render_settings_page(): void { @@ -154,6 +165,7 @@ public function render_settings_page(): void { public function __construct() { add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_hello_plus_settings_scripts' ] ); + add_action( 'admin_head', [ $this, 'hide_settings_submenu_item' ] ); add_action( 'hello-plus-theme/admin-menu', [ $this, 'register_settings_page' ], 10, 1 ); } } From 3819a0434b6e5be04367491adc6261dc0d02cc3b Mon Sep 17 00:00:00 2001 From: Netanel Baba Date: Sun, 16 Aug 2026 16:57:32 +0300 Subject: [PATCH 5/6] Fix test --- tests/playwright/tests/theme-settings.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/playwright/tests/theme-settings.test.ts b/tests/playwright/tests/theme-settings.test.ts index 09211f62..52d73f21 100644 --- a/tests/playwright/tests/theme-settings.test.ts +++ b/tests/playwright/tests/theme-settings.test.ts @@ -25,7 +25,7 @@ test.describe('Admin Menu', () => { await expect(page).toHaveURL(/page=hello-elementor-settings/); }); - test('does not show Home submenu', async ({ + test('does not show submenu items', async ({ page, apiRequests, }, testInfo) => { @@ -36,8 +36,6 @@ test.describe('Admin Menu', () => { const helloMenu = page.locator('#toplevel_page_hello-elementor'); await helloMenu.hover(); - await expect( - page.locator('#toplevel_page_hello-elementor .wp-submenu'), - ).not.toContainText('Home'); + await expect(helloMenu.locator('.wp-submenu li')).toHaveCount(0); }); }); From 1422b91378bea0404dbad74338a0c5ab4ca77784 Mon Sep 17 00:00:00 2001 From: Netanel Baba Date: Sun, 16 Aug 2026 17:33:43 +0300 Subject: [PATCH 6/6] Simplify hide_settings_submenu_item comment Co-authored-by: Cursor --- modules/admin-home/components/settings-controller.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/modules/admin-home/components/settings-controller.php b/modules/admin-home/components/settings-controller.php index e9e90d08..a62f925f 100644 --- a/modules/admin-home/components/settings-controller.php +++ b/modules/admin-home/components/settings-controller.php @@ -148,13 +148,7 @@ public function register_settings_page( $parent_slug ): void { ); } - /** - * The Hello menu item redirects to this page, so its submenu entry is redundant. - * - * Removing it during `admin_menu` would also make the page unreachable, because - * WordPress resolves a plugin page's hook by looking the slug up in the submenu - * globals. `admin_head` runs after that lookup and before the menu is rendered. - */ + // Runs on `admin_head`, not `admin_menu`: removing the submenu earlier breaks the page hook resolution and makes the page unreachable. public function hide_settings_submenu_item(): void { remove_submenu_page( $this->parent_slug, self::SETTINGS_PAGE_SLUG ); }