feat: add patches for per-area font customization

Three new patches extending workbench font customization to all areas:
- feat-workbench-zz-area-font-family: fontFamily for sidebar, statusbar,
  tabs, panel, activitybar + global fontSize setting
- feat-workbench-zz-area-font-size-core: fontSize for statusbar,
  activitybar, panel with proportional scaling via FONT object
- feat-workbench-zz-area-font-size-tabs: fontSize for tabs with CSS
  variable scaling for tab heights and widths

Includes fixes from audit review:
- Fix stale CSS var when fontSize reverts to default (cache isUserSet)
- Fix else-if config listener blocking simultaneous updates
- Trigger grid relayout after statusbar font-size change
- Apply activitybar font before show() for correct initial sizing
- Trigger tab relayout after font-size change
- Standardize CSS fallback chains to include global font-size
- Extract inspectFontSize() helper to reduce duplication
- Replace magic 1.833333 ratio with explicit CSS height variable
This commit is contained in:
xiaolai
2026-02-21 11:18:43 +08:00
parent ff5eff419c
commit ccf4d751c8
3 changed files with 1617 additions and 0 deletions

View File

@@ -0,0 +1,477 @@
diff --git a/src/vs/workbench/browser/media/style.css b/src/vs/workbench/browser/media/style.css
index 473c1f8..57ad58c 100644
--- a/src/vs/workbench/browser/media/style.css
+++ b/src/vs/workbench/browser/media/style.css
@@ -54,6 +54,7 @@ body {
overflow: hidden;
color: var(--vscode-foreground);
font-family: var(--vscode-workbench-font-family, var(--monaco-font));
+ font-size: var(--vscode-workbench-font-size, 13px);
}
.monaco-workbench.web {
diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
index 080b687..cbd14af 100644
--- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
+++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
@@ -38,6 +38,7 @@ import { IExtensionService } from '../../../services/extensions/common/extension
import { IWorkbenchEnvironmentService } from '../../../services/environment/common/environmentService.js';
import { IViewsService } from '../../../services/views/common/viewsService.js';
import { SwitchCompositeViewAction } from '../compositeBarActions.js';
+import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
export class ActivitybarPart extends Part {
@@ -65,8 +66,15 @@ export class ActivitybarPart extends Part {
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IThemeService themeService: IThemeService,
@IStorageService storageService: IStorageService,
+ @IConfigurationService private readonly configurationService: IConfigurationService,
) {
super(Parts.ACTIVITYBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);
+
+ this._register(configurationService.onDidChangeConfiguration(e => {
+ if (e.affectsConfiguration('workbench.activityBar.experimental.fontFamily')) {
+ this.applyActivityBarFontFamily();
+ }
+ }));
}
private createCompositeBar(): PaneCompositeBar {
@@ -107,9 +115,24 @@ export class ActivitybarPart extends Part {
this.show();
}
+ this.applyActivityBarFontFamily(parent);
+
return this.content;
}
+ private applyActivityBarFontFamily(container?: HTMLElement): void {
+ const target = container ?? this.getContainer();
+ if (!target) {
+ return;
+ }
+ const family = this.configurationService.getValue<string>('workbench.activityBar.experimental.fontFamily');
+ if (family) {
+ target.style.setProperty('--vscode-workbench-activitybar-font-family', family);
+ } else {
+ target.style.removeProperty('--vscode-workbench-activitybar-font-family');
+ }
+ }
+
getPinnedPaneCompositeIds(): string[] {
return this.compositeBar.value?.getPinnedPaneCompositeIds() ?? [];
}
diff --git a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css
index abe1427..7cd25d0 100644
--- a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css
+++ b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css
@@ -6,6 +6,7 @@
.monaco-workbench .part.activitybar {
width: 48px;
height: 100%;
+ font-family: var(--vscode-workbench-activitybar-font-family, inherit);
}
.monaco-workbench .activitybar.bordered::before {
diff --git a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts
index d3fa112..31d8df8 100644
--- a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts
+++ b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts
@@ -137,6 +137,9 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart {
if (e.affectsConfiguration(SidebarPart.fontSizeSettingsKey)) {
this.applyAuxiliaryBarFontSize();
}
+ if (e.affectsConfiguration('workbench.sideBar.experimental.fontFamily')) {
+ this.applyAuxiliaryBarFontFamily();
+ }
}));
}
@@ -178,6 +181,20 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart {
container.style.borderRightWidth = borderColor && isPositionLeft ? '1px' : '0px';
this.applyAuxiliaryBarFontSize(container);
+ this.applyAuxiliaryBarFontFamily(container);
+ }
+
+ private applyAuxiliaryBarFontFamily(container?: HTMLElement): void {
+ const target = container ?? this.getContainer();
+ if (!target) {
+ return;
+ }
+ const family = this.configurationService.getValue<string>('workbench.sideBar.experimental.fontFamily');
+ if (family) {
+ target.style.setProperty('--vscode-workbench-sidebar-font-family', family);
+ } else {
+ target.style.removeProperty('--vscode-workbench-sidebar-font-family');
+ }
}
protected getCompositeBarOptions(): IPaneCompositeBarOptions {
diff --git a/src/vs/workbench/browser/parts/auxiliarybar/media/auxiliaryBarPart.css b/src/vs/workbench/browser/parts/auxiliarybar/media/auxiliaryBarPart.css
index 6ec40df..398bbe1 100644
--- a/src/vs/workbench/browser/parts/auxiliarybar/media/auxiliaryBarPart.css
+++ b/src/vs/workbench/browser/parts/auxiliarybar/media/auxiliaryBarPart.css
@@ -28,6 +28,7 @@
.monaco-workbench .part.auxiliarybar > .content {
font-size: var(--vscode-workbench-sidebar-font-size, 13px);
+ font-family: var(--vscode-workbench-sidebar-font-family, inherit);
line-height: 1.4em;
}
diff --git a/src/vs/workbench/browser/parts/editor/editorTabsControl.ts b/src/vs/workbench/browser/parts/editor/editorTabsControl.ts
index b0a44e2..a946cb7 100644
--- a/src/vs/workbench/browser/parts/editor/editorTabsControl.ts
+++ b/src/vs/workbench/browser/parts/editor/editorTabsControl.ts
@@ -46,6 +46,7 @@ import { ServiceCollection } from '../../../../platform/instantiation/common/ser
import { IBaseActionViewItemOptions } from '../../../../base/browser/ui/actionbar/actionViewItems.js';
import { MarkdownString } from '../../../../base/common/htmlContent.js';
import { IManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js';
+import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
import { applyDragImage } from '../../../../base/browser/ui/dnd/dnd.js';
export class EditorCommandsContextActionRunner extends ActionRunner {
@@ -140,6 +141,7 @@ export abstract class EditorTabsControl extends Themable implements IEditorTabsC
@IThemeService themeService: IThemeService,
@IEditorResolverService private readonly editorResolverService: IEditorResolverService,
@IHostService private readonly hostService: IHostService,
+ @IConfigurationService protected readonly configurationService: IConfigurationService,
) {
super(themeService);
@@ -147,6 +149,12 @@ export abstract class EditorTabsControl extends Themable implements IEditorTabsC
const container = this.create(parent);
+ this._register(configurationService.onDidChangeConfiguration(e => {
+ if (e.affectsConfiguration('workbench.tabs.experimental.fontFamily')) {
+ this.applyTabsFontFamily();
+ }
+ }));
+
// Context Keys
this.contextMenuContextKeyService = this._register(this.contextKeyService.createScoped(container));
const scopedInstantiationService = this._register(this.instantiationService.createChild(new ServiceCollection(
@@ -169,9 +177,23 @@ export abstract class EditorTabsControl extends Themable implements IEditorTabsC
protected create(parent: HTMLElement): HTMLElement {
this.updateTabHeight();
+ this.applyTabsFontFamily(parent);
return parent;
}
+ private applyTabsFontFamily(container?: HTMLElement): void {
+ const target = container ?? this.parent;
+ if (!target) {
+ return;
+ }
+ const family = this.configurationService.getValue<string>('workbench.tabs.experimental.fontFamily');
+ if (family) {
+ target.style.setProperty('--vscode-workbench-tabs-font-family', family);
+ } else {
+ target.style.removeProperty('--vscode-workbench-tabs-font-family');
+ }
+ }
+
private get editorActionsEnabled(): boolean {
return this.groupsView.partOptions.editorActionsLocation === 'default' && this.groupsView.partOptions.showTabs !== 'none';
}
diff --git a/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css b/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css
index 57ab8ca..e9e0b2b 100644
--- a/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css
+++ b/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css
@@ -7,6 +7,7 @@
.monaco-workbench .part.editor > .content .editor-group-container > .title {
cursor: pointer;
+ font-family: var(--vscode-workbench-tabs-font-family, inherit);
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label,
diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css
index e1c147d..76c7b07 100644
--- a/src/vs/workbench/browser/parts/panel/media/panelpart.css
+++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css
@@ -8,6 +8,10 @@
visibility: hidden !important;
}
+.monaco-workbench .part.panel > .content {
+ font-family: var(--vscode-workbench-panel-font-family, inherit);
+}
+
.monaco-workbench .part.panel.bottom .composite.title {
border-top-width: 1px;
border-top-style: solid;
diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts
index 585bc16..a5d3ff4 100644
--- a/src/vs/workbench/browser/parts/panel/panelPart.ts
+++ b/src/vs/workbench/browser/parts/panel/panelPart.ts
@@ -110,6 +110,9 @@ export class PanelPart extends AbstractPaneCompositePart {
if (e.affectsConfiguration('workbench.panel.showLabels')) {
this.updateCompositeBar(true);
}
+ if (e.affectsConfiguration('workbench.bottomPane.experimental.fontFamily')) {
+ this.applyPanelFontFamily();
+ }
}));
}
@@ -126,6 +129,21 @@ export class PanelPart extends AbstractPaneCompositePart {
if (this.titleArea) {
this.titleArea.style.borderTopColor = this.getColor(PANEL_BORDER) || this.getColor(contrastBorder) || '';
}
+
+ this.applyPanelFontFamily(container);
+ }
+
+ private applyPanelFontFamily(container?: HTMLElement): void {
+ const target = container ?? this.getContainer();
+ if (!target) {
+ return;
+ }
+ const family = this.configurationService.getValue<string>('workbench.bottomPane.experimental.fontFamily');
+ if (family) {
+ target.style.setProperty('--vscode-workbench-panel-font-family', family);
+ } else {
+ target.style.removeProperty('--vscode-workbench-panel-font-family');
+ }
}
protected getCompositeBarOptions(): IPaneCompositeBarOptions {
diff --git a/src/vs/workbench/browser/parts/sidebar/media/sidebarpart.css b/src/vs/workbench/browser/parts/sidebar/media/sidebarpart.css
index 7088a97..3a5ff82 100644
--- a/src/vs/workbench/browser/parts/sidebar/media/sidebarpart.css
+++ b/src/vs/workbench/browser/parts/sidebar/media/sidebarpart.css
@@ -198,4 +198,8 @@
.monaco-workbench .part.sidebar .monaco-custom-toggle {
height: calc(var(--vscode-workbench-sidebar-font-size) * 1.539);
width: calc(var(--vscode-workbench-sidebar-font-size) * 1.539);
-} */
\ No newline at end of file
+} */
+
+.monaco-workbench .part.sidebar > .content {
+ font-family: var(--vscode-workbench-sidebar-font-family, inherit);
+}
\ No newline at end of file
diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts
index 9b6ae18..322f69b 100644
--- a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts
+++ b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts
@@ -114,6 +114,9 @@ export class SidebarPart extends AbstractPaneCompositePart {
if (e.affectsConfiguration(SidebarPart.fontSizeSettingsKey)) {
this.applySidebarFontSize();
}
+ if (e.affectsConfiguration('workbench.sideBar.experimental.fontFamily')) {
+ this.applySidebarFontFamily();
+ }
}));
this.registerActions();
@@ -155,6 +158,7 @@ export class SidebarPart extends AbstractPaneCompositePart {
container.style.outlineColor = this.getColor(SIDE_BAR_DRAG_AND_DROP_BACKGROUND) ?? '';
this.applySidebarFontSize(container);
+ this.applySidebarFontFamily(container);
}
override layout(width: number, height: number, top: number, left: number): void {
@@ -297,6 +301,19 @@ export class SidebarPart extends AbstractPaneCompositePart {
target.style.setProperty('--vscode-workbench-sidebar-font-size', `${FONT.sidebarSize}px`);
}
+ private applySidebarFontFamily(container?: HTMLElement): void {
+ const target = container ?? this.getContainer();
+ if (!target) {
+ return;
+ }
+ const family = this.configurationService.getValue<string>('workbench.sideBar.experimental.fontFamily');
+ if (family) {
+ target.style.setProperty('--vscode-workbench-sidebar-font-family', family);
+ } else {
+ target.style.removeProperty('--vscode-workbench-sidebar-font-family');
+ }
+ }
+
private registerActions(): void {
const that = this;
this._register(registerAction2(class extends Action2 {
diff --git a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css
index 7faaf9e..b633ee1 100644
--- a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css
+++ b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css
@@ -9,6 +9,7 @@
width: 100%;
height: 22px;
font-size: 12px;
+ font-family: var(--vscode-workbench-statusbar-font-family, inherit);
display: flex;
overflow: hidden;
}
diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts
index 4bd53d4..62e78d0 100644
--- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts
+++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts
@@ -36,6 +36,7 @@ import { StatusBarFocused } from '../../../common/contextkeys.js';
import { Emitter, Event } from '../../../../base/common/event.js';
import { IView } from '../../../../base/browser/ui/grid/grid.js';
import { isManagedHoverTooltipHTMLElement, isManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js';
+import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
export interface IStatusbarEntryContainer extends IDisposable {
@@ -160,9 +161,16 @@ class StatusbarPart extends Part implements IStatusbarEntryContainer {
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
+ @IConfigurationService private readonly configurationService: IConfigurationService,
) {
super(id, { hasTitle: false }, themeService, storageService, layoutService);
+ this._register(configurationService.onDidChangeConfiguration(e => {
+ if (e.affectsConfiguration('workbench.statusBar.experimental.fontFamily')) {
+ this.applyStatusBarFontFamily();
+ }
+ }));
+
this.viewModel = this._register(new StatusbarViewModel(storageService));
this.onDidChangeEntryVisibility = this.viewModel.onDidChangeEntryVisibility;
@@ -427,9 +435,24 @@ class StatusbarPart extends Part implements IStatusbarEntryContainer {
// Initial status bar entries
this.createInitialStatusbarEntries();
+ this.applyStatusBarFontFamily(this.element);
+
return this.element;
}
+ private applyStatusBarFontFamily(container?: HTMLElement): void {
+ const target = container ?? this.getContainer();
+ if (!target) {
+ return;
+ }
+ const family = this.configurationService.getValue<string>('workbench.statusBar.experimental.fontFamily');
+ if (family) {
+ target.style.setProperty('--vscode-workbench-statusbar-font-family', family);
+ } else {
+ target.style.removeProperty('--vscode-workbench-statusbar-font-family');
+ }
+ }
+
private createInitialStatusbarEntries(): void {
// Add items in order according to alignment
diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts
index 3eaad2e..8a9eb0e 100644
--- a/src/vs/workbench/browser/workbench.contribution.ts
+++ b/src/vs/workbench/browser/workbench.contribution.ts
@@ -667,6 +667,44 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
description: localize('workbench.fontFamily', "Controls the font family in the workbench."),
'tags': ['experimental']
},
+ 'workbench.experimental.fontSize': {
+ type: 'number',
+ default: 13,
+ minimum: 6,
+ maximum: 32,
+ markdownDescription: localize('workbench.fontSize', "Controls the font size in pixels for the workbench."),
+ 'tags': ['accessibility', 'experimental']
+ },
+ 'workbench.sideBar.experimental.fontFamily': {
+ type: 'string',
+ default: '',
+ markdownDescription: localize('sideBarFontFamily', "Controls the font family in the side bar."),
+ 'tags': ['accessibility', 'experimental']
+ },
+ 'workbench.statusBar.experimental.fontFamily': {
+ type: 'string',
+ default: '',
+ markdownDescription: localize('statusBarFontFamily', "Controls the font family in the status bar."),
+ 'tags': ['accessibility', 'experimental']
+ },
+ 'workbench.tabs.experimental.fontFamily': {
+ type: 'string',
+ default: '',
+ markdownDescription: localize('tabsFontFamily', "Controls the font family in editor tabs."),
+ 'tags': ['accessibility', 'experimental']
+ },
+ 'workbench.bottomPane.experimental.fontFamily': {
+ type: 'string',
+ default: '',
+ markdownDescription: localize('bottomPaneFontFamily', "Controls the font family in the bottom panel."),
+ 'tags': ['accessibility', 'experimental']
+ },
+ 'workbench.activityBar.experimental.fontFamily': {
+ type: 'string',
+ default: '',
+ markdownDescription: localize('activityBarFontFamily', "Controls the font family in the activity bar."),
+ 'tags': ['accessibility', 'experimental']
+ },
'workbench.settings.editor': {
'type': 'string',
'enum': ['ui', 'json'],
diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts
index 7259aff..ee4cbf8 100644
--- a/src/vs/workbench/browser/workbench.ts
+++ b/src/vs/workbench/browser/workbench.ts
@@ -235,9 +235,12 @@ export class Workbench extends Layout {
if (e.affectsConfiguration('workbench.fontAliasing')) {
this.updateFontAliasing(configurationService);
}
- else if (e.affectsConfiguration('workbench.experimental.fontFamily')) {
+ if (e.affectsConfiguration('workbench.experimental.fontFamily')) {
this.updateFontFamily(configurationService);
}
+ if (e.affectsConfiguration('workbench.experimental.fontSize')) {
+ this.updateFontSize(configurationService);
+ }
}));
// Font Info
@@ -297,6 +300,33 @@ export class Workbench extends Layout {
}
}
+ private fontSize: number | undefined;
+ private fontSizeUserSet: boolean | undefined;
+ private updateFontSize(configurationService: IConfigurationService) {
+ const raw = configurationService.getValue<number>('workbench.experimental.fontSize');
+ const size = Math.max(6, Math.min(32, typeof raw === 'number' ? raw : 13));
+
+ const inspected = configurationService.inspect<number>('workbench.experimental.fontSize');
+ const isUserSet = inspected.userValue !== undefined
+ || inspected.userLocalValue !== undefined
+ || inspected.userRemoteValue !== undefined
+ || inspected.workspaceValue !== undefined
+ || inspected.workspaceFolderValue !== undefined;
+
+ if (this.fontSize === size && this.fontSizeUserSet === isUserSet) {
+ return;
+ }
+
+ this.fontSize = size;
+ this.fontSizeUserSet = isUserSet;
+
+ if (isUserSet) {
+ this.mainContainer.style.setProperty('--vscode-workbench-font-size', `${size}px`);
+ } else {
+ this.mainContainer.style.removeProperty('--vscode-workbench-font-size');
+ }
+ }
+
private fontFamily: string | undefined;
private updateFontFamily(configurationService: IConfigurationService) {
let family = configurationService.getValue<string>('workbench.experimental.fontFamily');
@@ -360,6 +390,7 @@ export class Workbench extends Layout {
this.updateFontAliasing(configurationService);
this.updateFontFamily(configurationService);
+ this.updateFontSize(configurationService);
// Warm up font cache information before building up too many dom elements
this.restoreFontInfo(storageService, configurationService);

View File

@@ -0,0 +1,917 @@
diff --git a/src/vs/base/common/font.ts b/src/vs/base/common/font.ts
index 2be97d7..8a8d60e 100644
--- a/src/vs/base/common/font.ts
+++ b/src/vs/base/common/font.ts
@@ -1,3 +1,27 @@
+/**
+ * Inspect a configuration value and return whether it was explicitly set by the user,
+ * along with the clamped numeric value.
+ */
+export function inspectFontSize(
+ configurationService: { inspect<T>(key: string): { userValue?: T; userLocalValue?: T; userRemoteValue?: T; workspaceValue?: T; workspaceFolderValue?: T }; getValue<T>(key: string): T },
+ key: string,
+ defaultSize: number,
+ min: number = 6,
+ max: number = 32
+): { isUserSet: boolean; size: number } {
+ const inspected = configurationService.inspect<number>(key);
+ const isUserSet = inspected.userValue !== undefined
+ || inspected.userLocalValue !== undefined
+ || inspected.userRemoteValue !== undefined
+ || inspected.workspaceValue !== undefined
+ || inspected.workspaceFolderValue !== undefined;
+
+ const raw = configurationService.getValue<number>(key);
+ const size = Math.max(min, Math.min(max, typeof raw === 'number' ? raw : defaultSize));
+
+ return { isUserSet, size };
+}
+
export const FONT = {
sidebarSize: 13,
sidebarSize8: 8,
@@ -16,8 +40,29 @@ export const FONT = {
sidebarSize44: 44,
sidebarSize62: 62,
sidebarSize72: 72,
+
+ statusBarSize: 12,
+ statusBarSize22: 22,
+
+ panelSize: 13,
+ panelSize22: 22,
+
+ activityBarSize: 16,
+ activityBarSize16: 16,
+ activityBarSize24: 24,
+ activityBarSize32: 32,
+ activityBarSize36: 36,
+ activityBarSize48: 48,
+
+ tabsSize: 13,
+ tabsSize22: 22,
+ tabsSize35: 35,
+ tabsSize38: 38,
+ tabsSize80: 80,
+ tabsSize120: 120,
};
+// Sidebar coefficients (base 13)
const COEFF_8 = 8/13;
const COEFF_10 = 10/13;
const COEFF_16 = 16/13;
@@ -54,3 +99,51 @@ export function updateSidebarSize(size: number): void {
FONT.sidebarSize62 = size * COEFF_62;
FONT.sidebarSize72 = size * COEFF_72;
}
+
+// Status bar coefficients (base 12)
+const SB_COEFF_22 = 22/12;
+
+export function updateStatusBarSize(size: number): void {
+ FONT.statusBarSize = size;
+ FONT.statusBarSize22 = size * SB_COEFF_22;
+}
+
+// Panel coefficients (base 13)
+const PN_COEFF_22 = 22/13;
+
+export function updatePanelSize(size: number): void {
+ FONT.panelSize = size;
+ FONT.panelSize22 = size * PN_COEFF_22;
+}
+
+// Activity bar coefficients (base 16)
+const AB_COEFF_16 = 16/16;
+const AB_COEFF_24 = 24/16;
+const AB_COEFF_32 = 32/16;
+const AB_COEFF_36 = 36/16;
+const AB_COEFF_48 = 48/16;
+
+export function updateActivityBarSize(size: number): void {
+ FONT.activityBarSize = size;
+ FONT.activityBarSize16 = size * AB_COEFF_16;
+ FONT.activityBarSize24 = size * AB_COEFF_24;
+ FONT.activityBarSize32 = size * AB_COEFF_32;
+ FONT.activityBarSize36 = size * AB_COEFF_36;
+ FONT.activityBarSize48 = size * AB_COEFF_48;
+}
+
+// Tabs coefficients (base 13)
+const TB_COEFF_22 = 22/13;
+const TB_COEFF_35 = 35/13;
+const TB_COEFF_38 = 38/13;
+const TB_COEFF_80 = 80/13;
+const TB_COEFF_120 = 120/13;
+
+export function updateTabsSize(size: number): void {
+ FONT.tabsSize = size;
+ FONT.tabsSize22 = size * TB_COEFF_22;
+ FONT.tabsSize35 = size * TB_COEFF_35;
+ FONT.tabsSize38 = size * TB_COEFF_38;
+ FONT.tabsSize80 = size * TB_COEFF_80;
+ FONT.tabsSize120 = size * TB_COEFF_120;
+}
diff --git a/src/vs/base/test/common/font.test.ts b/src/vs/base/test/common/font.test.ts
new file mode 100644
index 0000000..dcde0e7
--- /dev/null
+++ b/src/vs/base/test/common/font.test.ts
@@ -0,0 +1,482 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) VSCodium. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import assert from 'assert';
+import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../test/common/utils.js';
+import { FONT, updateSidebarSize, updateStatusBarSize, updatePanelSize, updateActivityBarSize, updateTabsSize } from '../../common/font.js';
+
+/**
+ * Test file for src/vs/base/common/font.ts
+ *
+ * Tests all update*Size() functions for:
+ * - Default values match upstream VS Code hardcoded constants
+ * - Proportional scaling preserves ratios at non-default sizes
+ * - Boundary values (minimum=6, maximum=32) produce positive values
+ * - Reset to default restores original values
+ * - Non-divisible sizes produce consistent coefficient-based output
+ * - Cross-area updates do not mutate unrelated fields
+ */
+
+const EPSILON = 1e-9;
+
+/** Assert two numbers are equal within floating-point tolerance */
+function assertClose(actual: number, expected: number, message?: string): void {
+ const diff = Math.abs(actual - expected);
+ assert.ok(diff < EPSILON, `${message ?? ''} expected ${expected}, got ${actual} (diff: ${diff})`);
+}
+
+/**
+ * Snapshot all FONT fields to detect unintended mutations.
+ * Returns a plain object copy of every enumerable property.
+ */
+function snapshotFont(): Record<string, number> {
+ const snap: Record<string, number> = {};
+ for (const key of Object.keys(FONT)) {
+ snap[key] = (FONT as Record<string, number>)[key];
+ }
+ return snap;
+}
+
+/** Assert that specific fields in FONT have not changed from a snapshot */
+function assertFieldsUnchanged(snapshot: Record<string, number>, prefix: string, message: string): void {
+ for (const key of Object.keys(snapshot)) {
+ if (key.startsWith(prefix)) {
+ assertClose((FONT as Record<string, number>)[key], snapshot[key], `${message}: ${key}`);
+ }
+ }
+}
+
+suite('FONT - Sidebar Size', () => {
+
+ ensureNoDisposablesAreLeakedInTestSuite();
+
+ // Capture defaults before any test mutates them
+ const DEFAULTS = snapshotFont();
+
+ teardown(() => {
+ // Reset after each test
+ updateSidebarSize(13);
+ });
+
+ test('defaults match upstream VS Code constants', () => {
+ assert.strictEqual(FONT.sidebarSize, 13);
+ assert.strictEqual(FONT.sidebarSize8, 8);
+ assert.strictEqual(FONT.sidebarSize10, 10);
+ assert.strictEqual(FONT.sidebarSize16, 16);
+ assert.strictEqual(FONT.sidebarSize17, 17);
+ assert.strictEqual(FONT.sidebarSize18, 18);
+ assert.strictEqual(FONT.sidebarSize20, 20);
+ assert.strictEqual(FONT.sidebarSize22, 22);
+ assert.strictEqual(FONT.sidebarSize23, 23);
+ assert.strictEqual(FONT.sidebarSize24, 24);
+ assert.strictEqual(FONT.sidebarSize26, 26);
+ assert.strictEqual(FONT.sidebarSize28, 28);
+ assert.strictEqual(FONT.sidebarSize34, 34);
+ assert.strictEqual(FONT.sidebarSize39, 39);
+ assert.strictEqual(FONT.sidebarSize44, 44);
+ assert.strictEqual(FONT.sidebarSize62, 62);
+ assert.strictEqual(FONT.sidebarSize72, 72);
+ });
+
+ test('proportional scaling preserves ratios at 2x', () => {
+ updateSidebarSize(26); // 2x default
+ assert.strictEqual(FONT.sidebarSize, 26);
+ assert.strictEqual(FONT.sidebarSize8, 16);
+ assert.strictEqual(FONT.sidebarSize22, 44);
+ assert.strictEqual(FONT.sidebarSize44, 88);
+ assert.strictEqual(FONT.sidebarSize72, 144);
+ });
+
+ test('non-divisible size produces consistent coefficient-based values', () => {
+ updateSidebarSize(7);
+ assertClose(FONT.sidebarSize22, 7 * (22 / 13));
+ assertClose(FONT.sidebarSize44, 7 * (44 / 13));
+ assertClose(FONT.sidebarSize72, 7 * (72 / 13));
+ });
+
+ test('another non-divisible size (31)', () => {
+ updateSidebarSize(31);
+ assertClose(FONT.sidebarSize22, 31 * (22 / 13));
+ assertClose(FONT.sidebarSize44, 31 * (44 / 13));
+ });
+
+ test('minimum value (6) produces positive values', () => {
+ updateSidebarSize(6);
+ assert.strictEqual(FONT.sidebarSize, 6);
+ assert.ok(FONT.sidebarSize8 > 0, 'sidebarSize8 must be positive');
+ assert.ok(FONT.sidebarSize10 > 0, 'sidebarSize10 must be positive');
+ assert.ok(FONT.sidebarSize22 > 0, 'sidebarSize22 must be positive');
+ assert.ok(FONT.sidebarSize72 > 0, 'sidebarSize72 must be positive');
+ });
+
+ test('maximum value (32) produces reasonable values', () => {
+ updateSidebarSize(32);
+ assert.strictEqual(FONT.sidebarSize, 32);
+ assert.ok(FONT.sidebarSize22 > 40, 'row height should scale up');
+ assert.ok(FONT.sidebarSize22 < 80, 'row height should not be extreme');
+ });
+
+ test('reset to default restores all values', () => {
+ updateSidebarSize(20);
+ assert.notStrictEqual(FONT.sidebarSize22, DEFAULTS.sidebarSize22);
+ updateSidebarSize(13);
+ assertFieldsUnchanged(DEFAULTS, 'sidebar', 'after reset');
+ });
+
+ test('multiple updates in sequence are idempotent at same value', () => {
+ updateSidebarSize(18);
+ const snap = snapshotFont();
+ updateSidebarSize(18);
+ assertFieldsUnchanged(snap, 'sidebar', 'idempotent');
+ });
+});
+
+suite('FONT - Status Bar Size', () => {
+
+ ensureNoDisposablesAreLeakedInTestSuite();
+
+ teardown(() => {
+ updateStatusBarSize(12);
+ });
+
+ test('defaults match upstream VS Code status bar constants', () => {
+ assert.strictEqual(FONT.statusBarSize, 12);
+ assert.strictEqual(FONT.statusBarSize22, 22); // StatusbarPart.HEIGHT
+ });
+
+ test('proportional scaling at 2x', () => {
+ updateStatusBarSize(24);
+ assert.strictEqual(FONT.statusBarSize, 24);
+ assert.strictEqual(FONT.statusBarSize22, 44);
+ });
+
+ test('non-divisible size (7)', () => {
+ updateStatusBarSize(7);
+ assertClose(FONT.statusBarSize22, 7 * (22 / 12));
+ });
+
+ test('minimum value (6) produces positive height', () => {
+ updateStatusBarSize(6);
+ assert.strictEqual(FONT.statusBarSize, 6);
+ assert.ok(FONT.statusBarSize22 > 0, 'height must be positive');
+ assertClose(FONT.statusBarSize22, 6 * (22 / 12));
+ });
+
+ test('maximum value (32) produces reasonable height', () => {
+ updateStatusBarSize(32);
+ assertClose(FONT.statusBarSize22, 32 * (22 / 12));
+ assert.ok(FONT.statusBarSize22 > 50, 'height should scale up');
+ assert.ok(FONT.statusBarSize22 < 70, 'height should not be extreme');
+ });
+
+ test('reset to default restores values', () => {
+ updateStatusBarSize(20);
+ updateStatusBarSize(12);
+ assert.strictEqual(FONT.statusBarSize, 12);
+ assert.strictEqual(FONT.statusBarSize22, 22);
+ });
+});
+
+suite('FONT - Panel Size', () => {
+
+ ensureNoDisposablesAreLeakedInTestSuite();
+
+ teardown(() => {
+ updatePanelSize(13);
+ });
+
+ test('defaults match sidebar defaults (same base size)', () => {
+ assert.strictEqual(FONT.panelSize, 13);
+ assert.strictEqual(FONT.panelSize22, 22);
+ });
+
+ test('panel and sidebar can have independent sizes', () => {
+ updatePanelSize(18);
+ assert.strictEqual(FONT.panelSize, 18);
+ assert.notStrictEqual(FONT.panelSize22, 22);
+ // Sidebar unchanged
+ assert.strictEqual(FONT.sidebarSize, 13);
+ assert.strictEqual(FONT.sidebarSize22, 22);
+ });
+
+ test('proportional scaling at 2x', () => {
+ updatePanelSize(26);
+ assert.strictEqual(FONT.panelSize22, 44);
+ });
+
+ test('non-divisible size (7)', () => {
+ updatePanelSize(7);
+ assertClose(FONT.panelSize22, 7 * (22 / 13));
+ });
+
+ test('minimum value (6)', () => {
+ updatePanelSize(6);
+ assert.ok(FONT.panelSize22 > 0, 'row height must be positive');
+ assert.ok(FONT.panelSize22 >= 10, 'row height at minimum should be usable');
+ });
+
+ test('maximum value (32)', () => {
+ updatePanelSize(32);
+ assert.ok(FONT.panelSize22 > 50, 'row height should scale up');
+ });
+
+ test('reset to default restores values', () => {
+ updatePanelSize(20);
+ updatePanelSize(13);
+ assert.strictEqual(FONT.panelSize, 13);
+ assert.strictEqual(FONT.panelSize22, 22);
+ });
+});
+
+suite('FONT - Activity Bar Size', () => {
+
+ ensureNoDisposablesAreLeakedInTestSuite();
+
+ teardown(() => {
+ updateActivityBarSize(16);
+ });
+
+ test('defaults match upstream VS Code activity bar constants', () => {
+ assert.strictEqual(FONT.activityBarSize, 16);
+ assert.strictEqual(FONT.activityBarSize16, 16); // COMPACT_ICON_SIZE
+ assert.strictEqual(FONT.activityBarSize24, 24); // ICON_SIZE
+ assert.strictEqual(FONT.activityBarSize32, 32); // COMPACT_ACTION_HEIGHT
+ assert.strictEqual(FONT.activityBarSize36, 36); // COMPACT_ACTIVITYBAR_WIDTH
+ assert.strictEqual(FONT.activityBarSize48, 48); // ACTION_HEIGHT / ACTIVITYBAR_WIDTH
+ });
+
+ test('proportional scaling at 2x', () => {
+ updateActivityBarSize(32);
+ assert.strictEqual(FONT.activityBarSize, 32);
+ assert.strictEqual(FONT.activityBarSize16, 32); // compact icon = base size
+ assert.strictEqual(FONT.activityBarSize24, 48);
+ assert.strictEqual(FONT.activityBarSize32, 64);
+ assert.strictEqual(FONT.activityBarSize36, 72);
+ assert.strictEqual(FONT.activityBarSize48, 96);
+ });
+
+ test('compact constants scale correctly', () => {
+ updateActivityBarSize(20);
+ // Compact icon size = base size * (16/16) = 20
+ assertClose(FONT.activityBarSize16, 20 * (16 / 16));
+ // Compact width = base * (36/16) = 45
+ assertClose(FONT.activityBarSize36, 20 * (36 / 16));
+ // Compact action height = base * (32/16) = 40
+ assertClose(FONT.activityBarSize32, 20 * (32 / 16));
+ });
+
+ test('non-divisible size (7)', () => {
+ updateActivityBarSize(7);
+ assertClose(FONT.activityBarSize24, 7 * (24 / 16));
+ assertClose(FONT.activityBarSize48, 7 * (48 / 16));
+ assertClose(FONT.activityBarSize36, 7 * (36 / 16));
+ });
+
+ test('minimum value (6) produces positive values', () => {
+ updateActivityBarSize(6);
+ assert.strictEqual(FONT.activityBarSize, 6);
+ assert.ok(FONT.activityBarSize16 > 0, 'compact icon size must be positive');
+ assert.ok(FONT.activityBarSize24 > 0, 'icon size must be positive');
+ assert.ok(FONT.activityBarSize36 > 0, 'compact width must be positive');
+ assert.ok(FONT.activityBarSize48 > 0, 'action height must be positive');
+ });
+
+ test('maximum value (32) produces reasonable values', () => {
+ updateActivityBarSize(32);
+ assert.strictEqual(FONT.activityBarSize48, 96);
+ assert.ok(FONT.activityBarSize48 <= 100, 'action height should be bounded');
+ });
+
+ test('reset to default restores values', () => {
+ updateActivityBarSize(24);
+ updateActivityBarSize(16);
+ assert.strictEqual(FONT.activityBarSize, 16);
+ assert.strictEqual(FONT.activityBarSize16, 16);
+ assert.strictEqual(FONT.activityBarSize24, 24);
+ assert.strictEqual(FONT.activityBarSize32, 32);
+ assert.strictEqual(FONT.activityBarSize36, 36);
+ assert.strictEqual(FONT.activityBarSize48, 48);
+ });
+});
+
+suite('FONT - Tabs Size', () => {
+
+ ensureNoDisposablesAreLeakedInTestSuite();
+
+ teardown(() => {
+ updateTabsSize(13);
+ });
+
+ test('defaults match upstream VS Code tab constants', () => {
+ assert.strictEqual(FONT.tabsSize, 13);
+ assert.strictEqual(FONT.tabsSize22, 22); // EDITOR_TAB_HEIGHT compact
+ assert.strictEqual(FONT.tabsSize35, 35); // EDITOR_TAB_HEIGHT normal
+ assert.strictEqual(FONT.tabsSize38, 38); // TAB_WIDTH compact
+ assert.strictEqual(FONT.tabsSize80, 80); // TAB_WIDTH shrink
+ assert.strictEqual(FONT.tabsSize120, 120); // TAB_WIDTH fit
+ });
+
+ test('proportional scaling preserves tab height/width ratios at 2x', () => {
+ updateTabsSize(26);
+ assert.strictEqual(FONT.tabsSize, 26);
+ assert.strictEqual(FONT.tabsSize22, 44);
+ assert.strictEqual(FONT.tabsSize35, 70);
+ assert.strictEqual(FONT.tabsSize38, 76);
+ assert.strictEqual(FONT.tabsSize80, 160);
+ assert.strictEqual(FONT.tabsSize120, 240);
+ });
+
+ test('non-divisible size (7)', () => {
+ updateTabsSize(7);
+ assertClose(FONT.tabsSize22, 7 * (22 / 13));
+ assertClose(FONT.tabsSize35, 7 * (35 / 13));
+ assertClose(FONT.tabsSize80, 7 * (80 / 13));
+ assertClose(FONT.tabsSize120, 7 * (120 / 13));
+ });
+
+ test('minimum value (6) produces usable tab dimensions', () => {
+ updateTabsSize(6);
+ assert.strictEqual(FONT.tabsSize, 6);
+ assert.ok(FONT.tabsSize35 > 10, 'normal tab height must be clickable');
+ assert.ok(FONT.tabsSize22 > 8, 'compact tab height must be usable');
+ assert.ok(FONT.tabsSize38 > 0, 'compact tab width must be positive');
+ assert.ok(FONT.tabsSize80 > 0, 'shrink tab width must be positive');
+ });
+
+ test('maximum value (32) produces reasonable tab dimensions', () => {
+ updateTabsSize(32);
+ assert.ok(FONT.tabsSize35 > 80, 'normal tab height should scale up');
+ assert.ok(FONT.tabsSize35 < 100, 'normal tab height should be bounded');
+ });
+
+ test('reset to default restores all values', () => {
+ updateTabsSize(20);
+ updateTabsSize(13);
+ assert.strictEqual(FONT.tabsSize, 13);
+ assert.strictEqual(FONT.tabsSize22, 22);
+ assert.strictEqual(FONT.tabsSize35, 35);
+ assert.strictEqual(FONT.tabsSize38, 38);
+ assert.strictEqual(FONT.tabsSize80, 80);
+ assert.strictEqual(FONT.tabsSize120, 120);
+ });
+});
+
+suite('FONT - Cross-area independence', () => {
+
+ ensureNoDisposablesAreLeakedInTestSuite();
+
+ teardown(() => {
+ updateSidebarSize(13);
+ updateStatusBarSize(12);
+ updatePanelSize(13);
+ updateActivityBarSize(16);
+ updateTabsSize(13);
+ });
+
+ test('updating sidebar does not affect any other area (full derived field check)', () => {
+ const before = snapshotFont();
+ updateSidebarSize(20);
+
+ // All non-sidebar fields must be unchanged
+ assertFieldsUnchanged(before, 'statusBar', 'after sidebar update');
+ assertFieldsUnchanged(before, 'panel', 'after sidebar update');
+ assertFieldsUnchanged(before, 'activityBar', 'after sidebar update');
+ assertFieldsUnchanged(before, 'tabs', 'after sidebar update');
+ });
+
+ test('updating statusBar does not affect any other area', () => {
+ const before = snapshotFont();
+ updateStatusBarSize(20);
+
+ assertFieldsUnchanged(before, 'sidebar', 'after statusBar update');
+ assertFieldsUnchanged(before, 'panel', 'after statusBar update');
+ assertFieldsUnchanged(before, 'activityBar', 'after statusBar update');
+ assertFieldsUnchanged(before, 'tabs', 'after statusBar update');
+ });
+
+ test('updating panel does not affect any other area', () => {
+ const before = snapshotFont();
+ updatePanelSize(20);
+
+ assertFieldsUnchanged(before, 'sidebar', 'after panel update');
+ assertFieldsUnchanged(before, 'statusBar', 'after panel update');
+ assertFieldsUnchanged(before, 'activityBar', 'after panel update');
+ assertFieldsUnchanged(before, 'tabs', 'after panel update');
+ });
+
+ test('updating activityBar does not affect any other area', () => {
+ const before = snapshotFont();
+ updateActivityBarSize(20);
+
+ assertFieldsUnchanged(before, 'sidebar', 'after activityBar update');
+ assertFieldsUnchanged(before, 'statusBar', 'after activityBar update');
+ assertFieldsUnchanged(before, 'panel', 'after activityBar update');
+ assertFieldsUnchanged(before, 'tabs', 'after activityBar update');
+ });
+
+ test('updating tabs does not affect any other area', () => {
+ const before = snapshotFont();
+ updateTabsSize(20);
+
+ assertFieldsUnchanged(before, 'sidebar', 'after tabs update');
+ assertFieldsUnchanged(before, 'statusBar', 'after tabs update');
+ assertFieldsUnchanged(before, 'panel', 'after tabs update');
+ assertFieldsUnchanged(before, 'activityBar', 'after tabs update');
+ });
+
+ test('all areas set to same value produce different derived values due to different coefficients', () => {
+ const commonSize = 18;
+ updateSidebarSize(commonSize);
+ updateStatusBarSize(commonSize);
+ updatePanelSize(commonSize);
+ updateActivityBarSize(commonSize);
+ updateTabsSize(commonSize);
+
+ assert.strictEqual(FONT.sidebarSize, commonSize);
+ assert.strictEqual(FONT.statusBarSize, commonSize);
+ assert.strictEqual(FONT.panelSize, commonSize);
+ assert.strictEqual(FONT.activityBarSize, commonSize);
+ assert.strictEqual(FONT.tabsSize, commonSize);
+
+ // sidebarSize22 = 18 * (22/13), statusBarSize22 = 18 * (22/12)
+ // Different coefficients → different results
+ assert.notStrictEqual(FONT.sidebarSize22, FONT.statusBarSize22,
+ 'same base size should produce different derived values due to different coefficients');
+ });
+
+ test('sequential updates across all areas and full reset', () => {
+ updateSidebarSize(8);
+ updateStatusBarSize(10);
+ updatePanelSize(15);
+ updateActivityBarSize(20);
+ updateTabsSize(25);
+
+ // Verify all set correctly
+ assert.strictEqual(FONT.sidebarSize, 8);
+ assert.strictEqual(FONT.statusBarSize, 10);
+ assert.strictEqual(FONT.panelSize, 15);
+ assert.strictEqual(FONT.activityBarSize, 20);
+ assert.strictEqual(FONT.tabsSize, 25);
+
+ // Reset all
+ updateSidebarSize(13);
+ updateStatusBarSize(12);
+ updatePanelSize(13);
+ updateActivityBarSize(16);
+ updateTabsSize(13);
+
+ // All defaults restored
+ assert.strictEqual(FONT.sidebarSize, 13);
+ assert.strictEqual(FONT.sidebarSize22, 22);
+ assert.strictEqual(FONT.statusBarSize, 12);
+ assert.strictEqual(FONT.statusBarSize22, 22);
+ assert.strictEqual(FONT.panelSize, 13);
+ assert.strictEqual(FONT.panelSize22, 22);
+ assert.strictEqual(FONT.activityBarSize, 16);
+ assert.strictEqual(FONT.activityBarSize48, 48);
+ assert.strictEqual(FONT.tabsSize, 13);
+ assert.strictEqual(FONT.tabsSize35, 35);
+ });
+});
diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
index cbd14af..83153fe 100644
--- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
+++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
@@ -38,11 +38,11 @@ import { IExtensionService } from '../../../services/extensions/common/extension
import { IWorkbenchEnvironmentService } from '../../../services/environment/common/environmentService.js';
import { IViewsService } from '../../../services/views/common/viewsService.js';
import { SwitchCompositeViewAction } from '../compositeBarActions.js';
-import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
+import { FONT, inspectFontSize, updateActivityBarSize } from '../../../../base/common/font.js';
export class ActivitybarPart extends Part {
- static readonly ACTION_HEIGHT = 48;
+ static get ACTION_HEIGHT() { return FONT.activityBarSize48; }
static readonly pinnedViewContainersKey = 'workbench.activity.pinnedViewlets2';
static readonly placeholderViewContainersKey = 'workbench.activity.placeholderViewlets';
@@ -74,6 +74,9 @@ export class ActivitybarPart extends Part {
if (e.affectsConfiguration('workbench.activityBar.experimental.fontFamily')) {
this.applyActivityBarFontFamily();
}
+ if (e.affectsConfiguration('workbench.activityBar.experimental.fontSize')) {
+ this.applyActivityBarFontSize();
+ }
}));
}
@@ -111,15 +114,34 @@ export class ActivitybarPart extends Part {
this.element = parent;
this.content = append(this.element, $('.content'));
+ // Apply font settings before show() so composite bar uses correct sizes
+ this.applyActivityBarFontFamily(parent);
+ this.applyActivityBarFontSize(parent);
+
if (this.layoutService.isVisible(Parts.ACTIVITYBAR_PART)) {
this.show();
}
- this.applyActivityBarFontFamily(parent);
-
return this.content;
}
+ private applyActivityBarFontSize(container?: HTMLElement): void {
+ const target = container ?? this.getContainer();
+ if (!target) {
+ return;
+ }
+
+ const { isUserSet, size } = inspectFontSize(this.configurationService, 'workbench.activityBar.experimental.fontSize', 16);
+
+ if (isUserSet) {
+ updateActivityBarSize(size);
+ target.style.setProperty('--vscode-workbench-activitybar-font-size', `${size}px`);
+ } else {
+ updateActivityBarSize(16);
+ target.style.removeProperty('--vscode-workbench-activitybar-font-size');
+ }
+ }
+
private applyActivityBarFontFamily(container?: HTMLElement): void {
const target = container ?? this.getContainer();
if (!target) {
diff --git a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css
index 7cd25d0..680dc73 100644
--- a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css
+++ b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css
@@ -7,6 +7,7 @@
width: 48px;
height: 100%;
font-family: var(--vscode-workbench-activitybar-font-family, inherit);
+ font-size: var(--vscode-workbench-activitybar-font-size, var(--vscode-workbench-font-size, 16px));
}
.monaco-workbench .activitybar.bordered::before {
diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css
index 76c7b07..6faf068 100644
--- a/src/vs/workbench/browser/parts/panel/media/panelpart.css
+++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css
@@ -10,6 +10,7 @@
.monaco-workbench .part.panel > .content {
font-family: var(--vscode-workbench-panel-font-family, inherit);
+ font-size: var(--vscode-workbench-panel-font-size, var(--vscode-workbench-font-size, 13px));
}
.monaco-workbench .part.panel.bottom .composite.title {
diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts
index a5d3ff4..b9b240d 100644
--- a/src/vs/workbench/browser/parts/panel/panelPart.ts
+++ b/src/vs/workbench/browser/parts/panel/panelPart.ts
@@ -31,6 +31,7 @@ import { getContextMenuActions } from '../../../../platform/actions/browser/menu
import { IPaneCompositeBarOptions } from '../paneCompositeBar.js';
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
+import { FONT, inspectFontSize, updatePanelSize } from '../../../../base/common/font.js';
export class PanelPart extends AbstractPaneCompositePart {
@@ -113,6 +114,9 @@ export class PanelPart extends AbstractPaneCompositePart {
if (e.affectsConfiguration('workbench.bottomPane.experimental.fontFamily')) {
this.applyPanelFontFamily();
}
+ if (e.affectsConfiguration('workbench.bottomPane.experimental.fontSize')) {
+ this.applyPanelFontSize();
+ }
}));
}
@@ -131,6 +135,24 @@ export class PanelPart extends AbstractPaneCompositePart {
}
this.applyPanelFontFamily(container);
+ this.applyPanelFontSize(container);
+ }
+
+ private applyPanelFontSize(container?: HTMLElement): void {
+ const target = container ?? this.getContainer();
+ if (!target) {
+ return;
+ }
+
+ const { isUserSet, size } = inspectFontSize(this.configurationService, 'workbench.bottomPane.experimental.fontSize', 13);
+
+ if (isUserSet) {
+ updatePanelSize(size);
+ target.style.setProperty('--vscode-workbench-panel-font-size', `${size}px`);
+ } else {
+ updatePanelSize(13);
+ target.style.removeProperty('--vscode-workbench-panel-font-size');
+ }
}
private applyPanelFontFamily(container?: HTMLElement): void {
diff --git a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css
index b633ee1..7621d4e 100644
--- a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css
+++ b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css
@@ -7,8 +7,8 @@
box-sizing: border-box;
cursor: default;
width: 100%;
- height: 22px;
- font-size: 12px;
+ height: var(--vscode-workbench-statusbar-height, 22px);
+ font-size: var(--vscode-workbench-statusbar-font-size, var(--vscode-workbench-font-size, 12px));
font-family: var(--vscode-workbench-statusbar-font-family, inherit);
display: flex;
overflow: hidden;
@@ -58,7 +58,7 @@
.monaco-workbench .part.statusbar > .items-container > .statusbar-item {
display: inline-block;
- line-height: 22px;
+ line-height: var(--vscode-workbench-statusbar-height, 22px);
height: 100%;
vertical-align: top;
max-width: 40vw;
diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts
index 62e78d0..d5dc64a 100644
--- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts
+++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts
@@ -37,6 +37,7 @@ import { Emitter, Event } from '../../../../base/common/event.js';
import { IView } from '../../../../base/browser/ui/grid/grid.js';
import { isManagedHoverTooltipHTMLElement, isManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
+import { FONT, inspectFontSize, updateStatusBarSize } from '../../../../base/common/font.js';
export interface IStatusbarEntryContainer extends IDisposable {
@@ -119,14 +120,14 @@ interface IPendingStatusbarEntry {
class StatusbarPart extends Part implements IStatusbarEntryContainer {
- static readonly HEIGHT = 22;
+ static get HEIGHT() { return FONT.statusBarSize22; }
//#region IView
readonly minimumWidth: number = 0;
readonly maximumWidth: number = Number.POSITIVE_INFINITY;
- readonly minimumHeight: number = StatusbarPart.HEIGHT;
- readonly maximumHeight: number = StatusbarPart.HEIGHT;
+ get minimumHeight(): number { return FONT.statusBarSize22; }
+ get maximumHeight(): number { return FONT.statusBarSize22; }
//#endregion
@@ -169,6 +170,9 @@ class StatusbarPart extends Part implements IStatusbarEntryContainer {
if (e.affectsConfiguration('workbench.statusBar.experimental.fontFamily')) {
this.applyStatusBarFontFamily();
}
+ if (e.affectsConfiguration('workbench.statusBar.experimental.fontSize')) {
+ this.applyStatusBarFontSize();
+ }
}));
this.viewModel = this._register(new StatusbarViewModel(storageService));
@@ -436,10 +440,33 @@ class StatusbarPart extends Part implements IStatusbarEntryContainer {
this.createInitialStatusbarEntries();
this.applyStatusBarFontFamily(this.element);
+ this.applyStatusBarFontSize(this.element);
return this.element;
}
+ private applyStatusBarFontSize(container?: HTMLElement): void {
+ const target = container ?? this.getContainer();
+ if (!target) {
+ return;
+ }
+
+ const { isUserSet, size } = inspectFontSize(this.configurationService, 'workbench.statusBar.experimental.fontSize', 12);
+
+ if (isUserSet) {
+ updateStatusBarSize(size);
+ target.style.setProperty('--vscode-workbench-statusbar-font-size', `${size}px`);
+ target.style.setProperty('--vscode-workbench-statusbar-height', `${FONT.statusBarSize22}px`);
+ } else {
+ updateStatusBarSize(12);
+ target.style.removeProperty('--vscode-workbench-statusbar-font-size');
+ target.style.removeProperty('--vscode-workbench-statusbar-height');
+ }
+
+ // Notify grid layout that height constraints changed
+ this._onDidChange.fire(undefined);
+ }
+
private applyStatusBarFontFamily(container?: HTMLElement): void {
const target = container ?? this.getContainer();
if (!target) {
@@ -761,7 +788,7 @@ export class AuxiliaryStatusbarPart extends StatusbarPart implements IAuxiliaryS
private static COUNTER = 1;
- readonly height = StatusbarPart.HEIGHT;
+ get height() { return StatusbarPart.HEIGHT; }
constructor(
readonly container: HTMLElement,
diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts
index 8a9eb0e..5bb0959 100644
--- a/src/vs/workbench/browser/workbench.contribution.ts
+++ b/src/vs/workbench/browser/workbench.contribution.ts
@@ -705,6 +705,38 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
markdownDescription: localize('activityBarFontFamily', "Controls the font family in the activity bar."),
'tags': ['accessibility', 'experimental']
},
+ 'workbench.statusBar.experimental.fontSize': {
+ type: 'number',
+ default: 12,
+ minimum: 6,
+ maximum: 32,
+ markdownDescription: localize('statusBarFontSize', "Controls the font size in pixels for the status bar."),
+ 'tags': ['accessibility', 'experimental']
+ },
+ 'workbench.bottomPane.experimental.fontSize': {
+ type: 'number',
+ default: 13,
+ minimum: 6,
+ maximum: 32,
+ markdownDescription: localize('bottomPaneFontSize', "Controls the font size in pixels for the bottom panel."),
+ 'tags': ['accessibility', 'experimental']
+ },
+ 'workbench.activityBar.experimental.fontSize': {
+ type: 'number',
+ default: 16,
+ minimum: 6,
+ maximum: 32,
+ markdownDescription: localize('activityBarFontSize', "Controls the font size in pixels for the activity bar."),
+ 'tags': ['accessibility', 'experimental']
+ },
+ 'workbench.tabs.experimental.fontSize': {
+ type: 'number',
+ default: 13,
+ minimum: 6,
+ maximum: 32,
+ markdownDescription: localize('tabsFontSize', "Controls the font size in pixels for editor tabs."),
+ 'tags': ['accessibility', 'experimental']
+ },
'workbench.settings.editor': {
'type': 'string',
'enum': ['ui', 'json'],
diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts
index ee4cbf8..4d7a787 100644
--- a/src/vs/workbench/browser/workbench.ts
+++ b/src/vs/workbench/browser/workbench.ts
@@ -7,6 +7,7 @@ import './style.js';
import { runWhenWindowIdle } from '../../base/browser/dom.js';
import { Event, Emitter, setGlobalLeakWarningThreshold } from '../../base/common/event.js';
import { RunOnceScheduler, timeout } from '../../base/common/async.js';
+import { inspectFontSize } from '../../base/common/font.js';
import { isFirefox, isSafari, isChrome } from '../../base/browser/browser.js';
import { mark } from '../../base/common/performance.js';
import { onUnexpectedError, setUnexpectedErrorHandler } from '../../base/common/errors.js';
@@ -303,15 +304,7 @@ export class Workbench extends Layout {
private fontSize: number | undefined;
private fontSizeUserSet: boolean | undefined;
private updateFontSize(configurationService: IConfigurationService) {
- const raw = configurationService.getValue<number>('workbench.experimental.fontSize');
- const size = Math.max(6, Math.min(32, typeof raw === 'number' ? raw : 13));
-
- const inspected = configurationService.inspect<number>('workbench.experimental.fontSize');
- const isUserSet = inspected.userValue !== undefined
- || inspected.userLocalValue !== undefined
- || inspected.userRemoteValue !== undefined
- || inspected.workspaceValue !== undefined
- || inspected.workspaceFolderValue !== undefined;
+ const { isUserSet, size } = inspectFontSize(configurationService, 'workbench.experimental.fontSize', 13);
if (this.fontSize === size && this.fontSizeUserSet === isUserSet) {
return;

View File

@@ -0,0 +1,223 @@
diff --git a/src/vs/workbench/browser/parts/editor/editorTabsControl.ts b/src/vs/workbench/browser/parts/editor/editorTabsControl.ts
index a946cb7..4db07a2 100644
--- a/src/vs/workbench/browser/parts/editor/editorTabsControl.ts
+++ b/src/vs/workbench/browser/parts/editor/editorTabsControl.ts
@@ -47,6 +47,7 @@ import { IBaseActionViewItemOptions } from '../../../../base/browser/ui/actionba
import { MarkdownString } from '../../../../base/common/htmlContent.js';
import { IManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
+import { FONT, inspectFontSize, updateTabsSize } from '../../../../base/common/font.js';
import { applyDragImage } from '../../../../base/browser/ui/dnd/dnd.js';
export class EditorCommandsContextActionRunner extends ActionRunner {
@@ -100,10 +101,12 @@ export abstract class EditorTabsControl extends Themable implements IEditorTabsC
protected readonly groupTransfer = LocalSelectionTransfer.getInstance<DraggedEditorGroupIdentifier>();
protected readonly treeItemsTransfer = LocalSelectionTransfer.getInstance<DraggedTreeItemsIdentifier>();
- private static readonly EDITOR_TAB_HEIGHT = {
- normal: 35 as const,
- compact: 22 as const
- };
+ private static get EDITOR_TAB_HEIGHT() {
+ return {
+ normal: FONT.tabsSize35,
+ compact: FONT.tabsSize22
+ };
+ }
protected editorActionsToolbarContainer: HTMLElement | undefined;
private editorActionsToolbar: WorkbenchToolBar | undefined;
@@ -153,6 +156,11 @@ export abstract class EditorTabsControl extends Themable implements IEditorTabsC
if (e.affectsConfiguration('workbench.tabs.experimental.fontFamily')) {
this.applyTabsFontFamily();
}
+ if (e.affectsConfiguration('workbench.tabs.experimental.fontSize')) {
+ this.applyTabsFontSize();
+ this.updateTabHeight();
+ this.groupView.relayout();
+ }
}));
// Context Keys
@@ -176,11 +184,37 @@ export abstract class EditorTabsControl extends Themable implements IEditorTabsC
}
protected create(parent: HTMLElement): HTMLElement {
+ this.applyTabsFontSize(parent);
this.updateTabHeight();
this.applyTabsFontFamily(parent);
return parent;
}
+ private applyTabsFontSize(container?: HTMLElement): void {
+ const target = container ?? this.parent;
+ if (!target) {
+ return;
+ }
+
+ const { isUserSet, size } = inspectFontSize(this.configurationService, 'workbench.tabs.experimental.fontSize', 13);
+
+ if (isUserSet) {
+ updateTabsSize(size);
+ target.style.setProperty('--vscode-workbench-tabs-font-size', `${size}px`);
+ target.style.setProperty('--vscode-workbench-tabs-compact-height', `${FONT.tabsSize22}px`);
+ target.style.setProperty('--vscode-workbench-tabs-sticky-compact-width', `${FONT.tabsSize38}px`);
+ target.style.setProperty('--vscode-workbench-tabs-sticky-shrink-width', `${FONT.tabsSize80}px`);
+ target.style.setProperty('--vscode-workbench-tabs-fit-width', `${FONT.tabsSize120}px`);
+ } else {
+ updateTabsSize(13);
+ target.style.removeProperty('--vscode-workbench-tabs-font-size');
+ target.style.removeProperty('--vscode-workbench-tabs-compact-height');
+ target.style.removeProperty('--vscode-workbench-tabs-sticky-compact-width');
+ target.style.removeProperty('--vscode-workbench-tabs-sticky-shrink-width');
+ target.style.removeProperty('--vscode-workbench-tabs-fit-width');
+ }
+ }
+
private applyTabsFontFamily(container?: HTMLElement): void {
const target = container ?? this.parent;
if (!target) {
diff --git a/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css b/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css
index e9e0b2b..fc1bebe 100644
--- a/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css
+++ b/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css
@@ -23,7 +23,7 @@
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label a,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label a {
- font-size: 13px;
+ font-size: var(--vscode-workbench-tabs-font-size, var(--vscode-workbench-font-size, 13px));
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .monaco-icon-label::before,
diff --git a/src/vs/workbench/browser/parts/editor/media/editortitlecontrol.css b/src/vs/workbench/browser/parts/editor/media/editortitlecontrol.css
index a24f761..8c72d17 100644
--- a/src/vs/workbench/browser/parts/editor/media/editortitlecontrol.css
+++ b/src/vs/workbench/browser/parts/editor/media/editortitlecontrol.css
@@ -7,23 +7,23 @@
.monaco-workbench .part.editor > .content .editor-group-container > .title .breadcrumbs-below-tabs .breadcrumbs-control {
flex: 1 100%;
- height: 22px;
+ height: var(--vscode-workbench-tabs-compact-height, 22px);
cursor: default;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .breadcrumbs-below-tabs .breadcrumbs-control .monaco-icon-label {
- height: 22px;
- line-height: 22px;
+ height: var(--vscode-workbench-tabs-compact-height, 22px);
+ line-height: var(--vscode-workbench-tabs-compact-height, 22px);
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .breadcrumbs-below-tabs .breadcrumbs-control .monaco-icon-label::before {
- height: 22px; /* tweak the icon size of the editor labels when icons are enabled */
+ height: var(--vscode-workbench-tabs-compact-height, 22px); /* tweak the icon size of the editor labels when icons are enabled */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .breadcrumbs-below-tabs .breadcrumbs-control .outline-element-icon {
padding-right: 3px;
- height: 22px; /* tweak the icon size of the editor labels when icons are enabled */
- line-height: 22px;
+ height: var(--vscode-workbench-tabs-compact-height, 22px); /* tweak the icon size of the editor labels when icons are enabled */
+ line-height: var(--vscode-workbench-tabs-compact-height, 22px);
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .breadcrumbs-below-tabs .breadcrumbs-control .monaco-breadcrumb-item {
@@ -32,7 +32,7 @@
.monaco-workbench .part.editor > .content .editor-group-container > .title .breadcrumbs-below-tabs .breadcrumbs-control .monaco-breadcrumb-item::before {
width: 16px;
- height: 22px;
+ height: var(--vscode-workbench-tabs-compact-height, 22px);
display: flex;
align-items: center;
justify-content: center;
diff --git a/src/vs/workbench/browser/parts/editor/media/multieditortabscontrol.css b/src/vs/workbench/browser/parts/editor/media/multieditortabscontrol.css
index 924d9b3..58efc4d 100644
--- a/src/vs/workbench/browser/parts/editor/media/multieditortabscontrol.css
+++ b/src/vs/workbench/browser/parts/editor/media/multieditortabscontrol.css
@@ -160,7 +160,7 @@
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit {
- width: 120px;
+ width: var(--vscode-workbench-tabs-fit-width, 120px);
min-width: fit-content;
flex-shrink: 0;
}
@@ -183,7 +183,7 @@
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink {
- min-width: 80px;
+ min-width: var(--vscode-workbench-tabs-sticky-shrink-width, 80px);
flex-basis: 0; /* all tabs are even */
flex-grow: 1; /* all tabs grow even */
max-width: fit-content;
@@ -210,9 +210,9 @@
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.sticky-compact {
/** Sticky compact tabs have a fixed width of 38px */
- width: 38px;
- min-width: 38px;
- max-width: 38px;
+ width: var(--vscode-workbench-tabs-sticky-compact-width, 38px);
+ min-width: var(--vscode-workbench-tabs-sticky-compact-width, 38px);
+ max-width: var(--vscode-workbench-tabs-sticky-compact-width, 38px);
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky-shrink,
@@ -220,9 +220,9 @@
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.sticky-shrink {
/** Sticky shrink tabs have a fixed width of 80px */
- width: 80px;
- min-width: 80px;
- max-width: 80px;
+ width: var(--vscode-workbench-tabs-sticky-shrink-width, 80px);
+ min-width: var(--vscode-workbench-tabs-sticky-shrink-width, 80px);
+ max-width: var(--vscode-workbench-tabs-sticky-shrink-width, 80px);
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-fit.sticky-compact,
@@ -257,7 +257,7 @@
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-left,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.tab-actions-left {
- min-width: 80px; /* make more room for close button when it shows to the left */
+ min-width: var(--vscode-workbench-tabs-sticky-shrink-width, 80px); /* make more room for close button when it shows to the left */
padding-right: 5px; /* we need less room when sizing is shrink/fixed */
}
diff --git a/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts b/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts
index b0befd9..ef06bcc 100644
--- a/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts
+++ b/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts
@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import './media/multieditortabscontrol.css';
+import { FONT } from '../../../../base/common/font.js';
import { isLinux, isMacintosh, isWindows } from '../../../../base/common/platform.js';
import { shorten } from '../../../../base/common/labels.js';
import { EditorResourceAccessor, Verbosity, IEditorPartOptions, SideBySideEditor, DEFAULT_EDITOR_ASSOCIATION, EditorInputCapabilities, IUntypedEditorInput, preventEditorClose, EditorCloseMethod, EditorsOrder, IToolbarActions } from '../../../common/editor.js';
@@ -94,11 +95,13 @@ export class MultiEditorTabsControl extends EditorTabsControl {
large: 10 as const
};
- private static readonly TAB_WIDTH = {
- compact: 38 as const,
- shrink: 80 as const,
- fit: 120 as const
- };
+ private static get TAB_WIDTH() {
+ return {
+ compact: FONT.tabsSize38,
+ shrink: FONT.tabsSize80,
+ fit: FONT.tabsSize120
+ };
+ }
private static readonly DRAG_OVER_OPEN_TAB_THRESHOLD = 1500;