Skip to content

chore(global-header): Global header optimization - #4006

Open
debsmita1 wants to merge 2 commits into
redhat-developer:mainfrom
debsmita1:global-header-optimization
Open

chore(global-header): Global header optimization#4006
debsmita1 wants to merge 2 commits into
redhat-developer:mainfrom
debsmita1:global-header-optimization

Conversation

@debsmita1

@debsmita1 debsmita1 commented Jul 27, 2026

Copy link
Copy Markdown
Member

Hey, I just made a Pull Request!

Resolves:
https://redhat.atlassian.net/browse/RHIDP-15555

Solution description:

  • Cut NFS ./alpha Module Federation sync from ~972 KB → ~116 KB (~88%) by aligning with Backstage NFS patterns: thin alpha registration, heavy UI behind loaders/import().
  • Default toolbar/menu extensions now use blueprint loaders; dropdowns use HeaderIcon ligatures instead of static @mui/icons-material on the sync path.
  • Building blocks (GlobalHeaderIconButton / MenuItem / Dropdown) moved to a separate ./components export so they stay off /alpha sync and the path remains stable after alpha→stable graduation (MF forbids nested mounts like ./alpha/components).
  • Lazy-load the AppBar shell in globalHeaderModule and config-driven HeaderIconButton so MUI is not on the alpha sync graph.
  • Remaining ~116 KB is mostly Zod / frontend-plugin-api (framework tax).

NFS alpha expose summary

Metric BEFORE AFTER Δ
Sync chunks 5 3 -2
Sync size 972 KB 116 KB -857 KB (-88%)
Async chunks 198 240 +42
Async size 963 KB 2123 KB +1160 KB

GIF:

Tested on RHDH with Quickstarts plugin

Screen.Recording.2026-07-27.at.10.44.05.PM.mov

Test setup:

Update the Quickstarts plugin

import { GlobalHeaderMenuItem } from '@red-hat-developer-hub/backstage-plugin-global-header/components';
  1. Use blueprint loader — src/index.tsx:
const quickstartHelpMenuItem = GlobalHeaderMenuItemBlueprint.make({
  name: 'quickstart',
  params: {
    target: 'help',
    priority: 50,
    loader: async () => {
      const { QuickstartHelpMenuItem } = await import(
        './QuickstartHelpMenuItem'
      );
      return QuickstartHelpMenuItem;
    },
  },
});
(GlobalHeaderMenuItemBlueprint still comes from /alpha.)
  1. Local portal (so TS + runtime see /components before publish)

In workspaces/quickstart:

File Dependency
package.json (resolutions) portal:../global-header/plugins/global-header
plugins/quickstart/package.json. portal:../../../global-header/plugins/global-header
packages/app/package.json. portal:../../../global-header/plugins/global-header

  1. Build and export global-header and then quick start plugins into RHDH
npx @red-hat-developer-hub/cli plugin export --clean --dev \
  --dynamic-plugins-root <path-to>/rhdh/dynamic-plugins-root
  1. check-out PR chore(app-next): add runnable RHDH NFS shell for local development rhdh#5115 and run the following commands:
EXPERIMENTAL_MODULE_FEDERATION=true yarn workspace app-next build
yarn workspace backend start:next 

✔️ Checklist

  • A changeset describing the change and affected packages. (more info)
  • Added or Updated documentation
  • Tests for new functionality and regression tests for bug fixes
  • Screenshots attached (for UI changes)

@rhdh-gh-app

rhdh-gh-app Bot commented Jul 27, 2026

Copy link
Copy Markdown

Important

This PR includes changes that affect public-facing API. Please ensure you are adding/updating documentation for new features or behavior.

Changed Packages

Package Name Package Path Changeset Bump Current Version
app workspaces/global-header/packages/app none v0.0.0
@red-hat-developer-hub/backstage-plugin-global-header workspaces/global-header/plugins/global-header minor v1.22.1

@rhdh-qodo-merge

Copy link
Copy Markdown

PR Summary by Qodo

Optimize global-header federation sync via loaders and /components entry

