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