Skip to content

ContextMenu2 migration

Adi Dahiya edited this page Feb 14, 2023 · 9 revisions

Requirements

  • ContextMenu2 APIs are available in the @blueprintjs/popover2 package, so make sure to check out the Popover2 migration guide in addition to this guide.

ContextMenu2

Compared to <ContextMenu> and @ContextMenuTarget, the new component <ContextMenu2> has been simplified greatly so that it works much more like a popover. It does not require your build system to support decorators and it can be used with function components. It wraps a target element which will receive contextmenu events (right click) and expects menu content supplied as a prop:

import { Menu, MenuItem } from "@blueprintjs/core";
import { ContextMenu2 } from "@blueprintjs/popover2";

export default function ContextMenuExample() {
    return (
        <ContextMenu2
            content={
                <Menu>
                    <MenuItem text="Save" />
                    <MenuItem text="Save as..." />
                    <MenuItem text="Delete..." intent="danger" />
                </Menu>
            }
        >
            <div className="my-context-menu-target">
                Right click me!
            </div>
        </ContextMenu2>
    );
}

See the component documentation page for more details.

ContextMenu2Popover

We've also exposed a lower-level component API for ContextMenu2 called <ContextMenu2Popover> which encapsulates some of the opinionated popover implementation of <ContextMenu2> into a declarative component API.

It's lower-level than <ContextMenu2> since users have to hook up onContextMenu event handlers and cancel the default context menu themselves with e.preventDefault(), but this does offer a good declarative alternative to the deprecated ContextMenu.show() imperative API.

See documentation here.

showContextMenu & hideContextMenu imperative APIs

Finally, the popover2 package offers two imperative APIs for interacting with <ContextMenu2Popover>. These functions are provided as a convenience to make it easy to migrate to Blueprint v5. Note that these rely on ⚠️ global state ⚠️ stored in Blueprint library code.

Migration from ContextMenu.show()

These APIs provided the simplest migration path from ContextMenu.show():

- import { ContextMenu, Menu, MenuItem } from "@blueprintjs/core";
+ import { Menu, MenuItem } from "@blueprintjs/core";
+ import { showContextMenu, hideContextMenu } from "@blueprintjs/popover2";

const menu = (
  <Menu>
    <MenuItem text="first" />
    {/* more items... */}
-     <MenuItem text="close" onClick={() => ContextMenu.hide()} />
+     <MenuItem text="close" onClick={hideContextMenu} />
  </Menu>
);

function MyComponent() {
  const handleContextMenuClosed = React.useCallback(() => {
    console.info("closed context menu");
  }, []);
  const handleContextMenu = React.useCallback((event: React.MouseEvent<HTMLElement) => {
    event.preventDefault();
-     ContextMenu.show(menu, { left: e.clientX, top: e.clientY }, handleContextMenuClosed);
+     showContextMenu({
+       content: menu,
+       targetOffset: {
+         left: e.clientX,
+         top: e.clientY
+       },
+       onClose: handleContextMenuClosed,
+     });
  }, []);

  return (
    <div onContextMenu={handleContextMenu}>
      {/* interactive content */}
    </div>
  );
}

See documentation for the imperative APIs here.

Clone this wiki locally