✨ Enhancement 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add a new /components MF entry for building-block header UI exports.
• Prefer blueprint loader + lazy AppBar to keep MUI off /alpha sync.
• Replace sync MUI icons with HeaderIcon ligatures and fix menu item layout.
Diagram

graph TD
  A["Plugin consumer"] --> B["global-header /alpha"] --> C["Blueprints"] --> D["ExtensionBoundary.lazyComponent"] --> E["Async UI chunks"] --> F["MUI + Header UI"]
  B --> G["globalHeaderModule"] --> H["Lazy GlobalHeader"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Split building blocks into a separate NPM package
  • ➕ Hard boundary prevents accidental sync-graph bloat
  • ➕ Avoids MF expose constraints entirely
  • ➖ Extra package/versioning/release overhead
  • ➖ More complicated dependency story for plugin authors
2. Keep exports in /alpha but rely on tree-shaking
  • ➕ No breaking import-path change for consumers
  • ➕ Less export surface/config churn
  • ➖ Doesn't reliably reduce MF sync size (sync chunk often includes UI deps)
  • ➖ Harder to enforce 'thin registration, heavy UI async' invariant

Recommendation: The PR’s approach (separate /components MF entry + loader-first blueprints + lazy AppBar shell) is the most reliable way to minimize the Module Federation sync graph given MF expose/mount constraints. The separate entry also preserves a stable import path for building blocks after alpha graduation.

Files changed (23) +550 / -269

Enhancement (10) +342 / -146
App.tsxSwitch sample header extension to loader-based /components import +21/-11

Switch sample header extension to loader-based /components import

• Updates the example menu item extension to use a blueprint 'loader' that dynamically imports 'GlobalHeaderMenuItem' from '/components'. Removes the eager '/alpha' building-block import to keep the app’s sync graph small.

workspaces/global-header/packages/app/src/App.tsx

components.tsCreate /components MF entry exporting building-block components +50/-0

Create /components MF entry exporting building-block components

• Adds a dedicated entry point that re-exports building-block components and types while default-exporting an empty 'createFrontendModule' so Backstage federates the entry. Documents why the path is '/components' (MF forbids nested mounts).

workspaces/global-header/plugins/global-header/src/alpha/components.ts

ApplicationLauncherDropdown.tsxReplace MUI icon imports with HeaderIcon ligatures +6/-6

Replace MUI icon imports with HeaderIcon ligatures

• Removes '@mui/icons-material' usage from the dropdown button and empty state. Uses 'HeaderIcon' and lightweight MUI 'Box' styling to keep icon code off the sync path.

workspaces/global-header/plugins/global-header/src/alpha/components/ApplicationLauncherDropdown.tsx

HelpDropdown.tsxSwap Help dropdown icons to HeaderIcon + Box wrapper +6/-4

Swap Help dropdown icons to HeaderIcon + Box wrapper

• Removes '@mui/icons-material' icons and replaces them with 'HeaderIcon' (ligatures) for both the toolbar button and the empty-state icon. Uses 'Box' to preserve sizing and disabled coloring.

workspaces/global-header/plugins/global-header/src/alpha/components/HelpDropdown.tsx

ProfileDropdown.tsxReplace profile dropdown icons with HeaderIcon +14/-6

Replace profile dropdown icons with HeaderIcon

• Removes MUI icon imports for account and chevron, replacing them with 'HeaderIcon' inside 'Box' wrappers. Preserves spacing and background styling while reducing sync-path icon dependencies.

workspaces/global-header/plugins/global-header/src/alpha/components/ProfileDropdown.tsx

menuItemExtensions.tsxLazy-load default dropdown menu items via blueprint loader +12/-9

Lazy-load default dropdown menu items via blueprint loader

• Converts default menu item extensions (profile/logout/support) from eager 'component' references to 'loader' functions with dynamic imports. Updates documentation comments to reflect loader/component behavior.

workspaces/global-header/plugins/global-header/src/alpha/defaults/menuItemExtensions.tsx

toolbarExtensions.tsxConvert default toolbar extensions to loader-first and data-driven tiers +63/-33

Convert default toolbar extensions to loader-first and data-driven tiers

• Replaces eager component imports with per-extension 'loader' functions for heavy UI (search, dropdowns, notifications, etc.). Converts the self-service button to data-driven params (title/icon/link) so the blueprint can lazy-load the shared button implementation.

workspaces/global-header/plugins/global-header/src/alpha/defaults/toolbarExtensions.tsx

blueprints.tsxAdd loader support and async data-driven component resolution +141/-65

Add loader support and async data-driven component resolution

• Extends toolbar and menu-item blueprint params with 'loader' and wraps implementations with 'ExtensionBoundary' for both lazy and sync components. Introduces an async data-driven loader so 'HeaderIconButton' and related MUI imports stay off the blueprint’s sync module graph.

workspaces/global-header/plugins/global-header/src/alpha/extensions/blueprints.tsx

globalHeaderModule.tsxLazy-load the GlobalHeader AppBar shell in the wrapper module +10/-3

Lazy-load the GlobalHeader AppBar shell in the wrapper module

• Removes the eager 'GlobalHeader' import and replaces it with 'React.lazy' + 'Suspense'. This keeps the AppBar/MUI-heavy shell out of the '/alpha' federation sync chunk.

workspaces/global-header/plugins/global-header/src/alpha/extensions/globalHeaderModule.tsx

readConfigComponents.tsxLazy-load config-driven HeaderIconButton rendering +19/-9

Lazy-load config-driven HeaderIconButton rendering

• Wraps config-driven header components in 'Suspense' and uses a lazy import for 'HeaderIconButton'. Keeps config-rendered UI from pulling MUI into the federation sync chunk.

workspaces/global-header/plugins/global-header/src/alpha/utils/readConfigComponents.tsx

Bug fix (6) +46 / -7
GlobalHeaderMenuItem.tsxFix menu item anchor layout to be full-width and consistent +9/-1

Fix menu item anchor layout to be full-width and consistent

• Expands the menu item link styling (padding/width/boxSizing/flex) to ensure consistent clickable area and layout across environments. Keeps visual styling aligned with other menu item wrappers.

workspaces/global-header/plugins/global-header/src/alpha/components/GlobalHeaderMenuItem.tsx

MyProfileMenuItem.tsxNormalize profile menu item link styling +9/-1

Normalize profile menu item link styling

• Updates the profile menu item’s link styling to match the new full-width/flex layout approach. Improves consistency with other menu items and surrounding wrappers.

workspaces/global-header/plugins/global-header/src/alpha/components/MyProfileMenuItem.tsx

MenuSection.tsxFix MenuSection menu item link wrapper styling and link props +10/-3

Fix MenuSection menu item link wrapper styling and link props

• Moves link wiring to a conditional spread to avoid always setting 'component/to'. Updates 'sx' to enforce full-width/flex layout and consistent padding across Backstage/RHDH styling differences.

workspaces/global-header/plugins/global-header/src/components/HeaderDropdownComponent/MenuSection.tsx

LogoutButton.tsxNormalize Logout button menu item layout to match other items +4/-0

Normalize Logout button menu item layout to match other items

• Adjusts padding/box model and layout styles so the logout row aligns with other menu items and fills the row width reliably. Helps maintain consistent clickable area and spacing.

workspaces/global-header/plugins/global-header/src/components/LogoutButton/LogoutButton.tsx

MenuItemLinkContent.tsxMove padding to menu item content for PatternFly compatibility +5/-1

Move padding to menu item content for PatternFly compatibility

• Replaces margin shorthand with 'my' and adds 'px' padding and 'boxSizing' at the content level. Documents why padding is applied to content (downstream styling zeroes padding on anchors/list items).

workspaces/global-header/plugins/global-header/src/components/MenuItemLink/MenuItemLinkContent.tsx

SupportButton.tsxUpdate Support button menu item styling for consistent row layout +9/-1

Update Support button menu item styling for consistent row layout

• Adjusts 'MenuItem' styling to match the new standard (padding, full width, flex layout, boxSizing). Ensures consistent appearance across help/profile dropdowns.

workspaces/global-header/plugins/global-header/src/components/SupportButton/SupportButton.tsx

Documentation (3) +76 / -44
components-entry-lazy-appbar.mdAdd changeset for /components entry and loader-first guidance +7/-0

Add changeset for /components entry and loader-first guidance

• Introduces a minor release note documenting the breaking import-path move for building blocks. Calls out the preferred pattern of dynamically importing components inside blueprint loaders and notes AppBar/MUI lazy-loading rationale.

workspaces/global-header/.changeset/components-entry-lazy-appbar.md

new-frontend-system.mdUpdate NFS docs to use loaders and /components building blocks +68/-43

Update NFS docs to use loaders and /components building blocks

• Rewrites examples to prefer 'loader' over 'component', dynamically importing building blocks from the new '/components' entry. Adds 'loader' to the parameter reference and clarifies which exports remain under '/alpha' versus '/components'.

workspaces/global-header/docs/new-frontend-system.md

README.mdDocument new /components import path for building-block UI +1/-1

Document new /components import path for building-block UI

• Clarifies that other plugins should import 'GlobalHeaderMenuItem'/'GlobalHeaderDropdown' from '/components' so they stay off the '/alpha' sync chunk. Keeps the existing pointer to the NFS documentation for full examples.

workspaces/global-header/plugins/global-header/README.md

Other (4) +86 / -72
package.jsonExport new ./components entry with typesVersions mapping +4/-0

Export new ./components entry with typesVersions mapping

• Adds a './components' export pointing at 'src/alpha/components.ts' and a corresponding 'typesVersions' entry. This enables consumers to import building blocks via '@.../components' with correct TS resolution.

workspaces/global-header/plugins/global-header/package.json

report-alpha.api.mdUpdate alpha API report for loader params and moved UI exports +2/-64

Update alpha API report for loader params and moved UI exports

• Removes building-block component exports from the '/alpha' report and adds 'loader' to toolbar/menu blueprint parameter types. Aligns the reported API surface with the new lazy-loading strategy.

workspaces/global-header/plugins/global-header/report-alpha.api.md

report-components.api.mdAdd API report for new /components entry +75/-0

Add API report for new /components entry

• Introduces a new API Extractor report describing the '/components' entry surface: 'GlobalHeaderIconButton', 'GlobalHeaderMenuItem', and 'GlobalHeaderDropdown' (and associated props).

workspaces/global-header/plugins/global-header/report-components.api.md

index.tsStop exporting building-block components from /alpha entry +5/-8

Stop exporting building-block components from /alpha entry

• Removes the building-block component re-exports from the '/alpha' barrel and replaces them with guidance comments pointing to '@.../components'. This enforces a smaller sync graph for the main federation entry.

workspaces/global-header/plugins/global-header/src/alpha/index.ts

@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 5.35714% with 53 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.42%. Comparing base (376ef8a) to head (11f5f34).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4006      +/-   ##
==========================================
- Coverage   56.44%   56.42%   -0.03%     
==========================================
  Files        2383     2383              
  Lines       95609    95649      +40     
  Branches    26718    26721       +3     
==========================================
+ Hits        53968    53970       +2     
- Misses      41268    41305      +37     
- Partials      373      374       +1     
Flag Coverage Δ *Carryforward flag
adoption-insights 84.54% <ø> (ø) Carriedforward from 376ef8a
ai-integrations 69.06% <ø> (ø) Carriedforward from 376ef8a
app-defaults 69.79% <ø> (ø) Carriedforward from 376ef8a
augment 46.67% <ø> (ø) Carriedforward from 376ef8a
boost 75.92% <ø> (ø) Carriedforward from 376ef8a
bulk-import 72.55% <ø> (ø) Carriedforward from 376ef8a
cost-management 13.55% <ø> (ø) Carriedforward from 376ef8a
dcm 60.72% <ø> (ø) Carriedforward from 376ef8a
extensions 56.48% <ø> (ø) Carriedforward from 376ef8a
global-floating-action-button 71.18% <ø> (ø) Carriedforward from 376ef8a
global-header 60.07% <5.35%> (-2.11%) ⬇️
homepage 47.46% <ø> (ø) Carriedforward from 376ef8a
install-dynamic-plugins 56.77% <ø> (ø) Carriedforward from 376ef8a
intelligent-assistant 74.06% <ø> (ø) Carriedforward from 376ef8a
konflux 91.98% <ø> (ø) Carriedforward from 376ef8a
lightspeed 69.02% <ø> (ø) Carriedforward from 376ef8a
mcp-integrations 83.40% <ø> (ø) Carriedforward from 376ef8a
orchestrator 66.79% <ø> (ø) Carriedforward from 376ef8a
quickstart 65.04% <ø> (ø) Carriedforward from 376ef8a
sandbox 79.56% <ø> (ø) Carriedforward from 376ef8a
scorecard 82.97% <ø> (ø) Carriedforward from 376ef8a
theme 83.89% <ø> (ø) Carriedforward from 376ef8a
translations 5.12% <ø> (ø) Carriedforward from 376ef8a
x2a 55.05% <ø> (ø) Carriedforward from 376ef8a

*This pull request uses carry forward flags. Click here to find out more.


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 376ef8a...11f5f34. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@rhdh-qodo-merge

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Context used
⚠️ Tickets: not configured — ticket URL found in PR but could not be fetched — check ticket provider credentials
✅ Compliance rules (platform): 11 rules
✅ Cross-repo context
  ⚠️ Failed to retrieve: redhat-developer/rhdh
  Not relevant to this PR: redhat-developer/rhdh-chart
  Not relevant to this PR: redhat-developer/rhdh-operator
  Not relevant to this PR: redhat-developer/rhdh-local

Grey Divider


Action required

1. trackValidity stuck on empty 🐞 Bug ≡ Correctness
Description
HelpDropdown uses trackValidity, but this PR changes the default help item to load via a
blueprint loader, meaning the dropdown can initially render with no [role="menuitem"] nodes.
GlobalHeaderDropdown then flips to emptyState (unmounting the menu content), so the dropdown can
remain empty for that open session even though items exist and would appear once loaded.
Code

workspaces/global-header/plugins/global-header/src/alpha/defaults/menuItemExtensions.tsx[R82-85]

+      loader: () =>
+        import('../../components/SupportButton/SupportButton').then(
+          m => m.SupportButton,
+        ),
Relevance

⭐⭐⭐ High

Team often accepts fixes for transient empty-state/stale UI when async data loads into menus.

PR-#1804
PR-#3282

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The Help dropdown explicitly enables trackValidity, and the support button menu item is now loaded
asynchronously via loader. GlobalHeaderDropdown computes showEmpty from `trackValidity &&
!hasVisibleItems and (when true) renders emptyState` instead of rendering
GlobalHeaderDropdownContent, while hasVisibleItems is only updated by a layout effect that
checks for [role="menuitem"] in the rendered MenuList—creating a timing window where async items
are not yet rendered and the dropdown flips to empty.

workspaces/global-header/plugins/global-header/src/alpha/components/HelpDropdown.tsx[29-51]
workspaces/global-header/plugins/global-header/src/alpha/defaults/menuItemExtensions.tsx[75-87]
workspaces/global-header/plugins/global-header/src/alpha/components/GlobalHeaderDropdown.tsx[71-113]
workspaces/global-header/plugins/global-header/src/alpha/extensions/blueprints.tsx[104-112]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`GlobalHeaderDropdown`’s `trackValidity` logic can switch to `emptyState` before async-loaded menu items finish rendering. Once `emptyState` is shown, the menu content is unmounted, so lazy items may never mount/render for that open session.

### Issue Context
This PR converts the default Help dropdown’s `support-button` extension to use a blueprint `loader` (async component). `HelpDropdown` enables `trackValidity`, which relies on DOM presence of `[role="menuitem"]`.

### Fix Focus Areas
- workspaces/global-header/plugins/global-header/src/alpha/components/GlobalHeaderDropdown.tsx[75-113]
- workspaces/global-header/plugins/global-header/src/alpha/defaults/menuItemExtensions.tsx[75-87]
- workspaces/global-header/plugins/global-header/src/alpha/components/HelpDropdown.tsx[29-51]

### Suggested fix approach
1. Ensure the validity check re-runs after any render while the dropdown is open (e.g., remove the dependency array and guard with `if (!trackValidity || !isOpen) return;`), so it can recover when lazy items finally render.
2. Avoid unmounting the menu content solely due to `trackValidity` while items may still be loading. A robust pattern is:
  - Always render `GlobalHeaderDropdownContent` when `entries.length > 0`.
  - Conditionally *also* render `emptyState` (or overlay it) when no visible menu items are found, instead of replacing/unmounting the content.
3. Add a test case that opens Help dropdown with a lazy-loaded menu item and asserts it eventually renders (and does not get stuck on `emptyState`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Lazy header lacks boundary 🐞 Bug ☼ Reliability
Description
The global header shell is now loaded via React.lazy and wrapped only in Suspense, so a rejected
dynamic import (e.g., missing/failed chunk) will error the header subtree instead of being contained
with a controlled fallback. This reduces resilience of a core navigation surface under real-world
chunk-load failures.
Code

workspaces/global-header/plugins/global-header/src/alpha/extensions/globalHeaderModule.tsx[R78-80]

+      <Suspense fallback={null}>
+        <LazyGlobalHeader />
+      </Suspense>
Relevance

⭐⭐ Medium

Resilience improvement is plausible, but adding an outer ErrorBoundary for lazy-import failures is
somewhat subjective.

PR-#3572
PR-#3296

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
globalHeaderModule now defines and renders LazyGlobalHeader via React.lazy with only a
Suspense wrapper. Meanwhile, the GlobalHeader component’s existing ErrorBoundary usage only
applies *after* the shell has successfully loaded and started rendering toolbar items, so it cannot
catch a lazy-import failure for the shell itself.

workspaces/global-header/plugins/global-header/src/alpha/extensions/globalHeaderModule.tsx[39-83]
workspaces/global-header/plugins/global-header/src/alpha/components/GlobalHeader.tsx[17-62]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`LazyGlobalHeader` is rendered inside `Suspense` but not inside an `ErrorBoundary`. If the dynamic import rejects, React will throw an error (not a Suspense fallback), and without a local boundary the failure propagates to the nearest ancestor boundary (potentially taking out the header wrapper).

### Issue Context
The project already uses `@backstage/core-components` `ErrorBoundary` inside the `GlobalHeader` component for individual toolbar items, but the lazy-loaded *shell* itself is outside that protection.

### Fix Focus Areas
- workspaces/global-header/plugins/global-header/src/alpha/extensions/globalHeaderModule.tsx[39-83]
- workspaces/global-header/plugins/global-header/src/alpha/components/GlobalHeader.tsx[17-62]

### Suggested fix approach
Wrap the `<Suspense><LazyGlobalHeader/></Suspense>` block in `@backstage/core-components` `ErrorBoundary` (or use an equivalent Backstage boundary) with a small fallback that preserves layout (even if it’s `null`) and logs a useful error. This confines chunk-load failures to the header region and avoids breaking the wrapper subtree.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@rhdh-qodo-merge rhdh-qodo-merge Bot added documentation Improvements or additions to documentation enhancement New feature or request labels Jul 27, 2026
@debsmita1
debsmita1 force-pushed the global-header-optimization branch from 27ade55 to 9460854 Compare July 27, 2026 17:42
@debsmita1
debsmita1 force-pushed the global-header-optimization branch from 9460854 to 11f5f34 Compare July 27, 2026 17:42
@sonarqubecloud

Copy link
Copy Markdown

@ciiay ciiay left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The following files still importing GlobalHeaderMenuItem from /alpha. Let's also update them in this pr.

  1. workspaces/quickstart/plugins/quickstart/src/QuickstartHelpMenuItem.tsx
  2. workspaces/app-defaults/packages/app/src/modules/drawer-demo/DrawerDemoContent.tsx

loader: () =>
import('../../components/SupportButton/SupportButton').then(
m => m.SupportButton,
),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

HelpDropdown sets trackValidity. This PR makes support-button async via loader. GlobalHeaderDropdown flips to emptyState (and unmounts menu content) when no [role="menuitem"] is found, and never resets hasVisibleItems.
This could cause a race condition: open Help before the lazy SupportButton paints → no menuitem → hasVisibleItems=false → content unmounted → items never mount for that session (and reopen stays empty). Qodo also flagged this which I agree is high severity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request workspace/global-header

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants