VS Code Extension - How to add a WebviewPanel to the sidebar?
Asked Answered
C

4

8

According to this page webviews can be "rendered in the sidebar or panel areas". The examples show how to render as editor panels...

vscode.window.createWebviewPanel(
    'catCoding', // Identifies the type of the webview. Used internally
    'Cat Coding', // Title of the panel displayed to the user
    vscode.ViewColumn.One, // Editor column to show the new webview panel in.
    {} // Webview options..
);

I'm trying to render the webview as an additional panel in the sidebar under explorer.

I'm assuming some kind of change to the 3rd arg vscode.ViewColumn.One?

Corron answered 18/4, 2021 at 15:56 Comment(0)
C
12

@Gamma11, thanks for your answer. Definitely helped resolve the "labyrinth of definitions"

Elaborating that out a bit (and maybe simplifying/clarifying the webview-view-sample with a tighter JS (as opposed to TS) version):

1 - In package.json you have the following entry defining the view as a webview that lives in the sidebar explorer:

"views": {
    "explorer": [
        {
            "type": "webview",
            "id": "calicoColors.colorsView",
            "name": "Trillion Files"
        }
    ]
}

2 - Also in package.json the activation that sends to JS

"activationEvents": [
    "onView:calicoColors.colorsView"
]

3 - In JS the event is picked up by vscode.commands.registerCommand

function activate(context){
    var thisProvider={
        resolveWebviewView:function(thisWebview, thisWebviewContext, thisToken){
            thisWebviewView.webview.options={enableScripts:true}
            thisWebviewView.webview.html="<!doctype><html>[etc etc]";
        }
    };
    context.subscriptions.push(
        vscode.commands.registerWebviewViewProvider("calicoColors.colorView", thisProvider);
    );
}

function deactivate() { }

module.exports = {
    activate,
    deactivate
}

There are plenty more properties that can go into thisProvider, but this minimal code gets a panel up and running in the sidebar.

Corron answered 19/4, 2021 at 2:48 Comment(0)
K
11

It seems like createWebviewPanel() is actually only for webviews shown in the editor. For the side bar, you have to use registerWebviewViewProvider() as shown in the webview-view-sample linked on that page:

vscode.window.registerWebviewViewProvider('calicoColors.colorsView', provider));

And then specify which view to show it in via package.json - the example uses the Explorer:

{
    "contributes": {
        "views": {
            "explorer": [
                {
                    "type": "webview",
                    "id": "calicoColors.colorsView",
                    "name": "Calico Colors"
                }
            ]
        }
    }
}
Katheykathi answered 18/4, 2021 at 20:55 Comment(1)
So far, navigating the example code and API docs, it seems more like a labyrinth of circular definitions. You need to register a WebviewViewProvider, which in turn involves a WebviewViewProvider which in turn involves a WebviewView, which in turn involves a Webview. Haven't been able to glean which of those can or must be defined in the JS context, and which perhaps inherit their value from the the package.json.Corron
G
0

package.json

"viewsContainers": {
  "activitybar": [
    {
      "id": "ollamaContainer",
      "title": "Ollama",
      "icon": "media/icon.png"
    }
  ]
},
"views": {
  "ollamaContainer": [
    {
      "type": "webview",
      "id": "ollamaView",
      "name": "Ask ai chat"
    }
  ]
}

activityBar is where your container will be located. ViewsContainer: id: is how you tell your views where to render. title: Name displayed when hovering your extension icon. icon: The image displayed in the side bar.

Views: "ollamaContainer" in my example. This must match the id of your views container. type: (Set to tree node by default.) Must be set to webview otherwise you will get the following error: "There is no data provider registered that can provide view data." id: The id that must be called from extension inside of your activation function. name: Appears at the top of your side bar.

extension.ts

export async function activate(context: vscode.ExtensionContext) {
   context.subscriptions.push(
       vscode.window.registerWebviewViewProvider(
       "ollamaView",
       new MyWebviewViewProvider(context)
    )
  );
}


export class MyWebviewViewProvider implements vscode.WebviewViewProvider {
  constructor(private context: vscode.ExtensionContext) {}

  resolveWebviewView(
    webviewView: vscode.WebviewView,
    context: vscode.WebviewViewResolveContext,
    _token: vscode.CancellationToken
  ) {
    webviewView.webview.options = {
      enableScripts: true,
    };

    webviewView.webview.html = this.getWebviewContent();

    webviewView.webview.onDidReceiveMessage(async (message) => {
      switch (message.command) {
        case "showMessage":
          vscode.window.showInformationMessage(message.text);
          break;
      }
    });
  }

  getWebviewContent() {
    return `
            <!DOCTYPE html>
            <html>
            <body>
                <h1>Hello from Side Panel!</h1>
                <button onclick="sendMessage()">Send Message</button>
                <script>
                    const vscode = acquireVsCodeApi();
                    function sendMessage() {
                        vscode.postMessage({
                            command: 'showMessage',
                            text: 'Hello from Webview!'
                        });
                    }
                </script>
            </body>
            </html>
        `;
  }
}

This should be all you need in order to get a basic webview in your project started.

Glove answered 18/8, 2024 at 15:54 Comment(0)
I
-1

use vscode.ViewColumn.Beside for show on the side bar

this is how viewColumn is used

export enum ViewColumn {
        /**
         * A *symbolic* editor column representing the currently active column. This value
         * can be used when opening editors, but the *resolved* {@link TextEditor.viewColumn viewColumn}-value
         * of editors will always be `One`, `Two`, `Three`,... or `undefined` but never `Active`.
         */
        Active = -1,
        /**
         * A *symbolic* editor column representing the column to the side of the active one. This value
         * can be used when opening editors, but the *resolved* {@link TextEditor.viewColumn viewColumn}-value
         * of editors will always be `One`, `Two`, `Three`,... or `undefined` but never `Beside`.
         */
        Beside = -2,
        /**
         * The first editor column.
         */
        One = 1,
        /**
         * The second editor column.
         */
        Two = 2,
        /**
         * The third editor column.
         */
        Three = 3,
        /**
         * The fourth editor column.
         */
        Four = 4,
        /**
         * The fifth editor column.
         */
        Five = 5,
        /**
         * The sixth editor column.
         */
        Six = 6,
        /**
         * The seventh editor column.
         */
        Seven = 7,
        /**
         * The eighth editor column.
         */
        Eight = 8,
        /**
         * The ninth editor column.
         */
        Nine = 9
    }
Ingeborg answered 1/2, 2023 at 3:26 Comment(3)
It's great that you're giving a detailed explanation of the enum governing position, but could you expand on this a bit to show how this would go into defining a WebviewPanel config? It would be a more complete answer and help illustrate specifically how this is done.Lowrey
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Enright
'vscode.ViewColumn.Beside' is not for the side bar, but the edit column beside the active one.Tallow

© 2022 - 2025 — McMap. All rights reserved.