Docs / Guides
Sidebar views
An extension can add its own icon to the activity bar (the column of icons on the left) and fill the sidebar with views: a tree of items it supplies, or a page of HTML. Typical uses are an outline, a list of tasks or bookmarks, a scripts runner, a notes pad or a set of buttons.
Sidebar views arrived with extension API level 0.1.1: an extension that uses them should say "engines": { "ferrum": "^0.1.1" }. Views need no permission of their own. What the extension does inside them (reading files, running commands) needs the permission it always needed.
Declare it in ferrum.json
{
"activationEvents": ["onView:todo.items"],
"contributes": {
"viewsContainers": [
{ "id": "todo", "title": "TODO", "icon": "checklist" }
],
"views": [
{ "id": "todo.items", "name": "Items", "container": "todo", "type": "tree" }
],
"commands": [
{ "command": "todo.openAt", "title": "Open TODO", "hidden": true }
]
}
}
| Key | Description |
|---|---|
viewsContainers[].id |
Lower case letters, digits and dashes. Up to 3 containers per extension. |
viewsContainers[].title |
The heading of the sidebar and the tooltip of the icon (30 characters at most). |
viewsContainers[].icon |
A Codicon name such as checklist, bookmark, package, symbol-class, history. |
views[].id |
3 to 80 letters, digits, dots, dashes or underscores. Up to 6 views per extension. |
views[].name |
The section title (40 characters at most). |
views[].container |
The id of one of your containers. |
views[].type |
tree (default) or html. |
commands[].hidden |
true keeps a command out of the command palette. Use it for commands that exist only to be run by a click in a tree. |
The icon appears as soon as the extension is installed and turned on, even before your code runs. When the person opens the container, Ferrum starts your extension if it lists onView:<view id> in activationEvents (or onStartup). A container also gets the palette command View: Show <title>.
In Restricted Mode the container is shown but its views say that the folder must be trusted, because extension code does not run there.
Tree views
exports.activate = function (context) {
const view = ferrum.window.registerTreeView('todo.items', {
// Called for the top level (element is undefined) and again for an item that is opened.
async getChildren(element) {
if (!element) {
return [
{ id: 'f:a.js', label: 'a.js', description: '2', icon: 'file', collapsible: 'expanded' },
{ id: 'f:b.js', label: 'b.js', description: '1', icon: 'file', collapsible: 'collapsed' },
];
}
return [{ id: element.id + ':1', label: 'fix this', icon: 'circle-filled', color: '#3b82f6', command: 'todo.openAt', args: ['a.js', 1] }];
},
});
context.subscriptions.push(view);
context.subscriptions.push(
ferrum.commands.register('todo.openAt', (file, line) => ferrum.editor.openFile(file, { line, col: 0 })),
);
};
registerTreeView(viewId, provider) returns a handle:
| Member | Description |
|---|---|
refresh() |
Asks Ferrum to call getChildren again. Call it when your data changed (a file was saved, a scan finished). |
setBadge(n) |
A count shown on the section and on the activity bar icon. 0 or undefined removes it. |
setTitle(text) |
Changes the section title. |
dispose() |
Removes the view. |
getChildren(element) may return an array or a promise of one. element is the same item object you returned earlier. Ferrum asks for the children of an item only when it is opened.
Items
| Key | Description |
|---|---|
id |
Required. Unique among your items. Used to ask for children. |
label |
Required. The text. |
description |
Dimmer text after the label. |
tooltip |
Text on hover. |
icon |
A Codicon name. |
color |
The icon's color, or the label's if there is no icon (same colors as decorations). |
collapsible |
none (default), collapsed or expanded. |
command |
A command to run when the item is clicked: one of yours (declare it in contributes.commands, use hidden: true to keep it out of the palette) or an editor command. |
args |
A list of JSON values passed to the command (2 KB at most). |
Up to 2,000 items per level. A slow getChildren is stopped after 30 seconds.
HTML views
const page = ferrum.window.registerHtmlView('notes.page', {
html: '<h3>Notes</h3><textarea id="t"></textarea><script>/* ... */</script>',
});
page.onMessage((m) => { /* messages from the page */ });
page.postMessage({ type: 'saved' }); // to the page
page.setHtml('<p>New content</p>');
page.setBadge(3);
The page works exactly like a panel: a locked frame, the ferrumPanel.postMessage and ferrumPanel.onMessage bridge, the editor's colors as CSS variables, no network. It is simply shown in the sidebar instead of in a tab. When the person switches to another sidebar view and comes back, the page is built again from the last HTML you gave it, so keep what matters in ferrum.storage and send it to the page when it starts.
Things to know
- A view must be declared in
ferrum.jsonbefore you register it:registerTreeView('x')fails ifxis not incontributes.views, or if itstypedoes not match. - Register your views in
activate, so they are ready when the sidebar asks. - The views of an extension disappear when it is turned off or stops.
- Selecting a tree item runs its
command; opening and closing is handled by Ferrum.
Examples
Official extensions that use views: Outline Lite (a tree of the open file), Bookmarks and TODO Tree (grouped trees), NPM Scripts (click to run), Recent Files (remembered between sessions), Quick Notes and Git Quick Actions (HTML pages).