microsoft/vscode

Contributed webview context menu actions

mjbvz opened this issue ยท 17 comments

mjbvz commented

Feature request
Allow extensions to contribute to the context menu in a webview

(From FB meeting)

Any update on this issue? It's been on the backlog for quite a while now.

I've also thought about creating this request. Right now extensions need to build their own context menu widget which is obviously a pain and even done perfectly would look out of place on mac since it uses native menus.

My idea is adding an API that wraps Electron's Menu.popup and opens a context menu at the specified position to vscode.window.

  const template = [
    {
      label: 'Menu Item 1',
      click: () => { console.log('click') }
    },
    { type: 'separator' },
    { label: 'Menu Item 2', type: 'checkbox', checked: true }
  ]
  vscode.window.openContextMenu(position, template)

When you want to open a custom context menu instead of the default one, you colud preventDefault contextmenu event and use vscode.window.openContextMenu instead.

Would love to get some updates on this as well. Thanks!

gar1t commented

Some of the duplicate issues listed above refer to custom editors. This issue seems to be limited to web views. It would be helpful to either include custom editors in the title here.

I would argue that the custom view/editor support in the extension API is incomplete without context menu support. The default context menu with Copy, Cut, and Paste may not make sense for a custom interface (not to mention appears not to work - I can provide details if needed). VS Code is too mature IMO to have this functionality omitted at this point.

Does this work and if so how? I can't seem to find any documentation for it. If i've contributed my own webview to the debug context for instance, how do I provide a context menu for that web view?

Another vote for this.

Right now I'm using CSS/Javascript to create a context menu, but the context menu can't leave the webview render space, so in small windows the context menu is rather limited.

I would really love to have this as well -- even if menus were a part of the https://github.com/microsoft/vscode-webview-ui-toolkit (/cc @daviddossett @hawkticehurst) that would only help for custom menus, and as other have mentioned we'd still be bound to the webview box as well, which is certainly not ideal.

@mjbvz is something like this in the cards?

@eamodio FYI we're tracking that here but would also prefer this to come from core.

@daviddossett definitely, I don't think effort in the webview toolkit would be worth it, and then you'd be stuck with an inferior version of the menu when this does happen.

Here is another vote for having this feature supported natively.

FYI, I've started a draft PR to get this working -- would love feedback: #154524 (comment)

mjbvz commented

Reopening to track finalizing

mjbvz commented

We held off on finalizing this last iteration so that we could think about how extensions could pass data to contributed webview context menu commands. A motivating use case: passing the value of a text input back to an extension

I considered two approaches to this:

data-vscode-context-arg

The first option would use an additional data attribute (such as data-vscode-context-arg) to pass along arguments:

<div data-vscode-context='{ "my-context": "test" }'>
     <div data-vscode-context-arg='["custom", "data", 123]'></div>
</div>

If the user right clicks on the inner div, any context menu commands would be passed ["custom", "data", 123] as the first argument.

This has the benifit of working even if scripts are disabled.

The downside is that extensions have to mutate the dom to pass along dynamic data. You could either do this eagerly (such as updating data-vscode-context-arg when the user types in an input box), or try to do the dom mutation dynamically when the contextmenu event is fired

Pass along custom data on the context menu event

The second option is to allow extensions to pass data back on the contextmenu event itself:

el.addEventListener('contextmenu', e => {
    // Use a custom symbol to store the new property
    e[vscode.contextMenuArgSymbol] = ["custom", "data", 123];

   // This custom data can then be read by VS Code if the event propagates back to our contextmenu event handlers
});

This upside to this is that it's clearer that the data is only needed when the event is fired. It also get around some somewhat tricky questions about how data-vscode-context-arg would propagate in the dom (do child nodes inherit the value of their parent? Do we merge it like we do with data-vscode-context?)

The downside is that it requires scripts to be enabled


For either case, I'm now confident we could add this functionality after finalizing the current api. We should be good to finalize the api as it stands this iteration

@mjbvz When building this I had a very similar thought to data-vscode-context-arg (I called it data-vscode-context-menu-value in some initial prototypes), but I ultimately left it out, because while it would semantically separate the context from callback specific data, it didn't feel like it was needed -- since we were already providing the context to the callback (which is important).

Given that, I definitely like your 2nd proposal to allow custom args to be added into the context menu event as that feels different and provides an alternative method that isn't possible with the DOM attr approach. But also agree that this type of added functionality could be layered on top of the existing proposal.

๐ŸŽ‰ Woo! Thanks @mjbvz!