Skip to content

Comments

OCPBUGS-77044: Fix topology node labels disappearing when moving cursor to kebab menu#16042

Open
rhamilto wants to merge 1 commit intoopenshift:mainfrom
rhamilto:OCPBUGS-77044
Open

OCPBUGS-77044: Fix topology node labels disappearing when moving cursor to kebab menu#16042
rhamilto wants to merge 1 commit intoopenshift:mainfrom
rhamilto:OCPBUGS-77044

Conversation

@rhamilto
Copy link
Member

@rhamilto rhamilto commented Feb 18, 2026

Summary

Fixed topology node labels disappearing when moving cursor from the node to the kebab menu.

After (KnativeServiceGroup not included)

Screen.Recording.2026-02-18.at.2.51.13.PM.mov

Changes

Group Components (HelmReleaseGroup, KnativeServiceGroup, OperatorBackedServiceGroup)

  • Added separate labelHover state tracking using useHover() hook
  • Combined hover states: isHovering = hover || innerHover || labelHover || contextMenuOpen
  • Added 200ms delay on mouseleave for node hover states to create smooth transition when moving cursor to label
  • Updated label visibility condition to: showLabel || labelHover || contextMenuOpen
  • Combined refs: useCombineRefs(dragLabelRef, labelHoverRef) to track hover on the label element itself

Application Component

  • Restored hover tracking with useHover() and useCombineRefs(dragNodeRef, hoverRef)
  • Calculate showLabel based on hover via useShowLabel(hover)
  • Force label to stay visible when context menu is open: showLabel={showLabel || contextMenuOpen}
  • Enable hover-based label visibility with showLabelOnHover

InventoryItem Component

  • Fixed TypeScript error by importing ResolvedExtension directly from @console/dynamic-plugin-sdk instead of internal dist path

Technical Details

The fix uses different approaches for different component types:

Custom Group Components (Helm, Knative, Operator-backed):

  • Use 200ms delay on mouseleave for node hover states
  • When moving from node to label:
    1. Mouse leaves node → hover and innerHover start 200ms countdown
    2. Mouse enters label → labelHover becomes true
    3. Label stays visible because (showLabel || labelHover || contextMenuOpen) is still true
    4. The 200ms grace period ensures no flicker between node and label hover states

Application Component (using DefaultGroup):

  • Uses PatternFly's DefaultGroup component which has built-in label hover handling
  • Combines showLabel (based on node hover) with contextMenuOpen to keep label visible
  • showLabelOnHover enables the hover behavior
  • showLabel={showLabel || contextMenuOpen} ensures label persists when context menu opens

Test plan

  • Hover over a group node (Helm Release, Knative Service, or Operator-backed Service) in topology view
  • Move cursor from the node to the label and kebab menu
  • Verify label remains visible during transition
  • Verify kebab menu can be clicked
  • Verify label remains visible while context menu is open
  • Test Application groups to ensure labels appear on hover and stay visible with context menu

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Improved label visibility when context menus are open, ensuring consistent visual feedback.
    • Enhanced hover state persistence to prevent visual glitches when interacting with context menus.
    • Refined label dragging behavior for better stability during menu interactions.
    • Optimized context menu rendering performance with memoization.

@openshift-ci-robot openshift-ci-robot added jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. labels Feb 18, 2026
@openshift-ci-robot
Copy link
Contributor

@rhamilto: This pull request references Jira Issue OCPBUGS-77044, which is valid. The bug has been moved to the POST state.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (4.22.0) matches configured target version for branch (4.22.0)
  • bug is in the state ASSIGNED, which is one of the valid states (NEW, ASSIGNED, POST)

Requesting review from QA contact:
/cc @yapei

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

Summary

Fixed an issue where topology node labels with kebab menus would disappear when users moved their cursor from the node to access the kebab menu or when the context menu was open.

Changes

  • BaseNode: Added raiseLabelOnHover={false} to prevent double layer switching that was causing label remounts and hover state loss
  • BaseNode & WorkloadNode: Track combined hover state (hover || contextMenuOpen) to keep labels visible when context menu is open
  • Application: Removed local hover management and let PatternFly's DefaultGroup handle label visibility via internal hover detection
  • OperatorBackedServiceGroup: Added separate label hover tracking to maintain label visibility when hovering over the label itself
  • withTopologyContextMenu: Memoized action context to prevent unnecessary re-renders when context menu is open

Test plan

  • Navigate to Topology view
  • Hover over a workload node and verify the label appears
  • Move cursor from node to label and verify label stays visible
  • Click the kebab menu in the label
  • Move cursor to the context menu items and verify menu doesn't flicker or disappear
  • Repeat for application groups and operator-backed service groups

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot added component/topology Related to topology approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Feb 18, 2026
@openshift-ci-robot
Copy link
Contributor

@rhamilto: This pull request references Jira Issue OCPBUGS-77044, which is valid.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (4.22.0) matches configured target version for branch (4.22.0)
  • bug is in the state POST, which is one of the valid states (NEW, ASSIGNED, POST)

