Skip to content

Commit a78b270

Browse files
committed
💄
1 parent 30ee2ec commit a78b270

File tree

4 files changed

+53
-69
lines changed

4 files changed

+53
-69
lines changed

build/lib/stylelint/vscode-known-variables.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,7 @@
627627
"--vscode-tab-activeForeground",
628628
"--vscode-tab-activeModifiedBorder",
629629
"--vscode-tab-border",
630+
"--vscode-tab-dragAndDropBorder",
630631
"--vscode-tab-hoverBackground",
631632
"--vscode-tab-hoverBorder",
632633
"--vscode-tab-hoverForeground",

src/vs/workbench/browser/parts/editor/media/multieditortabscontrol.css

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
2929
[z-index] [kind]
3030
12 drag and drop overlay
31-
11 scrollbar
31+
11 scrollbar / tabs dnd border
3232
10 active-tab border-bottom
3333
9 tabs, title border bottom
3434
8 sticky-tab
@@ -461,14 +461,16 @@
461461

462462
/* Drag and drop target */
463463

464-
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.drop-target-left::after ,
464+
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.drop-target-left::after,
465465
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.drop-target-right::before {
466466
content: "";
467467
position: absolute;
468468
top: 0;
469469
height: 100%;
470470
width: 1px;
471+
background-color: var(--vscode-tab-dragAndDropBorder);
471472
pointer-events: none;
473+
z-index: 11;
472474
}
473475

