Skip to content

Conversation

@flaviendelangle
Copy link
Member

@flaviendelangle flaviendelangle commented Jan 20, 2026

Atempt to fix #3673

The hardest part was to now close the root Preview Card when hovering through its children Preview Card

@flaviendelangle flaviendelangle self-assigned this Jan 20, 2026
@flaviendelangle flaviendelangle added type: bug It doesn't behave as expected. component: preview card Changes related to the preview card component. labels Jan 20, 2026
@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 20, 2026

  • vite-css-base-ui-example

    pnpm add https://pkg.pr.new/mui/base-ui/@base-ui/react@3798
    
    pnpm add https://pkg.pr.new/mui/base-ui/@base-ui/utils@3798
    

commit: 432551a

@mui-bot
Copy link

mui-bot commented Jan 20, 2026

Bundle size report

Bundle Parsed size Gzip size
@base-ui/react 🔺+145B(+0.03%) 🔺+11B(+0.01%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@netlify
Copy link

netlify bot commented Jan 20, 2026

Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit 432551a
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/6970ccbce9422a0008ce7a59
😎 Deploy Preview https://deploy-preview-3798--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@flaviendelangle flaviendelangle marked this pull request as ready for review January 20, 2026 13:36
@greptile-apps
Copy link

greptile-apps bot commented Jan 20, 2026

Greptile Summary

This PR successfully implements support for nested preview cards by integrating FloatingTree support, following the same pattern already established in the Popover component. The implementation enables preview cards to be nested within other preview cards while maintaining proper interaction behavior.

Key changes:

  • PreviewCardRoot now conditionally wraps itself in FloatingTree when not already within a preview card context
  • PreviewCardPositioner registers itself as a FloatingNode to enable tree tracking
  • useHoverFloatingInteraction modified to preserve the safePolygon handler during mouse enter events, allowing it to detect nested children and prevent premature parent closure
  • Added comprehensive test coverage for click, hover, and pointer interactions with nested cards
  • Included experiment demos for manual testing

The implementation correctly addresses the issue where hovering through nested preview cards would close parent cards. The safePolygon handler's logic (lines 147-153 in safePolygon.ts) checks for open children in the floating tree and prevents closure when appropriate.

Confidence Score: 4/5

  • Safe to merge with minor concern about hover interaction edge cases
  • The implementation follows established patterns from Popover and includes comprehensive tests. However, the modification to useHoverFloatingInteraction that removes the cleanupMouseMoveHandler() call on mouse enter could potentially leave handlers active longer than necessary, though this appears intentional for nested popup detection.
  • Pay attention to packages/react/src/floating-ui-react/hooks/useHoverFloatingInteraction.ts for potential memory or event handler cleanup issues in complex nested scenarios

Important Files Changed

Filename Overview
packages/react/src/preview-card/root/PreviewCardRoot.tsx Adds FloatingTree support for nested preview cards by wrapping the component conditionally when not already in a preview card context
packages/react/src/floating-ui-react/hooks/useHoverFloatingInteraction.ts Modified hover interaction logic to preserve safePolygon handler for nested popup detection, preventing premature parent closure
packages/react/src/preview-card/positioner/PreviewCardPositioner.tsx Registers positioner as FloatingNode with unique nodeId to enable floating tree tracking for nested scenarios
packages/react/src/preview-card/root/PreviewCardRoot.test.tsx Adds comprehensive test coverage for nested preview card interactions including click, hover, and pointer events

// The handler needs to remain active to detect when mouse leaves to
// a nested portaled popup. The safePolygon logic checks for open children
// in the floating tree and prevents closing when appropriate.
handlerRef.current?.(event);
Copy link
Member Author

Choose a reason for hiding this comment

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

@atomiks I think this fixes the problem.
If we clean the mouse move events when opening the nested popover / preview card, then safePolygon can't properly do its job.

Tbh I don't know the codebase enough yet to be fully confident of the fix.
My experiment of both the nested Popover AND the nested Preview Card now work at least.
And without introducing additional logic that safePolygon should already handle.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah that looks to be a difference between the two hooks.

useHover

    function onFloatingMouseEnter() {
      timeout.clear();
      clearPointerEvents();
    }

useHoverFloatingInteraction

    function onFloatingMouseEnter(event: MouseEvent) {
      openChangeTimeout.clear();
      clearPointerEvents();
      handlerRef.current?.(event);
      cleanupMouseMoveHandler();
    }

Though the old one still doesn't call handlerRef.current

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't get any failing test and the nested popover and preview cards still behavior correctly if I comment the handlerRef.current?.(event); line.

But that's a change that could easily not be covered by any test.
cc @michaldudak since you did the initial useHoverFloatingInteraction implementation

@flaviendelangle
Copy link
Member Author

@greptileai

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

Labels

component: preview card Changes related to the preview card component. type: bug It doesn't behave as expected.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[preview card] nested preview cards don't work

3 participants