Add settings for fixed-width tabs (#181729)

* Add settings for fixed-width tabs

This is meant at least partially to address #40290 and
is a continuation of the unfinished work from #40750.

* Only apply fixed width when the setting is on

* Implement chrome-like tab width behavior

Tabs shrink uniformly (down to a limit) but stay fixed-width
when the mouse is over the tab bar.

* Rename width setting to max width

* Make the ifs more readable

* Have event handlers only if the option is set

* 🎨

* Handle sizing artifacts present with wrapping tabs

To achieve this, it's best to remove the transition delay.

* Rename setting to apply only for fixed-sized tabs

* Set default fixed max tab width to 160px

* Minor code tweaks from review comments

* formatting

Co-authored-by: Benjamin Pasero <benjamin.pasero@gmail.com>

* Use disposable listeners

* Remove redundant check for last-in-row

* Apply fade gradient from shrink tabSizing to fixed

* Trying to make the code cleaner and understandable

* Remove transition

On advice of @bpasero, removed transition because
the editor doesn't really use transition that much.

* some cleanup

* fix typo

* Simplify workaround for the overflow issue

* 💄

* 💄

* Let the tabs fix their width before closing the editor

* 💄

---------

Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com>
Co-authored-by: Benjamin Pasero <benjamin.pasero@gmail.com>
This commit is contained in:
Jacek Kopecký
2023-05-22 16:32:52 +01:00
committed by GitHub
parent 4d0b34bf48
commit cbbd9220c2
9 changed files with 164 additions and 36 deletions
@@ -692,6 +692,8 @@
"--tab-border-top-color",
"--tab-dirty-border-top-color",
"--tabs-border-bottom-color",
"--tab-sizing-current-width",
"--tab-sizing-fixed-max-width",
"--testMessageDecorationFontFamily",
"--testMessageDecorationFontSize",
"--title-border-bottom-color",
@@ -28,6 +28,7 @@ export const DEFAULT_EDITOR_PART_OPTIONS: IEditorPartOptions = {
highlightModifiedTabs: false,
tabCloseButton: 'right',
tabSizing: 'fit',
tabSizingFixedMaxWidth: 160,
pinnedTabSizing: 'normal',
titleScrollbarSizing: 'default',
focusRecentEditorAfterClose: true,
@@ -1337,6 +1337,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
private doCloseEditor(editor: EditorInput, focusNext = (this.accessor.activeGroup === this), internalOptions?: IInternalEditorCloseOptions): void {
let index: number | undefined;
// Forward to title control unless skipped via internal options
if (!internalOptions?.skipTitleUpdate) {
this.titleAreaControl.beforeCloseEditor(editor, index);
}
// Closing the active editor of the group is a bit more work
if (this.model.isActive(editor)) {
index = this.doCloseActiveEditor(focusNext, internalOptions);
@@ -111,7 +111,9 @@
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.tab-actions-right,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.tab-actions-off:not(.sticky-compact) {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.tab-actions-off:not(.sticky-compact),
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.has-icon.tab-actions-right,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.has-icon.tab-actions-off:not(.sticky-compact) {
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab actions is not left (unless sticky-compact) */
}
@@ -121,6 +123,19 @@
flex-shrink: 0;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed {
min-width: var(--tab-sizing-current-width, 50px);
max-width: var(--tab-sizing-current-width, var(--tab-sizing-fixed-max-width, 160px));
flex: 1 0 0; /* all tabs are evenly sized and grow */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.last-in-row {
/* prevent last tab in a row from moving to next row when tab widths are
* fixed in case rounding errors make the fixed tabs grow over the size
* of the tabs container */
min-width: calc(var(--tab-sizing-current-width, 50px) - 1px);
}
.monaco-workbench .part.editor > .content .editor-group-container > .title > .tabs-and-actions-container.wrapping .tabs-container > .tab.sizing-fit.last-in-row:not(:last-child) {
flex-grow: 1; /* grow the last tab in a row for a more homogeneous look except for last row (#113801) */
}
@@ -134,20 +149,23 @@
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky-compact,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky-compact,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.sticky-compact,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky-shrink,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky-shrink {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky-shrink,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.sticky-shrink {
/** Sticky compact/shrink tabs do not scroll in case of overflow and are always above unsticky tabs which scroll under */
/** Sticky compact/shrink/fixed tabs do not scroll in case of overflow and are always above unsticky tabs which scroll under */
position: sticky;
z-index: 8;
/** Sticky compact/shrink tabs are even and never grow */
/** Sticky compact/shrink/fixed tabs are even and never grow */
flex-basis: 0;
flex-grow: 0;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky-compact,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky-compact {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky-compact,
.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;
@@ -156,7 +174,8 @@
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky-shrink,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky-shrink {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky-shrink,
.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;
@@ -166,22 +185,27 @@
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-fit.sticky-compact,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-shrink.sticky-compact,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-fixed.sticky-compact,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-fit.sticky-shrink,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-shrink.sticky-shrink {
position: static; /** disable sticky positions for sticky compact/shrink tabs if the available space is too little */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-shrink.sticky-shrink,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-fixed.sticky-shrink {
position: static; /** disable sticky positions for sticky compact/shrink/fixed tabs if the available space is too little */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-left::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-off::after {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-off::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.tab-actions-left::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.tab-actions-off::after {
content: '';
display: flex;
flex: 0;
width: 5px; /* reserve space to hide tab fade when close button is left or off (fixes https://github.com/microsoft/vscode/issues/45728) */
}
.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-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 */
padding-right: 5px; /* we need less room when sizing is shrink */
padding-right: 5px; /* we need less room when sizing is shrink/fixed */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dragged {
@@ -244,11 +268,13 @@
line-height: 35px; /* aligns icon and label vertically centered in the tab */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink .tab-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink .tab-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed .tab-label {
position: relative;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .tab-label > .monaco-icon-label-container::after {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .tab-label > .monaco-icon-label-container::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed > .tab-label > .monaco-icon-label-container::after {
content: ''; /* enables a linear gradient to overlay the end of the label when tabs overflow */
position: absolute;
right: 0;
@@ -261,12 +287,14 @@
height: calc(100% - 2px);
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink:focus > .tab-label > .monaco-icon-label-container::after {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink:focus > .tab-label > .monaco-icon-label-container::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed:focus > .tab-label > .monaco-icon-label-container::after {
opacity: 0; /* when tab has the focus this shade breaks the tab border (fixes https://github.com/microsoft/vscode/issues/57819) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .tab-label.tab-label-has-badge::after {
padding-right: 5px; /* with tab sizing shrink and badges, we want a right-padding because the close button is hidden */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .tab-label.tab-label-has-badge::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed > .tab-label.tab-label-has-badge::after {
padding-right: 5px; /* with tab sizing shrink/fixed and badges, we want a right-padding because the close button is hidden */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sticky-compact:not(.has-icon) .monaco-icon-label {
@@ -278,13 +306,16 @@
overflow: visible; /* fixes https://github.com/microsoft/vscode/issues/20182 */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-container {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-container,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed > .monaco-icon-label > .monaco-icon-label-container {
text-overflow: clip;
flex: none;
}
.monaco-workbench.hc-black .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-container,
.monaco-workbench.hc-light .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-container {
.monaco-workbench.hc-light .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-container,
.monaco-workbench.hc-black .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed > .monaco-icon-label > .monaco-icon-label-container,
.monaco-workbench.hc-light .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed > .monaco-icon-label > .monaco-icon-label-container {
text-overflow: ellipsis;
}
@@ -300,15 +331,20 @@
width: 28px;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-shrink > .tab-actions {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-shrink > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-fixed > .tab-actions {
flex: 0;
overflow: hidden; /* let the tab actions be pushed out of view when sizing is set to shrink to make more room */
overflow: hidden; /* let the tab actions be pushed out of view when sizing is set to shrink/fixed to make more room */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty.tab-actions-right.sizing-shrink > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sticky.tab-actions-right.sizing-shrink > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-shrink:hover > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-shrink > .tab-actions:focus-within {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-shrink > .tab-actions:focus-within,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty.tab-actions-right.sizing-fixed > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sticky.tab-actions-right.sizing-fixed > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-fixed:hover > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-fixed > .tab-actions:focus-within {
overflow: visible; /* ...but still show the tab actions on hover, focus and when dirty or sticky */
}
@@ -366,8 +402,9 @@
padding-right: 10px; /* give a little bit more room if tab actions is off */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-off:not(.sticky-compact) {
padding-right: 5px; /* we need less room when sizing is shrink (unless tab is sticky-compact) */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-off:not(.sticky-compact),
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.tab-actions-off:not(.sticky-compact) {
padding-right: 5px; /* we need less room when sizing is shrink/fixed (unless tab is sticky-compact) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.dirty-border-top > .tab-actions {
@@ -143,6 +143,10 @@ export class NoTabsTitleControl extends TitleControl {
}
}
beforeCloseEditor(): void {
// Nothing to do before closing an editor
}
closeEditor(editor: EditorInput, index: number | undefined): void {
this.ifActiveEditorChanged(() => this.redraw());
}
@@ -108,6 +108,7 @@ export class TabsTitleControl extends TitleControl {
private tabsContainer: HTMLElement | undefined;
private editorToolbarContainer: HTMLElement | undefined;
private tabsScrollbar: ScrollableElement | undefined;
private tabSizingFixedDisposables: DisposableStore | undefined;
private readonly closeEditorAction = this._register(this.instantiationService.createInstance(CloseOneEditorAction, CloseOneEditorAction.ID, CloseOneEditorAction.LABEL));
private readonly unpinEditorAction = this._register(this.instantiationService.createInstance(UnpinEditorAction, UnpinEditorAction.ID, UnpinEditorAction.LABEL));
@@ -130,6 +131,7 @@ export class TabsTitleControl extends TitleControl {
private path: IPath = isWindows ? win32 : posix;
private lastMouseWheelEventTime = 0;
private isMouseOverTabs = false;
constructor(
parent: HTMLElement,
@@ -176,6 +178,9 @@ export class TabsTitleControl extends TitleControl {
this.tabsContainer.classList.add('tabs-container');
this._register(Gesture.addTarget(this.tabsContainer));
this.tabSizingFixedDisposables = this._register(new DisposableStore());
this.updateTabSizing(false);
// Tabs Scrollbar
this.tabsScrollbar = this._register(this.createTabsScrollbar(this.tabsContainer));
this.tabsAndActionsContainer.appendChild(this.tabsScrollbar.getDomNode());
@@ -222,6 +227,44 @@ export class TabsTitleControl extends TitleControl {
});
}
private updateTabSizing(fromEvent: boolean): void {
const [tabsContainer, tabSizingFixedDisposables] = assertAllDefined(this.tabsContainer, this.tabSizingFixedDisposables);
tabSizingFixedDisposables.clear();
const options = this.accessor.partOptions;
if (options.tabSizing === 'fixed') {
tabsContainer.style.setProperty('--tab-sizing-fixed-max-width', `${options.tabSizingFixedMaxWidth}px`);
// For https://github.com/microsoft/vscode/issues/40290 we want to
// preserve the current tab widths as long as the mouse is over the
// tabs so that you can quickly close them via mouse click. For that
// we track mouse movements over the tabs container.
tabSizingFixedDisposables.add(addDisposableListener(tabsContainer, EventType.MOUSE_ENTER, () => {
this.isMouseOverTabs = true;
}));
tabSizingFixedDisposables.add(addDisposableListener(tabsContainer, EventType.MOUSE_LEAVE, () => {
this.isMouseOverTabs = false;
this.updateTabsFixedWidth(false);
}));
} else if (fromEvent) {
tabsContainer.style.removeProperty('--tab-sizing-fixed-max-width');
this.updateTabsFixedWidth(false);
}
}
private updateTabsFixedWidth(fixed: boolean): void {
this.forEachTab((editor, index, tabContainer) => {
if (fixed) {
const { width } = tabContainer.getBoundingClientRect();
tabContainer.style.setProperty('--tab-sizing-current-width', `${width}px`);
} else {
tabContainer.style.removeProperty('--tab-sizing-current-width');
}
});
}
private getTabsScrollbarSizing(): number {
if (this.accessor.partOptions.titleScrollbarSizing !== 'large') {
return TabsTitleControl.SCROLLBAR_SIZES.default;
@@ -514,6 +557,18 @@ export class TabsTitleControl extends TitleControl {
labelA.ariaLabel === labelB.ariaLabel;
}
beforeCloseEditor(): void {
// Fix tabs width if the mouse is over tabs and
// before closing a tab when tab sizing is 'fixed'.
// This helps keeping the close button stable under
// the mouse and allows for rapid closing of tabs.
if (this.isMouseOverTabs && this.accessor.partOptions.tabSizing === 'fixed') {
this.updateTabsFixedWidth(true);
}
}
closeEditor(editor: EditorInput, index: number | undefined): void {
this.handleClosedEditors(index);
}
@@ -663,6 +718,14 @@ export class TabsTitleControl extends TitleControl {
this.updateTabsScrollbarSizing();
}
// Update tabs sizing
if (
oldOptions.tabSizingFixedMaxWidth !== newOptions.tabSizingFixedMaxWidth ||
oldOptions.tabSizing !== newOptions.tabSizing
) {
this.updateTabSizing(true);
}
// Redraw tabs when other options change
if (
oldOptions.labelFormat !== newOptions.labelFormat ||
@@ -1229,7 +1292,7 @@ export class TabsTitleControl extends TitleControl {
}
const tabSizing = isTabSticky && options.pinnedTabSizing === 'shrink' ? 'shrink' /* treat sticky shrink tabs as tabSizing: 'shrink' */ : options.tabSizing;
for (const option of ['fit', 'shrink']) {
for (const option of ['fit', 'shrink', 'fixed']) {
tabContainer.classList.toggle(`sizing-${option}`, tabSizing === option);
}
@@ -2109,7 +2172,7 @@ registerThemingParticipant((theme, collector) => {
`);
}
// Fade out styles via linear gradient (when tabs are set to shrink)
// Fade out styles via linear gradient (when tabs are set to shrink or fixed)
// But not when:
// - in high contrast theme
// - if we have a contrast border (which draws an outline - https://github.com/microsoft/vscode/issues/109117)
@@ -2132,11 +2195,13 @@ registerThemingParticipant((theme, collector) => {
// Adjust gradient for focused and unfocused hover background
const makeTabHoverBackgroundRule = (color: Color, colorDrag: Color, hasFocus = false) => `
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):not(.sticky-compact):hover > .tab-label > .monaco-icon-label-container::after {
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):not(.sticky-compact):hover > .tab-label > .monaco-icon-label-container::after,
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-fixed:not(.dragged):not(.sticky-compact):hover > .tab-label > .monaco-icon-label-container::after {
background: linear-gradient(to left, ${color}, transparent) !important;
}
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):not(.sticky-compact):hover > .tab-label > .monaco-icon-label-container::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):not(.sticky-compact):hover > .tab-label > .monaco-icon-label-container::after,
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-fixed:not(.dragged):not(.sticky-compact):hover > .tab-label > .monaco-icon-label-container::after {
background: linear-gradient(to left, ${colorDrag}, transparent) !important;
}
`;
@@ -2160,18 +2225,22 @@ registerThemingParticipant((theme, collector) => {
const adjustedColorDrag = editorDragAndDropBackground.flatten(adjustedTabDragBackground);
collector.addRule(`
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.active):not(.dragged):not(.sticky-compact) > .tab-label > .monaco-icon-label-container::after,
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.dragged):not(.sticky-compact) > .tab-label > .monaco-icon-label-container::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.dragged):not(.sticky-compact) > .tab-label > .monaco-icon-label-container::after,
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-fixed.dragged-over:not(.active):not(.dragged):not(.sticky-compact) > .tab-label > .monaco-icon-label-container::after,
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-fixed.dragged-over:not(.dragged):not(.sticky-compact) > .tab-label > .monaco-icon-label-container::after {
background: linear-gradient(to left, ${adjustedColorDrag}, transparent) !important;
}
`);
}
const makeTabBackgroundRule = (color: Color, colorDrag: Color, focused: boolean, active: boolean) => `
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged):not(.sticky-compact) > .tab-label > .monaco-icon-label-container::after {
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged):not(.sticky-compact) > .tab-label > .monaco-icon-label-container::after,
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-fixed${active ? '.active' : ''}:not(.dragged):not(.sticky-compact) > .tab-label > .monaco-icon-label-container::after {
background: linear-gradient(to left, ${color}, transparent);
}
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged):not(.sticky-compact) > .tab-label > .monaco-icon-label-container::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged):not(.sticky-compact) > .tab-label > .monaco-icon-label-container::after,
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-fixed${active ? '.active' : ''}:not(.dragged):not(.sticky-compact) > .tab-label > .monaco-icon-label-container::after {
background: linear-gradient(to left, ${colorDrag}, transparent);
}
`;
@@ -418,6 +418,8 @@ export abstract class TitleControl extends Themable {
abstract openEditors(editors: EditorInput[]): void;
abstract beforeCloseEditor(editor: EditorInput, index: number | undefined): void;
abstract closeEditor(editor: EditorInput, index: number | undefined): void;
abstract closeEditors(editors: EditorInput[]): void;
@@ -141,13 +141,20 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
},
'workbench.editor.tabSizing': {
'type': 'string',
'enum': ['fit', 'shrink'],
'enum': ['fit', 'shrink', 'fixed'],
'default': 'fit',
'enumDescriptions': [
localize('workbench.editor.tabSizing.fit', "Always keep tabs large enough to show the full editor label."),
localize('workbench.editor.tabSizing.shrink', "Allow tabs to get smaller when the available space is not enough to show all tabs at once.")
localize('workbench.editor.tabSizing.shrink', "Allow tabs to get smaller when the available space is not enough to show all tabs at once."),
localize('workbench.editor.tabSizing.fixed', "Make all tabs the same size, while allowing them to get smaller when the available space is not enough to show all tabs at once.")
],
'markdownDescription': localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'tabSizing' }, "Controls the sizing of editor tabs. This value is ignored when `#workbench.editor.showTabs#` is disabled.")
'markdownDescription': localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'tabSizing' }, "Controls the size of editor tabs. This value is ignored when `#workbench.editor.showTabs#` is disabled.")
},
'workbench.editor.tabSizingFixedMaxWidth': {
'type': 'number',
'default': 160,
'minimum': 50,
'markdownDescription': localize('workbench.editor.tabSizingFixedMaxWidth', "Controls the maximum width of tabs when {0} is set to {1}.", '`#workbench.editor.tabSizing#`', '`fixed`')
},
'workbench.editor.pinnedTabSizing': {
'type': 'string',
@@ -158,7 +165,7 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
localize('workbench.editor.pinnedTabSizing.compact', "A pinned tab will show in a compact form with only icon or first letter of the editor name."),
localize('workbench.editor.pinnedTabSizing.shrink', "A pinned tab shrinks to a compact fixed size showing parts of the editor name.")
],
'markdownDescription': localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'pinnedTabSizing' }, "Controls the sizing of pinned editor tabs. Pinned tabs are sorted to the beginning of all opened tabs and typically do not close until unpinned. This value is ignored when `#workbench.editor.showTabs#` is disabled.")
'markdownDescription': localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'pinnedTabSizing' }, "Controls the size of pinned editor tabs. Pinned tabs are sorted to the beginning of all opened tabs and typically do not close until unpinned. This value is ignored when `#workbench.editor.showTabs#` is disabled.")
},
'workbench.editor.splitSizing': {
'type': 'string',
@@ -168,7 +175,7 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
localize('workbench.editor.splitSizingDistribute', "Splits all the editor groups to equal parts."),
localize('workbench.editor.splitSizingSplit', "Splits the active editor group to equal parts.")
],
'description': localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'splitSizing' }, "Controls the sizing of editor groups when splitting them.")
'description': localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'splitSizing' }, "Controls the size of editor groups when splitting them.")
},
'workbench.editor.splitOnDragAndDrop': {
'type': 'boolean',
+2 -1
View File
@@ -1100,7 +1100,8 @@ interface IEditorPartConfiguration {
scrollToSwitchTabs?: boolean;
highlightModifiedTabs?: boolean;
tabCloseButton?: 'left' | 'right' | 'off';
tabSizing?: 'fit' | 'shrink';
tabSizing?: 'fit' | 'shrink' | 'fixed';
tabSizingFixedMaxWidth?: number;
pinnedTabSizing?: 'normal' | 'compact' | 'shrink';
titleScrollbarSizing?: 'default' | 'large';
focusRecentEditorAfterClose?: boolean;