474476
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.drop-target-right::before {
@@ -482,12 +484,7 @@
482484
/* Make drop target edge cases more visible (wrapped tabs & first/last) */
483485

484486
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.last-in-row.drop-target-left:not(:last-child)::after {
485-
right: 1px;
486-
}
487-
488-
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.drop-target-right:first-child:before,
489-
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.last-in-row + .tab.drop-target-right::before {
490-
left: 1px;
487+
right: 0px;
491488
}
492489

493490
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.last-in-row.drop-target-left::after,

src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts

Lines changed: 42 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElemen
2626
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
2727
import { getOrSet } from 'vs/base/common/map';
2828
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
29-
import { TAB_INACTIVE_BACKGROUND, TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND, TAB_UNFOCUSED_INACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_BACKGROUND, TAB_UNFOCUSED_ACTIVE_BORDER, TAB_ACTIVE_BORDER, TAB_HOVER_BACKGROUND, TAB_HOVER_BORDER, TAB_UNFOCUSED_HOVER_BACKGROUND, TAB_UNFOCUSED_HOVER_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND, WORKBENCH_BACKGROUND, TAB_ACTIVE_BORDER_TOP, TAB_UNFOCUSED_ACTIVE_BORDER_TOP, TAB_ACTIVE_MODIFIED_BORDER, TAB_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_ACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_BACKGROUND, TAB_HOVER_FOREGROUND, TAB_UNFOCUSED_HOVER_FOREGROUND, EDITOR_GROUP_HEADER_TABS_BORDER, TAB_LAST_PINNED_BORDER, TAB_DRAG_AND_DROP_BETWEEEN_INDICATOR } from 'vs/workbench/common/theme';
29+
import { TAB_INACTIVE_BACKGROUND, TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND, TAB_UNFOCUSED_INACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_BACKGROUND, TAB_UNFOCUSED_ACTIVE_BORDER, TAB_ACTIVE_BORDER, TAB_HOVER_BACKGROUND, TAB_HOVER_BORDER, TAB_UNFOCUSED_HOVER_BACKGROUND, TAB_UNFOCUSED_HOVER_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND, WORKBENCH_BACKGROUND, TAB_ACTIVE_BORDER_TOP, TAB_UNFOCUSED_ACTIVE_BORDER_TOP, TAB_ACTIVE_MODIFIED_BORDER, TAB_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_ACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_BACKGROUND, TAB_HOVER_FOREGROUND, TAB_UNFOCUSED_HOVER_FOREGROUND, EDITOR_GROUP_HEADER_TABS_BORDER, TAB_LAST_PINNED_BORDER } from 'vs/workbench/common/theme';
3030
import { activeContrastBorder, contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry';
3131
import { ResourcesDropHandler, DraggedEditorIdentifier, DraggedEditorGroupIdentifier, extractTreeDropData, isWindowDraggedOver } from 'vs/workbench/browser/dnd';
3232
import { Color } from 'vs/base/common/color';
@@ -131,30 +131,6 @@ export class MultiEditorTabsControl extends EditorTabsControl {
131131

132132
private lastMouseWheelEventTime = 0;
133133
private isMouseOverTabs = false;
134-
135-
private _dndDropTarget: { leftElement: HTMLElement | undefined; rightElement: HTMLElement | undefined } | undefined;
136-
private set dndDropTarget(target: { leftElement: HTMLElement | undefined; rightElement: HTMLElement | undefined } | undefined) {
137-
const oldTargets = this._dndDropTarget;
138-
if (oldTargets === target || oldTargets && target && oldTargets.leftElement === target.leftElement && oldTargets.rightElement === target.rightElement) {
139-
return;
140-
}
141-
142-
const dropClassLeft = 'drop-target-left';
143-
const dropClassRight = 'drop-target-right';
144-
145-
if (oldTargets) {
146-
oldTargets.leftElement?.classList.remove(dropClassLeft);
147-
oldTargets.rightElement?.classList.remove(dropClassRight);
148-
}
149-
150-
if (target) {
151-
target.leftElement?.classList.add(dropClassLeft);
152-
target.rightElement?.classList.add(dropClassRight);
153-
}
154-
155-
this._dndDropTarget = target;
156-
}
157-
158134
constructor(
159135
parent: HTMLElement,
160136
editorPartsView: IEditorPartsView,
@@ -370,15 +346,9 @@ export class MultiEditorTabsControl extends EditorTabsControl {
370346
return;
371347
}
372348

373-
// Return if dragged editor is last tab because then this is a no-op
374-
let isLocalDragAndDrop = false;
375-
if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) {
376-
isLocalDragAndDrop = true;
377-
}
378-
379349
// Update the dropEffect to "copy" if there is no local data to be dragged because
380350
// in that case we can only copy the data into and not move it from its source
381-
if (!isLocalDragAndDrop) {
351+
if (!this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) {
382352
if (e.dataTransfer) {
383353
e.dataTransfer.dropEffect = 'copy';
384354
}
@@ -1055,7 +1025,7 @@ export class MultiEditorTabsControl extends EditorTabsControl {
10551025
this.doFillResourceDataTransfers([editor], e, isNewWindowOperation);
10561026

10571027
// Fixes https://github.com/microsoft/vscode/issues/18733
1058-
this.updateDropFeedback(tab.cloneNode(true) as HTMLElement, true, e, tabIndex);
1028+
this.updateDropFeedback(tab, true, e, tabIndex);
10591029
scheduleAtNextAnimationFrame(getWindow(this.parent), () => this.updateDropFeedback(tab, false, e, tabIndex));
10601030
},
10611031

@@ -1136,10 +1106,13 @@ export class MultiEditorTabsControl extends EditorTabsControl {
11361106

11371107
// compute the target index
11381108
let targetIndex = tabIndex;
1139-
if (!this.isHeadOfTab(e, tab)) {
1109+
if (this.getTabDragOverLocation(e, tab) === 'right') {
11401110
targetIndex++;
11411111
}
11421112

1113+
// If we are moving an editor inside the same group and it is located before the target index
1114+
// wee need to reduce the index by one to account for the fact that the move will cause all subsequent
1115+
// tabs to move one to the left.
11431116
const editorIdentifiers = this.editorTransfer.getData(DraggedEditorIdentifier.prototype);
11441117
if (editorIdentifiers !== undefined) {
11451118

@@ -1188,15 +1161,17 @@ export class MultiEditorTabsControl extends EditorTabsControl {
11881161
private updateDropFeedback(element: HTMLElement, isDND: boolean, e: DragEvent, tabIndex?: number): void {
11891162
const isTab = (typeof tabIndex === 'number');
11901163

1164+
let dropTarget;
11911165
if (isDND) {
11921166
if (isTab) {
1193-
this.dndDropTarget = this.computeDropTarget(e, tabIndex, element);
1167+
dropTarget = this.computeDropTarget(e, tabIndex, element);
11941168
} else {
1195-
this.dndDropTarget = { leftElement: element.lastElementChild as HTMLElement, rightElement: undefined };
1169+
dropTarget = { leftElement: element.lastElementChild as HTMLElement, rightElement: undefined };
11961170
}
11971171
} else {
1198-
this.dndDropTarget = undefined;
1172+
dropTarget = undefined;
11991173
}
1174+
this.updateDropTarget(dropTarget);
12001175

12011176
// Outline
12021177
const activeContrastBorderColor = this.getColor(activeContrastBorder);
@@ -1213,30 +1188,53 @@ export class MultiEditorTabsControl extends EditorTabsControl {
12131188
}
12141189
}
12151190

1216-
private isHeadOfTab(e: DragEvent, tab: HTMLElement): boolean {
1191+
private dropTarget: { leftElement: HTMLElement | undefined; rightElement: HTMLElement | undefined } | undefined;
1192+
private updateDropTarget(target: { leftElement: HTMLElement | undefined; rightElement: HTMLElement | undefined } | undefined): void {
1193+
const oldTargets = this.dropTarget;
1194+
if (oldTargets === target || oldTargets && target && oldTargets.leftElement === target.leftElement && oldTargets.rightElement === target.rightElement) {
1195+
return;
1196+
}
1197+
1198+
const dropClassLeft = 'drop-target-left';
1199+
const dropClassRight = 'drop-target-right';
1200+
1201+
if (oldTargets) {
1202+
oldTargets.leftElement?.classList.remove(dropClassLeft);
1203+
oldTargets.rightElement?.classList.remove(dropClassRight);
1204+
}
1205+
1206+
if (target) {
1207+
target.leftElement?.classList.add(dropClassLeft);
1208+
target.rightElement?.classList.add(dropClassRight);
1209+
}
1210+
1211+
this.dropTarget = target;
1212+
}
1213+
1214+
private getTabDragOverLocation(e: DragEvent, tab: HTMLElement): 'left' | 'right' {
12171215
const rect = tab.getBoundingClientRect();
12181216
const offsetXRelativeToParent = e.clientX - rect.left;
1219-
return offsetXRelativeToParent <= rect.width / 2;
1217+
return offsetXRelativeToParent <= rect.width / 2 ? 'left' : 'right';
12201218
}
12211219

12221220
private computeDropTarget(e: DragEvent, tabIndex: number, targetTab: HTMLElement): { leftElement: HTMLElement | undefined; rightElement: HTMLElement | undefined } | undefined {
1223-
const isHeadOfTab = this.isHeadOfTab(e, targetTab);
1221+
const isLeftSideOfTab = this.getTabDragOverLocation(e, targetTab) === 'left';
12241222
const isLastTab = tabIndex === this.tabsModel.count - 1;
12251223
const isFirstTab = tabIndex === 0;
12261224

12271225
// Before first tab
1228-
if (isHeadOfTab && isFirstTab) {
1226+
if (isLeftSideOfTab && isFirstTab) {
12291227
return { leftElement: undefined, rightElement: targetTab };
12301228
}
12311229

12321230
// After last tab
1233-
if (!isHeadOfTab && isLastTab) {
1231+
if (!isLeftSideOfTab && isLastTab) {
12341232
return { leftElement: targetTab, rightElement: undefined };
12351233
}
12361234

12371235
// Between two tabs
1238-
const tabBefore = isHeadOfTab ? targetTab.previousElementSibling : targetTab;
1239-
const tabAfter = isHeadOfTab ? targetTab : targetTab.nextElementSibling;
1236+
const tabBefore = isLeftSideOfTab ? targetTab.previousElementSibling : targetTab;
1237+
const tabAfter = isLeftSideOfTab ? targetTab : targetTab.nextElementSibling;
12401238

12411239
return { leftElement: tabBefore as HTMLElement, rightElement: tabAfter as HTMLElement };
12421240
}
@@ -2410,16 +2408,4 @@ registerThemingParticipant((theme, collector) => {
24102408
collector.addRule(makeTabBackgroundRule(adjustedColor, adjustedColorDrag, false, false));
24112409
}
24122410
}
2413-
2414-
const tabDndIndicatorColor = theme.getColor(TAB_DRAG_AND_DROP_BETWEEEN_INDICATOR);
2415-
if (tabDndIndicatorColor) {
2416-
// DnD Feedback
2417-
2418-
collector.addRule(`
2419-
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.drop-target-left::after,
2420-
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.drop-target-right::before {
2421-
background-color: ${tabDndIndicatorColor};
2422-
}
2423-
`);
2424-
}
24252411
});

src/vs/workbench/common/theme.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,14 +182,14 @@ export const TAB_UNFOCUSED_HOVER_BORDER = registerColor('tab.unfocusedHoverBorde
182182

183183
//#endregion
184184

185-
//#region Tab Drag and Drop Indicator
185+
//#region Tab Drag and Drop Border
186186

187-
export const TAB_DRAG_AND_DROP_BETWEEEN_INDICATOR = registerColor('tab.dragAndDropBetweenIndicator', {
188-
dark: TAB_INACTIVE_FOREGROUND,
189-
light: TAB_INACTIVE_FOREGROUND,
187+
export const TAB_DRAG_AND_DROP_BORDER = registerColor('tab.dragAndDropBorder', {
188+
dark: TAB_ACTIVE_FOREGROUND,
189+
light: TAB_ACTIVE_FOREGROUND,
190190
hcDark: activeContrastBorder,
191191
hcLight: activeContrastBorder
192-
}, localize('tabDragAndDropBetweenIndicator', "Indicator between tabs to indicate that a tab can be dropped between two tabs. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups."));
192+
}, localize('tabDragAndDropBorder', "Border between tabs to indicate that a tab can be inserted between two tabs. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups."));
193193

194194
//#endregion
195195

0 commit comments

Comments
 (0)