diff --git a/package-lock.json b/package-lock.json
index 0e6f871e..fecfb261 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -62,6 +62,7 @@
"posthog-node": "^4.8.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
+ "react-tooltip": "^5.28.0",
"tas-client-umd": "0.2.0",
"v8-inspect-profiler": "^0.1.1",
"vscode-html-languageservice": "^5.3.1",
@@ -6621,6 +6622,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
+ "license": "MIT"
+ },
"node_modules/cli-cursor": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
@@ -17999,6 +18006,20 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
+ "node_modules/react-tooltip": {
+ "version": "5.28.0",
+ "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.28.0.tgz",
+ "integrity": "sha512-R5cO3JPPXk6FRbBHMO0rI9nkUG/JKfalBSQfZedZYzmqaZQgq7GLzF8vcCWx6IhUCKg0yPqJhXIzmIO5ff15xg==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.6.1",
+ "classnames": "^2.3.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.14.0",
+ "react-dom": ">=16.14.0"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
diff --git a/package.json b/package.json
index f1faef9f..6ce28572 100644
--- a/package.json
+++ b/package.json
@@ -123,6 +123,7 @@
"posthog-node": "^4.8.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
+ "react-tooltip": "^5.28.0",
"tas-client-umd": "0.2.0",
"v8-inspect-profiler": "^0.1.1",
"vscode-html-languageservice": "^5.3.1",
diff --git a/src/vs/workbench/contrib/void/browser/react/src/void-tooltip/VoidTooltip.tsx b/src/vs/workbench/contrib/void/browser/react/src/void-tooltip/VoidTooltip.tsx
new file mode 100644
index 00000000..21f80ed9
--- /dev/null
+++ b/src/vs/workbench/contrib/void/browser/react/src/void-tooltip/VoidTooltip.tsx
@@ -0,0 +1,64 @@
+/*--------------------------------------------------------------------------------------
+ * Copyright 2025 Glass Devtools, Inc. All rights reserved.
+ * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
+ *--------------------------------------------------------------------------------------*/
+
+import { Tooltip } from 'react-tooltip';
+import 'react-tooltip/dist/react-tooltip.css';
+
+/**
+ * Creates a configured global tooltip component with consistent styling
+ * To use:
+ * 1. Mount a Tooltip with some id eg id='void-tooltip'
+ * 2. Add data-tooltip-id="void-tooltip" and data-tooltip-content="Your tooltip text" to any element
+ */
+export const VoidTooltip = () => {
+ return (
+
+ // use native colors so we don't have to worry about @@void-scope styles
+ // --void-bg-1: var(--vscode-input-background);
+ // --void-bg-1-alt: var(--vscode-badge-background);
+ // --void-bg-2: var(--vscode-sideBar-background);
+ // --void-bg-2-alt: color-mix(in srgb, var(--vscode-sideBar-background) 30%, var(--vscode-editor-background) 70%);
+ // --void-bg-3: var(--vscode-editor-background);
+
+ // --void-fg-0: color-mix(in srgb, var(--vscode-tab-activeForeground) 90%, black 10%);
+ // --void-fg-1: var(--vscode-editor-foreground);
+ // --void-fg-2: var(--vscode-input-foreground);
+ // --void-fg-3: var(--vscode-input-placeholderForeground);
+ // /* --void-fg-4: var(--vscode-tab-inactiveForeground); */
+ // --void-fg-4: var(--vscode-list-deemphasizedForeground);
+
+ // --void-warning: var(--vscode-charts-yellow);
+
+ // --void-border-1: var(--vscode-commandCenter-activeBorder);
+ // --void-border-2: var(--vscode-commandCenter-border);
+ // --void-border-3: var(--vscode-commandCenter-inactiveBorder);
+ // --void-border-4: var(--vscode-editorGroup-border);
+
+ <>
+
+
+
+
+ >
+ );
+};
diff --git a/src/vs/workbench/contrib/void/browser/react/src/void-tooltip/index.tsx b/src/vs/workbench/contrib/void/browser/react/src/void-tooltip/index.tsx
new file mode 100644
index 00000000..f51adfe6
--- /dev/null
+++ b/src/vs/workbench/contrib/void/browser/react/src/void-tooltip/index.tsx
@@ -0,0 +1,9 @@
+/*--------------------------------------------------------------------------------------
+ * Copyright 2025 Glass Devtools, Inc. All rights reserved.
+ * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
+ *--------------------------------------------------------------------------------------*/
+
+import { mountFnGenerator } from '../util/mountFnGenerator.js'
+import { VoidTooltip } from './VoidTooltip.js'
+
+export const mountVoidTooltip = mountFnGenerator(VoidTooltip)
diff --git a/src/vs/workbench/contrib/void/browser/react/tsup.config.js b/src/vs/workbench/contrib/void/browser/react/tsup.config.js
index 82dae1d9..be66a10b 100644
--- a/src/vs/workbench/contrib/void/browser/react/tsup.config.js
+++ b/src/vs/workbench/contrib/void/browser/react/tsup.config.js
@@ -10,6 +10,7 @@ export default defineConfig({
'./src2/void-editor-widgets-tsx/index.tsx',
'./src2/sidebar-tsx/index.tsx',
'./src2/void-settings-tsx/index.tsx',
+ './src2/void-tooltip/index.tsx',
'./src2/quick-edit-tsx/index.tsx',
'./src2/diff/index.tsx',
],
diff --git a/src/vs/workbench/contrib/void/browser/sidebarPane.ts b/src/vs/workbench/contrib/void/browser/sidebarPane.ts
index 1fe2e88a..803b2b8b 100644
--- a/src/vs/workbench/contrib/void/browser/sidebarPane.ts
+++ b/src/vs/workbench/contrib/void/browser/sidebarPane.ts
@@ -108,7 +108,7 @@ export const VOID_VIEW_ID = VOID_VIEW_CONTAINER_ID
const viewContainerRegistry = Registry.as(ViewContainerExtensions.ViewContainersRegistry);
const container = viewContainerRegistry.registerViewContainer({
id: VOID_VIEW_CONTAINER_ID,
- title: nls.localize2('voidContainer', 'Void Chat'), // this is used to say "Void" (Ctrl + L)
+ title: nls.localize2('voidContainer', 'Chat'), // this is used to say "Void" (Ctrl + L)
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [VOID_VIEW_CONTAINER_ID, {
mergeViewWithContainerWhenSingleView: true,
orientation: Orientation.HORIZONTAL,
diff --git a/src/vs/workbench/contrib/void/browser/tooltipService.ts b/src/vs/workbench/contrib/void/browser/tooltipService.ts
new file mode 100644
index 00000000..2bd64251
--- /dev/null
+++ b/src/vs/workbench/contrib/void/browser/tooltipService.ts
@@ -0,0 +1,55 @@
+/*--------------------------------------------------------------------------------------
+ * Copyright 2025 Glass Devtools, Inc. All rights reserved.
+ * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
+ *--------------------------------------------------------------------------------------*/
+
+import { Disposable, toDisposable } from '../../../../base/common/lifecycle.js';
+import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
+import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
+import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js';
+import { mountVoidTooltip } from './react/out/void-tooltip/index.js';
+import { h, getActiveWindow } from '../../../../base/browser/dom.js';
+
+// Tooltip contribution that mounts the component at startup
+export class TooltipContribution extends Disposable implements IWorkbenchContribution {
+ static readonly ID = 'workbench.contrib.voidTooltip';
+
+ constructor(
+ @IInstantiationService private readonly instantiationService: IInstantiationService,
+ ) {
+ super();
+ this.initializeTooltip();
+ }
+
+ private initializeTooltip(): void {
+ // Get the active window reference for multi-window support
+ const targetWindow = getActiveWindow();
+
+ // Find the monaco-workbench element using the proper window reference
+ const workbench = targetWindow.document.querySelector('.monaco-workbench');
+
+ if (workbench) {
+ // Create a container element for the tooltip using h function
+ const tooltipContainer = h('div.void-tooltip-container').root;
+ workbench.appendChild(tooltipContainer);
+
+ // Mount the React component
+ this.instantiationService.invokeFunction((accessor: ServicesAccessor) => {
+ const result = mountVoidTooltip(tooltipContainer, accessor);
+ if (result && typeof result.dispose === 'function') {
+ this._register(toDisposable(result.dispose));
+ }
+ });
+
+ // Register cleanup for the DOM element
+ this._register(toDisposable(() => {
+ if (tooltipContainer.parentElement) {
+ tooltipContainer.parentElement.removeChild(tooltipContainer);
+ }
+ }));
+ }
+ }
+}
+
+// Register the contribution to be initialized during the AfterRestored phase
+registerWorkbenchContribution2(TooltipContribution.ID, TooltipContribution, WorkbenchPhase.AfterRestored);
diff --git a/src/vs/workbench/contrib/void/browser/void.contribution.ts b/src/vs/workbench/contrib/void/browser/void.contribution.ts
index f0dcc477..2576f097 100644
--- a/src/vs/workbench/contrib/void/browser/void.contribution.ts
+++ b/src/vs/workbench/contrib/void/browser/void.contribution.ts
@@ -49,6 +49,9 @@ import './helperServices/consistentItemService.js'
// register selection helper
import './voidSelectionHelperWidget.js'
+// register tooltip service
+import './tooltipService.js'
+
// ---------- common (unclear if these actually need to be imported, because they're already imported wherever they're used) ----------
// llmMessage