Requesting review from QA contact:
/cc @yapei

Details

In response to this:

Summary

Fixed an issue where topology node labels with kebab menus would disappear when users moved their cursor from the node to access the kebab menu or when the context menu was open.

After

Screen.Recording.2026-02-18.at.1.25.27.PM.mov

Changes

  • BaseNode: Added raiseLabelOnHover={false} to prevent double layer switching that was causing label remounts and hover state loss
  • BaseNode & WorkloadNode: Track combined hover state (hover || contextMenuOpen) to keep labels visible when context menu is open
  • Application: Removed local hover management and let PatternFly's DefaultGroup handle label visibility via internal hover detection
  • OperatorBackedServiceGroup: Added separate label hover tracking to maintain label visibility when hovering over the label itself
  • withTopologyContextMenu: Memoized action context to prevent unnecessary re-renders when context menu is open

Test plan

  • Navigate to Topology view
  • Hover over a workload node and verify the label appears
  • Move cursor from node to label and verify label stays visible
  • Click the kebab menu in the label
  • Move cursor to the context menu items and verify menu doesn't flicker or disappear
  • Repeat for application groups and operator-backed service groups

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 18, 2026

📝 Walkthrough

Walkthrough

The PR stabilizes hover-driven visuals by introducing an isHovering composite (combining hover, contextMenuOpen and, where present, innerHover/labelHover) across topology components. Application now accepts and forwards contextMenuOpen to GroupNode and DefaultGroup; GroupNode exposes an optional hover prop. BaseNode and WorkloadNode switch label/details logic to isHovering. Several group components add labelHover refs and combined dragLabelRefs for label drag/hover. withTopologyContextMenu memoizes actionContext with useMemo.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly describes the main fix: preventing topology node labels from disappearing when the cursor moves to the kebab menu, which is the core problem addressed across all file changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

@rhamilto rhamilto force-pushed the OCPBUGS-77044 branch 11 times, most recently from fbaaf5a to 104c053 Compare February 18, 2026 19:12
@openshift-ci openshift-ci bot added component/helm Related to helm-plugin component/knative Related to knative-plugin labels Feb 18, 2026
@rhamilto
Copy link
Member Author

/hold

Found additional issues.

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Feb 18, 2026
@rhamilto rhamilto force-pushed the OCPBUGS-77044 branch 2 times, most recently from 9689f9a to ea065f6 Compare February 18, 2026 19:43
@rhamilto
Copy link
Member Author

/hold cancel

@openshift-ci openshift-ci bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Feb 18, 2026
@rhamilto
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 18, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
frontend/packages/topology/src/components/graph-view/components/withTopologyContextMenu.tsx (1)

37-43: Memoization dependency on !!reference is correct but warrants a clearer explanation.

The pattern works because reference transitions null → {x,y} → null on each open/close cycle, so !!reference does toggle. However, the eslint-disable comment could be more explicit about why the boolean coercion is intentional—future maintainers might "fix" this by adding reference directly, which would defeat the optimization.

Consider expanding the comment:

     // Memoize the action context to prevent unnecessary re-renders of ActionServiceProvider
-    // Only recompute when the context menu is opened (reference changes from null to a value)
+    // Only recompute when the context menu is opened (reference transitions from null to a value).
+    // We intentionally use `!!reference` (boolean) rather than `reference` itself, so that
+    // position changes while the menu is open do not trigger a recomputation.
     const memoizedActionContext = useMemo(
       () => (reference ? actionContext(element as E) : null),
       // eslint-disable-next-line react-hooks/exhaustive-deps
       [!!reference],
     );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/topology/src/components/graph-view/components/withTopologyContextMenu.tsx`
around lines 37 - 43, Clarify the intentional use of boolean coercion for the
useMemo dependency: update the comment above the memoizedActionContext/useMemo
to explain that we deliberately use `!!reference` (not `reference`) so the memo
only toggles when reference goes null↔value on open/close cycles, preventing
recomputation when the reference object identity changes every render; mention
that this is required to avoid adding `reference`, `actionContext`, or `element`
to the deps (and why we keep the eslint-disable-next-line
react-hooks/exhaustive-deps) and reference the memoizedActionContext, useMemo,
reference, actionContext, and element symbols so future maintainers understand
the tradeoff.
frontend/packages/knative-plugin/src/topology/components/groups/KnativeServiceGroup.tsx (2)

113-113: Consider memoizing the hover condition passed to useShowLabel.

hover || innerHover creates a new boolean on every render, which is fine for primitives, but worth noting that useShowLabel will re-evaluate on each change. Given the frequency of hover state changes during mouse movement, ensure the hook internally handles rapid updates gracefully.

Minor observation—no action required unless you observe performance issues with many Knative groups rendered simultaneously.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/topology/components/groups/KnativeServiceGroup.tsx`
at line 113, The hover condition passed into useShowLabel is recomputed each
render; memoize it by creating a stable value (e.g., memoizedHover = useMemo(()
=> hover || innerHover, [hover, innerHover])) and pass memoizedHover into
useShowLabel in KnativeServiceGroup.tsx so useShowLabel receives a stable
boolean (refer to useShowLabel, hover, innerHover, showLabel).

