Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] fix(ContextMenu): create PopoverOverlay to avoid using popper.js #6720

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from

Conversation

adidahiya
Copy link
Contributor

@adidahiya adidahiya commented Feb 22, 2024

Fixes #5503

Checklist

  • Includes tests
  • Update documentation

Changes proposed in this pull request:

  • Refactor Popover's overlay functionality into a new component called PopoverOverlay which must be absolutely positioned on the page via props.style
  • Use PopoverOverlay in Popover, ContextMenu, and ContextMenuPopover
  • This removes popper.js behavior from ContextMenu and ContextMenuPopover, since we already have all the information we need to position the menu on the page with fixed positioning
    • I was never able to fully get to the bottom of the issue here, but for some reason @popperjs/core would not position our context menu "virtual target" element correctly in React 18 strict mode. Perhaps it's violating the rules somehow. I bet their advice would be to migrate to Floating UI, which we're not going to do any time soon (see Migrate to Floating UI #5739). So I figure the best approach is to stop using popper.js -- we don't even need any of its features for our context menu implementation.
  • This fixes Context menu snaps to top left corner in React 18 Strict Mode #5503, but that's only testable on a branch with React 18 used throughout the whole monorepo: [DEMO] use React 18 in demo-app, fix ContextMenu positioning #6702
  • Note that there is a small breaking change to ContextMenuPopover: the rootBoundary prop is now ignored, as it doesn't make sense to have this be anything other than "viewport"

Reviewers should focus on:

No regressions in any popover-related components + context menu

Screenshot

Screen Recording 2024-02-26 at 10 17 54 AM

Screen Recording 2024-02-26 at 10 17 33 AM

@adidahiya
Copy link
Contributor Author

[core] fix(ContextMenu): create PopoverOverlay to avoid using popper.js

Build artifact links for this commit: documentation | landing | table | demo

This is an automated comment from the deploy-preview CircleCI job.

@adidahiya
Copy link
Contributor Author

fix core:test:typeCheck

Build artifact links for this commit: documentation | landing | table | demo

This is an automated comment from the deploy-preview CircleCI job.

@adidahiya
Copy link
Contributor Author

minor code style fix: destructure transitionDuration

Build artifact links for this commit: documentation | landing | table | demo

This is an automated comment from the deploy-preview CircleCI job.

@adidahiya adidahiya force-pushed the ad/fix-context-menu-snapping-react-16 branch from 8f7da3e to 5e83160 Compare February 26, 2024 15:17
Copy link
Contributor Author

@adidahiya adidahiya left a comment

Choose a reason for hiding this comment

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

note that we no longer use ContextMenuPopover in Blueprint but it is still exported in the public API to avoid a breaking change. we should probably deprecate that component.

edit: no, actually, we can migrate ContextMenuPopover to use PopoverOverlay and continue supporting it.

menuContent === undefined || targetOffset === undefined || !isOpen ? undefined : (
<PopoverOverlay
containerRef={popoverElement}
content={<div onContextMenu={cancelContextMenu}>{menuContent}</div>}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

previously, this cancelContextMenu functionality happened in ContextMenuPopover

@adidahiya
Copy link
Contributor Author

fwd more props to fix bugs

Build artifact links for this commit: documentation | landing | table | demo

This is an automated comment from the deploy-preview CircleCI job.

@adidahiya adidahiya marked this pull request as ready for review February 28, 2024 15:45
@adidahiya
Copy link
Contributor Author

migrate ContextMenuPopover to PopoverOverlay

Build artifact links for this commit: documentation | landing | table | demo

This is an automated comment from the deploy-preview CircleCI job.

@adidahiya
Copy link
Contributor Author

fix resize sensor coverage

Build artifact links for this commit: documentation | landing | table | demo

This is an automated comment from the deploy-preview CircleCI job.

adidahiya added a commit that referenced this pull request Feb 28, 2024
@adidahiya
Copy link
Contributor Author

Confirmed that this fixes the linked bug in React 18 strict mode on this branch: #6702

image

you can see that demo-app is rendering in strict mode: https://github.com/palantir/blueprint/blob/ad/fix-context-menu-snapping/packages/demo-app/src/index.tsx#L33-L37

@ab-pm
Copy link

ab-pm commented May 15, 2024

for some reason @popperjs/core would not position our context menu "virtual target" element correctly in React 18 strict mode. Perhaps it's violating the rules somehow.

Have a look at #4642 (comment) for how to get rid of the "virtual target" rendered in a portal, and use a popper.js virtual element instead.
Admittedly updating the ref from renderTarget causes a "Warning: Cannot update a component (Manager) while rendering a different component (Reference). To locate the bad setState() call inside Reference, follow the stack trace as described in https://reactjs.org/link/setstate-in-render". However if this was built into the <Popover> code (instead of my hacky attempt), it could actually update the ref from the context menu click handler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Context menu snaps to top left corner in React 18 Strict Mode
2 participants