Skip to content

[context menu] Create new ContextMenu component #1665

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

Open
wants to merge 26 commits into
base: master
Choose a base branch
from

Conversation

atomiks
Copy link
Contributor

@atomiks atomiks commented Apr 2, 2025

Copy link

netlify bot commented Apr 2, 2025

Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit 0eb8abe
🔍 Latest deploy log https://app.netlify.com/sites/base-ui/deploys/6823ecf95f082c00081ffd67
😎 Deploy Preview https://deploy-preview-1665--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 site configuration.

@atomiks atomiks force-pushed the feat/ContextMenu branch 3 times, most recently from 4d55392 to a9acad9 Compare April 3, 2025 00:31
@atomiks atomiks marked this pull request as ready for review April 3, 2025 01:06
@michaldudak
Copy link
Member

We haven't discussed the API of it. I'm wondering if an ordinary Menu with a different Trigger wouldn't be enough:

<Menu.Root>
  <Menu.ContextTrigger />
  ...

@atomiks
Copy link
Contributor Author

atomiks commented Apr 3, 2025

@michaldudak discoverability-wise, it might be better as a component for Radix parity? The Root needs to know if it should act as a context menu, where a component provider works nicely in the API, since otherwise it would need a prop in conjunction with using Menu.ContextTrigger (unless we set the state in an effect to know it's been rendered, which is a bit annoying).

It's also better if it's part of ContextMenu for tree-shaking reasons. (Edit: if ContextTrigger isn't used, where most of the logic is contained, then tree-shaking still works under your suggestion) - I think many extraneous features, like Tooltip's trackCursorAxis may be better as a component/provider than a prop if it has non-negligible logic.

@mj12albert
Copy link
Member

mj12albert commented Apr 7, 2025

Testing on an iPhone SE (iOS 17.7.2), a long press on the trigger area when the context menu is already open will make a large text selection:

RPReplay_Final1744034094.mp4

I screen-capped Safari only but it repros on Firefox and Chrome as well

According to react-aria it requires quite a heavy handed approach to handle this for all browsers: https://github.com/adobe/react-spectrum/blob/main/packages/%40react-aria/interactions/src/textSelection.ts

@atomiks atomiks force-pushed the feat/ContextMenu branch from 06e668f to 850dee6 Compare April 9, 2025 02:14
@atomiks
Copy link
Contributor Author

atomiks commented Apr 9, 2025

@mj12albert looks like WebkitUserSelect: none on the internal backdrop is enough to fix that

@mj12albert
Copy link
Member

looks like WebkitUserSelect: none on the internal backdrop is enough to fix that

Nice, glad we can avoid that extra Safari handling ~

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Apr 15, 2025
@michaldudak
Copy link
Member

We could add an attribute indicating how the menu was open (touch or right-click). It seems that on mobile menus are often placed above the trigger (so they are not covered by user's hand). A callback variant of side/placement props could be useful here.

@@ -49,6 +50,8 @@ const MenuPopup = React.forwardRef(function MenuPopup(
onOpenChangeComplete,
} = useMenuRootContext();
const { side, align, floatingContext } = useMenuPositionerContext();
const contextMenuContext = useContextMenuRootContext();
const hasContextMenuParent = Boolean(contextMenuContext) && !nested;
Copy link
Member

Choose a reason for hiding this comment

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

In the Menubar PR I implemented a more universal solution to determine the menu's parent and its capabilities: https://github.com/mui/base-ui/pull/1684/files#diff-6da7b84ff007a487d62a9d48ba9fb32ad4b286ef666fd3d0419b14e9ebbe472a.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Context menus don't have any parents though, so I think this should suffice?

Copy link
Member

Choose a reason for hiding this comment

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

I'd like to avoid having all kinds of boolean values like nested, isInContextMenu, isInMenubar, (possibly) isInNavigationMenu. The approach I took in the Menubar PR lets a menu part know what kind of menu it's in in a standard way and provides a type-safe way to access the parent context (without having to check for its existence)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alright 👍 I'll wait for Menubar to be merged and then use its logic for Menu

@atomiks
Copy link
Contributor Author

atomiks commented Apr 23, 2025

A callback variant of side/placement props could be useful here.

This could also be used instead of useMediaQuery to determine what side to use in narrower viewports. Would be good if we found a robust solution to #817 though.

Signed-off-by: atomiks <cc.glows@gmail.com>
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Apr 23, 2025
@oliviertassinari oliviertassinari changed the title [ContextMenu] Create new ContextMenu component [context menu] Create new ContextMenu component Apr 30, 2025
@oliviertassinari
Copy link
Member

oliviertassinari commented Apr 30, 2025

From https://x.com/rsms/status/1522583516265029633, the click-drag-release flow doesn't work properly:

Screen.Recording.2025-05-01.at.01.07.20.mov

https://www.radix-ui.com/primitives/docs/components/context-menu, https://ariakit.org/examples/menu-context-menu don't support this correctly either. So maybe OK to ignore fore a v0


Great to see this, we will need this for 👍 mui/mui-x#12021

@oliviertassinari oliviertassinari added new feature New feature or request and removed component: menu labels Apr 30, 2025
Copy link

pkg-pr-new bot commented May 6, 2025

Open in StackBlitz

npm i https://pkg.pr.new/@base-ui-components/react@1665

commit: 0eb8abe

@ImSingee
Copy link

ImSingee commented May 8, 2025

Is it possible to stack two context menus? For example, can one context menu appear when clicking on a div and another when clicking outside of it?

I try to do it directly, but sadly it doesn't work:

https://codesandbox.io/p/sandbox/sweet-wave-h4lygt

image

I have two boxes here. Right-clicking the outer one displays the context menu as expected, but right-clicking the inner one does not show its context menu.

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label May 8, 2025
Signed-off-by: atomiks <cc.glows@gmail.com>
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label May 11, 2025
@atomiks atomiks force-pushed the feat/ContextMenu branch from af0da31 to cbfb825 Compare May 11, 2025 23:56
@atomiks atomiks force-pushed the feat/ContextMenu branch from cbfb825 to 96409ac Compare May 12, 2025 00:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[menu] Create Context Menu component
5 participants