Overview
The Vertical Tabs plugin emits several workspace events that your plugin can listen to. These events notify you of plugin lifecycle changes, metadata updates, workspace refresh operations, and icon rendering.
Plugin lifecycle
Load event
Fired when the Vertical Tabs plugin loads and the API becomes available:
this.registerEvent(
this.app.workspace.on("vertical-tabs:load", () => {
console.log("Vertical Tabs is ready");
const vtPlugin = this.app.plugins.getPlugin("vertical-tabs");
// API is now available
})
);Unload event
Fired when the Vertical Tabs plugin is about to unload:
this.registerEvent(
this.app.workspace.on("vertical-tabs:unload", () => {
console.log("Vertical Tabs is unloading");
// Clean up any references to the API
})
);Important: For robust integration that handles load and unload correctly, see Safe API Access.
Metadata changes
Fired when tab or group metadata is changed through the API:
this.registerEvent(
this.app.workspace.on("vertical-tabs:metadata-changed", (event) => {
console.log("Type:", event.type); // "tab" or "group"
console.log("ID:", event.id); // Identifier
console.log("Source:", event.source); // Optional plugin identifier
console.log("Metadata:", event.metadata);
})
);Event data:
interface MetadataChangeEvent {
type: "tab" | "group";
id: string;
metadata: APITabMetadata | APIGroupMetadata;
source?: string;
}Preventing infinite loops:
When listening to metadata changes and making changes in response, always check the source parameter to avoid infinite loops:
this.registerEvent(
this.app.workspace.on("vertical-tabs:metadata-changed", (event) => {
// Ignore changes made by this plugin
if (event.source === "my-plugin") return;
// React to changes from other sources
if (event.type === "tab") {
console.log("Tab metadata changed:", event.id);
}
})
);
// When making changes, provide source identifier
await api.setTabIcon(leaf.id, "star", "my-plugin");Workspace refresh
Fired when tabs or groups are opened or closed. The event provides details about which tabs and groups were added or removed:
this.registerEvent(
this.app.workspace.on("vertical-tabs:refresh", (event) => {
console.log("New tabs:", event.newTabs);
console.log("Closed tabs:", event.closedTabs);
console.log("New groups:", event.newGroups);
console.log("Closed groups:", event.closedGroups);
})
);Event data:
interface RefreshEvent {
newTabs: string[]; // IDs of newly opened tabs
newGroups: string[]; // IDs of newly created groups
closedTabs: string[]; // IDs of closed tabs
closedGroups: string[]; // IDs of closed groups
}Important: This event only fires when changes are detected. If no tabs or groups were opened or closed during a refresh operation, the event will not fire.
Use cases:
- Track workspace state changes
- React to new tabs being opened
- Clean up when tabs are closed
- Monitor group creation and deletion
this.registerEvent(
this.app.workspace.on("vertical-tabs:refresh", (event) => {
// Initialize metadata for new tabs
for (const tabId of event.newTabs) {
await api.setTabIcon(tabId, "file-text", "my-plugin");
}
// Clean up data for closed tabs
for (const tabId of event.closedTabs) {
this.cleanupTabData(tabId);
}
})
);Icon rendering
VERSION
Available since: API v1.3.0, Vertical Tabs v0.26.3
Fired after Vertical Tabs paints a sidebar icon slot, so another plugin can mutate the DOM. These events are not part of VerticalTabsAPI. See Icon Rendering for the full guide.
this.registerEvent(
this.app.workspace.on("vertical-tabs:render-tab-icon", (leaf, iconEl, tabEl) => {
// Paint iconEl for this leaf
})
);
this.registerEvent(
this.app.workspace.on("vertical-tabs:render-group-icon", (group, iconEl, groupEl) => {
// Paint iconEl for this group
})
);
this.app.workspace.trigger("vertical-tabs:request-icon-refresh");vertical-tabs:request-icon-refresh asks Vertical Tabs to re-paint every visible tab and group icon. Trigger it after you register listeners (if Vertical Tabs may already be running) and whenever your icon data changes.
If Vertical Tabs is not installed or not enabled, these events will not be available; no one will emit or respond to them.
Event registration
Always use registerEvent to ensure events are properly cleaned up when your plugin unloads:
export default class MyPlugin extends Plugin {
async onload() {
// Register all events using this.registerEvent
this.registerEvent(
this.app.workspace.on("vertical-tabs:load", () => {
// Handle load
})
);
}
// Events are automatically cleaned up on unload
}