Skip to content

Views

Views are an important part of a VSCode extension. There are two types of views in VSCode: Tree View and Webview. Please read the official UX guidelines for a basic understanding.

Define in Manifest Non-Proprietary

As described in the official documentation, first, you need view containers to be defined in the contributes.viewsContainers.[viewContainerType] section in the package.json. Then you can define your views in the contributes.views.[viewContainerId] section.

json
{
  "contributes": {
    "viewsContainers": {
      "activitybar": [
        {
          "id": "package-explorer",
          "title": "Package Explorer",
          "icon": "resources/package-explorer.svg"
        }
      ]
    },
    "views": {
      "package-explorer": [
        {
          "id": "package-dependencies",
          "name": "Dependencies"
        },
        {
          "id": "package-outline",
          "name": "Outline"
        }
      ]
    }
  }
}

Custom views container

Register Tree View

Tree views are used to display hierarchical data. You can define a tree view by using the useTreeView function.

Here is an example of a tree view:

ts
import type { TreeViewNode } from 'reactive-vscode'
import { 
computed
,
createSingletonComposable
,
useTreeView
} from 'reactive-vscode'
import {
TreeItemCollapsibleState
} from 'vscode'
export const
useDemoTreeView
=
createSingletonComposable
(() => {
function
getRootNode
(
index
: number) {
return {
children
: [
getChildNode
(
index
* 10 + 1),
getChildNode
(
index
* 10 + 2),
],
treeItem
: {
label
: `Root ${
index
}`,
collapsibleState
:
TreeItemCollapsibleState
.
Expanded
,
}, } } function
getChildNode
(
index
: number) {
return {
treeItem
: {
label
: `Child ${
index
}`,
collapsibleState
:
TreeItemCollapsibleState
.
None
,
}, } } const
treeData
=
computed
(() => {
const
roots
: TreeViewNode[] = []
for (let
i
= 1;
i
< 5;
i
++)
roots
.
push
(
getRootNode
(
i
))
return
roots
}) const
view
=
useTreeView
(
'reactive-tree-view',
treeData
,
{
title
: () => `Tree with ${
treeData
.
value
.
length
} roots`,
}, ) // return anything you want to expose return
view
})

Then you can call the useDemoTreeView function every where to register the tree view and get the returned value:

ts
import { 
defineExtension
} from 'reactive-vscode'
import {
useDemoTreeView
} from './treeView'
export =
defineExtension
(() => {
const
demoTreeView
=
useDemoTreeView
()
// ... })

The children property in nodes is used to define the children of the node. The treeItem property is required and is used to define the tree item of the node. It should be a TreeItem object, or a promise that resolves to a TreeItem object.

If you want to trigger an update based on some reactive values that aren't tracked in treeData, you can pass them to the watchSource option.

About createSingletonComposablecreateSingletonComposable is a helper function to create a singleton composable. It will only create the composable once and return the same instance every time it is called.

WARNING

For the above example, useDemoTreeView should not be called at the top-level in the module, because the extension context is not available at that time. Instead, you should always call it in the setup function.

Register Webview

Webviews are used to display web content in the editor. You can define a webview by using the useWebviewView function.

Here is an example of a webview:

ts
import { 
computed
,
createSingletonComposable
,
ref
,
useWebviewView
} from 'reactive-vscode'
export const
useDemoWebviewView
=
createSingletonComposable
(() => {
const
message
=
ref
('')
const
html
=
computed
(() => `
<script> vscode = acquireVsCodeApi() function updateMessage() { vscode.postMessage({ type: 'updateMessage', message: document.querySelector('input').value, }) } </script> <p>${
message
.
value
}</p>
<div style="display:flex; flex-wrap:wrap;"> <input type="text" placeholder="Input Message" /> <button onclick="updateMessage()">Update Message</button> </div> `) const {
postMessage
} =
useWebviewView
(
'reactive-webview-view',
html
,
{
webviewOptions
: {
enableScripts
: true,
enableCommandUris
: true,
},
onDidReceiveMessage
(
ev
) {
if (
ev
.type === 'updateMessage')
message
.
value
=
ev
.message
}, }, ) return {
message
,
postMessage
}
})

The time to call useDemoWebviewView is the same as the tree view in the previous section.

There is also useWebviewPanel composable to create a webview panel. The usage is similar to useWebviewView.