diff --git a/packages/core/src/browser/core-preferences.ts b/packages/core/src/browser/core-preferences.ts index 526e94eba4292..6628a928e8905 100644 --- a/packages/core/src/browser/core-preferences.ts +++ b/packages/core/src/browser/core-preferences.ts @@ -80,6 +80,11 @@ export const corePreferenceSchema: PreferenceSchema = { default: 'code', markdownDescription: nls.localizeByDefault('Controls the dispatching logic for key presses to use either `code` (recommended) or `keyCode`.') }, + 'window.tabbar.enhancedPreview': { + type: 'boolean', + default: false, + description: nls.localize('theia/core/enhancedPreview', 'Controls whether more information about the tab should be displayed in horizontal tab bars.') + }, 'window.menuBarVisibility': { type: 'string', enum: ['classic', 'visible', 'hidden', 'compact'], @@ -258,6 +263,7 @@ export interface CoreConfiguration { 'breadcrumbs.enabled': boolean; 'files.encoding': string; 'keyboard.dispatch': 'code' | 'keyCode'; + 'window.tabbar.enhancedPreview': boolean; 'window.menuBarVisibility': 'classic' | 'visible' | 'hidden' | 'compact'; 'window.title': string; 'window.titleSeparator': string; diff --git a/packages/core/src/browser/hover-service.ts b/packages/core/src/browser/hover-service.ts index 1747dfeadd11f..789a506d4b277 100644 --- a/packages/core/src/browser/hover-service.ts +++ b/packages/core/src/browser/hover-service.ts @@ -57,6 +57,11 @@ export interface HoverRequest { * if the specified content does not fit in the window next to the target element */ position: HoverPosition + /** + * Additional css classes that should be added to the hover box. + * Used to style certain boxes different e.g. for the extended tab preview. + */ + cssClasses?: string [] } @injectable() @@ -101,7 +106,10 @@ export class HoverService { protected async renderHover(request: HoverRequest): Promise { const host = this.hoverHost; - const { target, content, position } = request; + const { target, content, position, cssClasses } = request; + if (cssClasses) { + host.classList.add(...cssClasses); + } this.hoverTarget = target; if (content instanceof HTMLElement) { host.appendChild(content); @@ -124,6 +132,9 @@ export class HoverService { dispose: () => { this.lastHidHover = Date.now(); host.classList.remove(updatedPosition); + if (cssClasses) { + host.classList.remove(...cssClasses); + } } }); diff --git a/packages/core/src/browser/shell/application-shell.ts b/packages/core/src/browser/shell/application-shell.ts index 4139e23a842d7..5f33b65657ad2 100644 --- a/packages/core/src/browser/shell/application-shell.ts +++ b/packages/core/src/browser/shell/application-shell.ts @@ -286,6 +286,14 @@ export class ApplicationShell extends Widget { } }); } + + this.corePreferences.onPreferenceChanged(preference => { + if (preference.preferenceName === 'window.tabbar.enhancedPreview') { + this.allTabBars.forEach(tabBar => { + tabBar.update(); + }); + } + }); } protected initializeShell(): void { diff --git a/packages/core/src/browser/shell/tab-bars.ts b/packages/core/src/browser/shell/tab-bars.ts index 6c5695584c6b2..812b091374640 100644 --- a/packages/core/src/browser/shell/tab-bars.ts +++ b/packages/core/src/browser/shell/tab-bars.ts @@ -161,9 +161,7 @@ export class TabBarRenderer extends TabBar.Renderer { ? nls.localizeByDefault('Unpin') : nls.localizeByDefault('Close'); - const hover = this.tabBar && this.tabBar.orientation === 'horizontal' ? { - title: title.caption - } : { + const hover = this.tabBar && (this.tabBar.orientation === 'horizontal' && !this.corePreferences?.['window.tabbar.enhancedPreview']) ? { title: title.caption } : { onmouseenter: this.handleMouseEnterEvent }; @@ -484,16 +482,41 @@ export class TabBarRenderer extends TabBar.Renderer { return h.div({ className: baseClassName, style }, data.title.iconLabel); } + protected renderEnhancedPreview = (title: Title) => { + const hoverBox = document.createElement('div'); + hoverBox.classList.add('theia-horizontal-tabBar-hover-div'); + const labelElement = document.createElement('p'); + labelElement.classList.add('theia-horizontal-tabBar-hover-title'); + labelElement.textContent = title.label; + hoverBox.append(labelElement); + if (title.caption) { + const captionElement = document.createElement('p'); + captionElement.classList.add('theia-horizontal-tabBar-hover-caption'); + captionElement.textContent = title.caption; + hoverBox.appendChild(captionElement); + } + return hoverBox; + }; + protected handleMouseEnterEvent = (event: MouseEvent) => { if (this.tabBar && this.hoverService && event.currentTarget instanceof HTMLElement) { const id = event.currentTarget.id; const title = this.tabBar.titles.find(t => this.createTabId(t) === id); if (title) { - this.hoverService.requestHover({ - content: title.caption, - target: event.currentTarget, - position: 'right' - }); + if (this.tabBar.orientation === 'horizontal') { + this.hoverService.requestHover({ + content: this.renderEnhancedPreview(title), + target: event.currentTarget, + position: 'bottom', + cssClasses: ['extended-tab-preview'] + }); + } else { + this.hoverService.requestHover({ + content: title.caption, + target: event.currentTarget, + position: 'right' + }); + } } } }; diff --git a/packages/core/src/browser/style/hover-service.css b/packages/core/src/browser/style/hover-service.css index 8ed6a774418e5..86ba955b654b0 100644 --- a/packages/core/src/browser/style/hover-service.css +++ b/packages/core/src/browser/style/hover-service.css @@ -93,3 +93,7 @@ border-top: 5px solid transparent; border-bottom: 5px solid transparent; } + +.theia-hover.extended-tab-preview { + border-radius: 10px; +} diff --git a/packages/core/src/browser/style/tabs.css b/packages/core/src/browser/style/tabs.css index deb4d36a61cc0..05569f1cd786b 100644 --- a/packages/core/src/browser/style/tabs.css +++ b/packages/core/src/browser/style/tabs.css @@ -419,3 +419,19 @@ .p-TabBar[data-orientation='horizontal'] .p-TabBar-tab.p-mod-current .theia-tab-icon-label { overflow: hidden; } + +.theia-horizontal-tabBar-hover-div { + margin: 0px 4px; +} + +.theia-horizontal-tabBar-hover-title { + font-weight: bolder; + font-size: medium; + margin: 0px 0px; +} + +.theia-horizontal-tabBar-hover-caption { + font-size: small; + margin: 0px 0px; + margin-top: 4px; +}