207-224: Label visibility should account for keyboard focus when keyboard navigation is implemented.

The current condition (showLabel || labelHover || contextMenuOpen) doesn't include focus state. Keyboard-only users navigating via Tab/Enter won't trigger hover states. However, note that topology components currently lack keyboard navigation support; SVG nodes would require tabIndex, keyboard event handlers, and ARIA roles to be keyboard-accessible. If keyboard navigation is planned, ensure the label visibility condition is extended to include focus state to avoid hiding actionable elements (like the context menu kebab) from keyboard users.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/topology/components/groups/KnativeServiceGroup.tsx`
around lines 207 - 224, Update the NodeLabel visibility condition to include
keyboard focus so labels appear for keyboard users: modify the boolean
expression around NodeLabel in KnativeServiceGroup.tsx (currently using
showLabel, labelHover, contextMenuOpen) to also check a focus state (e.g.,
labelFocus or element-focused flag) and ensure that focus is set by adding
tabIndex and keyboard event handlers (onFocus/onBlur and key handlers) on the
interactive node element so the new focus state is driven by real keyboard
interactions; keep using the existing NodeLabel, onContextMenu, and
dragLabelRefs props but make visibility rely on (showLabel || labelHover ||
contextMenuOpen || labelFocus).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@frontend/packages/knative-plugin/src/topology/components/groups/KnativeServiceGroup.tsx`:
- Line 113: The hover condition passed into useShowLabel is recomputed each
render; memoize it by creating a stable value (e.g., memoizedHover = useMemo(()
=> hover || innerHover, [hover, innerHover])) and pass memoizedHover into
useShowLabel in KnativeServiceGroup.tsx so useShowLabel receives a stable
boolean (refer to useShowLabel, hover, innerHover, showLabel).
- Around line 207-224: Update the NodeLabel visibility condition to include
keyboard focus so labels appear for keyboard users: modify the boolean
expression around NodeLabel in KnativeServiceGroup.tsx (currently using
showLabel, labelHover, contextMenuOpen) to also check a focus state (e.g.,
labelFocus or element-focused flag) and ensure that focus is set by adding
tabIndex and keyboard event handlers (onFocus/onBlur and key handlers) on the
interactive node element so the new focus state is driven by real keyboard
interactions; keep using the existing NodeLabel, onContextMenu, and
dragLabelRefs props but make visibility rely on (showLabel || labelHover ||
contextMenuOpen || labelFocus).

In
`@frontend/packages/topology/src/components/graph-view/components/withTopologyContextMenu.tsx`:
- Around line 37-43: Clarify the intentional use of boolean coercion for the
useMemo dependency: update the comment above the memoizedActionContext/useMemo
to explain that we deliberately use `!!reference` (not `reference`) so the memo
only toggles when reference goes null↔value on open/close cycles, preventing
recomputation when the reference object identity changes every render; mention
that this is required to avoid adding `reference`, `actionContext`, or `element`
to the deps (and why we keep the eslint-disable-next-line
react-hooks/exhaustive-deps) and reference the memoizedActionContext, useMemo,
reference, actionContext, and element symbols so future maintainers understand
the tradeoff.

@rhamilto
Copy link
Member Author

/retest

@rhamilto
Copy link
Member Author

/label acknowledge-critical-fixes-only

@openshift-ci openshift-ci bot added the acknowledge-critical-fixes-only Indicates if the issuer of the label is OK with the policy. label Feb 19, 2026
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 20, 2026
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 23, 2026
Copy link
Member

@logonoff logonoff left a comment

Choose a reason for hiding this comment

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

makes sense to me

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 23, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: logonoff, rhamilto

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

…or to kebab menu

Fixed an issue where topology node labels with kebab menus would disappear
when users moved their cursor from the node to access the kebab menu or when
the context menu was open.

Changes:
- BaseNode: Added raiseLabelOnHover={false} to prevent double layer switching
  that was causing label remounts and hover state loss
- BaseNode & WorkloadNode: Track combined hover state (hover || contextMenuOpen)
  to keep labels visible when context menu is open
- Application: Removed local hover management and let PatternFly's DefaultGroup
  handle label visibility via internal hover detection
- OperatorBackedServiceGroup: Added separate label hover tracking to maintain
  label visibility when hovering over the label itself
- withTopologyContextMenu: Memoized action context to prevent unnecessary
  re-renders when context menu is open

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 24, 2026

@rhamilto: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-gcp-console 5bb93ff link true /test e2e-gcp-console

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

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

Labels

acknowledge-critical-fixes-only Indicates if the issuer of the label is OK with the policy. approved Indicates a PR has been approved by an approver from all required OWNERS files. component/helm Related to helm-plugin component/knative Related to knative-plugin component/topology Related to topology jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants