Skip to content

Sidebar

sachin soman edited this page Feb 16, 2021 · 2 revisions

SideBar

Webview is bit of an overkill most of the time so we will make a sidebar.

We need to go to package.json and tell that we are going to add a sidebar. So we going to tell vscode that we going to add the sidebar view.

   "contributes": {
		"viewsContainers": {
			"activitybar": [
			  {
				"id": "todo-sidebar-view",
				"title": "todo",
				"icon": "media/heart.svg"
			  }
			]
		  },
		  "views": {
			"todo-sidebar-view": [
			  {
				"type": "webview",
				"id": "todo-sidebar",
				"name": "todo",
				"icon": "media/heart.svg",
				"contextualTitle": "todo"
			  }
			]
		  },

So in contributes add these. Change the things which are obvious in the setting like the names and stuff.

Now add an activationEvents as well so it will be

"activationEvents": [
		"onCommand:todo.helloWorld",
		"onCommand:todo.askQuestion",
		"onCommand:todo.welp",
		"onCommand:todo.refresh",
		"onView:todo-sidebar"     <-------
	],

The name put in activationEvent must match the id of the sidebar view so in our case

"todo-sidebar-view": [
			  {
				"type": "webview",
				"id": "todo-sidebar",------> "Match this"
				"name": "todo",
				"icon": "media/heart.svg",
				"contextualTitle": "todo"
			  }

Let'start of by making an icon go to codicon and there find the name of the icon you want to use and then go to their github account. Go to src → icons → and grab the appropriate svg

Screenshot_2021-02-16_at_00 43 21

Now go to the media folder and add a file called checklist.svg and add the source there.

Now go to package.json and and change "icon" :"media/checklist.svg" both in viewsContainer and views

"viewsContainers": {
			"activitybar": [
				{
					"id": "todo-sidebar-view",
					"title": "todo",
					"icon": "media/checklist.svg"   <----
				}
			]
		},
		"views": {
			"todo-sidebar-view": [
				{
					"type": "webview",
					"id": "todo-sidebar",
					"name": "todo",
					"icon": "media/checklist.svg",   <-----
					"contextualTitle": "todo"
				}
			]

Now we go to extension.ts and initialise the view and register it. So type the following.

const sidebarProvider = new SidebarProvider(context.extensionUri);
	context.subscriptions.push(
		vscode.window.registerWebviewViewProvider(
			"todo-sidebar",
			sidebarProvider
		)
	);

make sure the name matches the id provided in package.json views id in our case its "todo-sidebar"

Now lets make the actual SideBarProvider itself. Lots of boilerplate and stuff. So here is 'SidebarProvider.ts'

import * as vscode from "vscode";
import { getNonce } from "./getNonce";

export class SidebarProvider implements vscode.WebviewViewProvider {
    _view?: vscode.WebviewView;
    _doc?: vscode.TextDocument;

    constructor(private readonly _extensionUri: vscode.Uri) { }

    public resolveWebviewView(webviewView: vscode.WebviewView) {
        this._view = webviewView;

        webviewView.webview.options = {
            // Allow scripts in the webview
            enableScripts: true,

            localResourceRoots: [this._extensionUri],
        };

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

        webviewView.webview.onDidReceiveMessage(async (data) => {
            switch (data.type) {

                case "onInfo": {
                    if (!data.value) {
                        return;
                    }
                    vscode.window.showInformationMessage(data.value);
                    break;
                }
                case "onError": {
                    if (!data.value) {
                        return;
                    }
                    vscode.window.showErrorMessage(data.value);
                    break;
                }
            }
        });
    }

    public revive(panel: vscode.WebviewView) {
        this._view = panel;
    }

    private _getHtmlForWebview(webview: vscode.Webview) {
        const styleResetUri = webview.asWebviewUri(
            vscode.Uri.joinPath(this._extensionUri, "media", "reset.css")
        );

        const styleVSCodeUri = webview.asWebviewUri(
            vscode.Uri.joinPath(this._extensionUri, "media", "vscode.css")
        );

        const scriptUri = webview.asWebviewUri(
            vscode.Uri.joinPath(this._extensionUri, "out", "compiled/sidebar.js")
        );
        const styleMainUri = webview.asWebviewUri(
            vscode.Uri.joinPath(this._extensionUri, "out", "compiled/sidebar.css")
        );

        // Use a nonce to only allow a specific script to be run.
        const nonce = getNonce();

        return `<!DOCTYPE html>
			<html lang="en">
			<head>
				<meta charset="UTF-8">
				<!--
					Use a content security policy to only allow loading images from https or from our extension directory,
					and only allow scripts that have a specific nonce.
        -->
        <meta http-equiv="Content-Security-Policy" content="img-src https: data:; style-src 'unsafe-inline' ${webview.cspSource
            }; script-src 'nonce-${nonce}';">
				<meta name="viewport" content="width=device-width, initial-scale=1.0">
				<link href="${styleResetUri}" rel="stylesheet">
				<link href="${styleVSCodeUri}" rel="stylesheet">
        <link href="${styleMainUri}" rel="stylesheet">
			</head>
      <body>
				<script nonce="${nonce}" src="${scriptUri}"></script>
			</body>
			</html>`;
    }
}

Now if we restart everything and run we will see a sidebar yay!!!

FYI make sure to import sidebar in extension.ts as well

Now lets add Js and CSS for the sidebar so that we can render stuff.

So make a file called 'sidebar.ts' in webviews/pages

and inside have the following piece of code

import App from "../components/Sidebar.svelte"

const app = new App({
    target: document.body,
});

export default app;

Next in components fo make a 'Sidebar.svelte' and maybe add a small <h1> tag with some content and a style tag like <style> div{color:pink}</style> and run npm watch to compile new files now in out/compiled there will css and js files.

So new versions of rollup will not generate css so you can use this versions "rollup": "^2.3.4", "rollup-plugin-svelte": "^6.0.0", change the version number in package.json and do npm install again. Or there seems to be other method which will be linked) here

Now we can again setup the shortcut workflow where we can open and close the side bar for that if we open the command pallet and type open sidebar and click on cog, then right click to get the command ID

so to view stuff in extnesions we can do this

Screenshot_2021-02-16_at_05 03 28

get the command ID for show todo

then update code like this( self explanatory) change per requirements in extension.ts

context.subscriptions.push(
		vscode.commands.registerCommand("todo.refresh", async () => {
			// HelloWorldPanel.kill();
			// HelloWorldPanel.createOrShow(context.extensionUri);
			await vscode.commands.executeCommand("workbench.action.closeSidebar");
			await vscode.commands.executeCommand("workbench.view.extension.todo-sidebar-view");
			setTimeout(() => {
				vscode.commands.executeCommand("workbench.action.webview.openDeveloperTools");
			}, 500);
		})
	);

Now just run the program and press hotkey to toggle it

Clone this wiki locally