Skip to content

Commit

Permalink
Merge pull request #209604 from microsoft/benibenj/governing-caterpillar
Browse files Browse the repository at this point in the history
Add customizable colors for tree sticky scroll
  • Loading branch information
benibenj authored Apr 5, 2024
2 parents 884c8a6 + ab4e8b5 commit 2fa8d0c
Show file tree
Hide file tree
Showing 23 changed files with 148 additions and 69 deletions.
6 changes: 6 additions & 0 deletions build/lib/stylelint/vscode-known-variables.json
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,9 @@
"--vscode-panelTitle-activeBorder",
"--vscode-panelTitle-activeForeground",
"--vscode-panelTitle-inactiveForeground",
"--vscode-panelStickyScroll-background",
"--vscode-panelStickyScroll-border",
"--vscode-panelStickyScroll-shadow",
"--vscode-peekView-border",
"--vscode-peekViewEditor-background",
"--vscode-peekViewEditor-matchHighlightBackground",
Expand Down Expand Up @@ -567,6 +570,9 @@
"--vscode-sideBarSectionHeader-foreground",
"--vscode-sideBarTitle-background",
"--vscode-sideBarTitle-foreground",
"--vscode-sideBarStickyScroll-background",
"--vscode-sideBarStickyScroll-border",
"--vscode-sideBarStickyScroll-shadow",
"--vscode-sideBySideEditor-horizontalBorder",
"--vscode-sideBySideEditor-verticalBorder",
"--vscode-simpleFindWidget-sashBorder",
Expand Down
8 changes: 7 additions & 1 deletion src/vs/base/browser/ui/list/listWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,9 @@ export interface IListStyles {
listHoverOutline: string | undefined;
treeIndentGuidesStroke: string | undefined;
treeInactiveIndentGuidesStroke: string | undefined;
treeStickyScrollBackground: string | undefined;
treeStickyScrollBorder: string | undefined;
treeStickyScrollShadow: string | undefined;
tableColumnsBorder: string | undefined;
tableOddRowsBackgroundColor: string | undefined;
}
Expand Down Expand Up @@ -1124,7 +1127,10 @@ export const unthemedListStyles: IListStyles = {
listFocusOutline: undefined,
listInactiveFocusOutline: undefined,
listSelectionOutline: undefined,
listHoverOutline: undefined
listHoverOutline: undefined,
treeStickyScrollBackground: undefined,
treeStickyScrollBorder: undefined,
treeStickyScrollShadow: undefined
};

const DefaultOptions: IListOptions<any> = {
Expand Down
17 changes: 14 additions & 3 deletions src/vs/base/browser/ui/tree/abstractTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2772,9 +2772,20 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
}

// Sticky Scroll Background
if (styles.listBackground) {
content.push(`.monaco-list${suffix} .monaco-scrollable-element .monaco-tree-sticky-container { background-color: ${styles.listBackground}; }`);
content.push(`.monaco-list${suffix} .monaco-scrollable-element .monaco-tree-sticky-container .monaco-tree-sticky-row { background-color: ${styles.listBackground}; }`);
const stickyScrollBackground = styles.treeStickyScrollBackground ?? styles.listBackground;
if (stickyScrollBackground) {
content.push(`.monaco-list${suffix} .monaco-scrollable-element .monaco-tree-sticky-container { background-color: ${stickyScrollBackground}; }`);
content.push(`.monaco-list${suffix} .monaco-scrollable-element .monaco-tree-sticky-container .monaco-tree-sticky-row { background-color: ${stickyScrollBackground}; }`);
}

// Sticky Scroll Border
if (styles.treeStickyScrollBorder) {
content.push(`.monaco-list${suffix} .monaco-scrollable-element .monaco-tree-sticky-container { border-bottom: 1px solid ${styles.treeStickyScrollBorder}; }`);
}

// Sticky Scroll Shadow
if (styles.treeStickyScrollShadow) {
content.push(`.monaco-list${suffix} .monaco-scrollable-element .monaco-tree-sticky-container .monaco-tree-sticky-container-shadow { box-shadow: ${styles.treeStickyScrollShadow} 0 6px 6px -6px inset; height: 3px; }`);
}

// Sticky Scroll Focus
Expand Down
9 changes: 4 additions & 5 deletions src/vs/base/browser/ui/tree/media/tree.css
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
height: 0;
z-index: 13; /* Settings editor uses z-index: 12 */

/* TODO@benibenj temporary solution, all lists should provide their background */
/* Backup color in case the tree does not provide the background color */
background-color: var(--vscode-sideBar-background);
}

Expand All @@ -147,7 +147,7 @@
opacity: 1 !important; /* Settings editor uses opacity < 1 */
overflow: hidden;

/* TODO@benibenj temporary solution, all lists should provide their background */
/* Backup color in case the tree does not provide the background color */
background-color: var(--vscode-sideBar-background);
}

Expand All @@ -161,13 +161,12 @@
display: none;
}

.monaco-list .monaco-scrollable-element .monaco-tree-sticky-container .monaco-tree-sticky-container-shadow{
.monaco-list .monaco-scrollable-element .monaco-tree-sticky-container .monaco-tree-sticky-container-shadow {
position: absolute;
bottom: -3px;
left: 0px;
height: 3px;
height: 0px; /* heigt is 3px and only set when there is a treeStickyScrollShadow color */
width: 100%;
box-shadow: var(--vscode-scrollbar-shadow) 0 6px 6px -6px inset;
}

.monaco-list .monaco-scrollable-element .monaco-tree-sticky-container[tabindex="0"]:focus{
Expand Down
5 changes: 5 additions & 0 deletions src/vs/base/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,8 @@ export type DeepRequiredNonNullable<T> = {
export type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : Partial<T[P]>;
};

/**
* Represents a type that is a partial version of a given type `T`, except a subset.
*/
export type PartialExcept<T, K extends keyof T> = Partial<Omit<T, K>> & Pick<T, K>;
6 changes: 6 additions & 0 deletions src/vs/platform/theme/browser/defaultStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ export const defaultListStyles: IListStyles = {
listHoverOutline: asCssVariable(activeContrastBorder),
treeIndentGuidesStroke: asCssVariable(treeIndentGuidesStroke),
treeInactiveIndentGuidesStroke: asCssVariable(treeInactiveIndentGuidesStroke),
treeStickyScrollBackground: undefined,
treeStickyScrollBorder: undefined,
treeStickyScrollShadow: undefined,
tableColumnsBorder: asCssVariable(tableColumnsBorder),
tableOddRowsBackgroundColor: asCssVariable(tableOddRowsBackgroundColor),
};
Expand Down Expand Up @@ -216,6 +219,9 @@ export const defaultSelectBoxStyles: ISelectBoxStyles = {
tableOddRowsBackgroundColor: undefined,
treeIndentGuidesStroke: undefined,
treeInactiveIndentGuidesStroke: undefined,
treeStickyScrollBackground: undefined,
treeStickyScrollBorder: undefined,
treeStickyScrollShadow: undefined
};

export function getSelectBoxStyles(override: IStyleOverride<ISelectBoxStyles>): ISelectBoxStyles {
Expand Down
9 changes: 3 additions & 6 deletions src/vs/workbench/browser/parts/views/treeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,8 @@ import { ThemeIcon } from 'vs/base/common/themables';
import { fillEditorsDragData } from 'vs/workbench/browser/dnd';
import { IResourceLabel, ResourceLabels } from 'vs/workbench/browser/labels';
import { API_OPEN_DIFF_EDITOR_COMMAND_ID, API_OPEN_EDITOR_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands';
import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPane';
import { getLocationBasedViewColors, IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPane';
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { Extensions, ITreeItem, ITreeItemLabel, ITreeView, ITreeViewDataProvider, ITreeViewDescriptor, ITreeViewDragAndDropController, IViewBadge, IViewDescriptorService, IViewsRegistry, ResolvableTreeItem, TreeCommand, TreeItemCollapsibleState, TreeViewItemHandleArg, TreeViewPaneHandleArg, ViewContainer, ViewContainerLocation } from 'vs/workbench/common/views';
import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
Expand Down Expand Up @@ -306,7 +305,7 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
}));
this._register(this.viewDescriptorService.onDidChangeLocation(({ views, from, to }) => {
if (views.some(v => v.id === this.id)) {
this.tree?.updateOptions({ overrideStyles: { listBackground: this.viewLocation === ViewContainerLocation.Panel ? PANEL_BACKGROUND : SIDE_BAR_BACKGROUND } });
this.tree?.updateOptions({ overrideStyles: getLocationBasedViewColors(this.viewLocation).listOverrideStyles });
}
}));
this.registerActions();
Expand Down Expand Up @@ -691,9 +690,7 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
},
multipleSelectionSupport: this.canSelectMany,
dnd: this.treeViewDnd,
overrideStyles: {
listBackground: this.viewLocation === ViewContainerLocation.Panel ? PANEL_BACKGROUND : SIDE_BAR_BACKGROUND
}
overrideStyles: getLocationBasedViewColors(this.viewLocation).listOverrideStyles
}) as WorkbenchAsyncDataTree<ITreeItem, ITreeItem, FuzzyScore>);
treeMenus.setContextKeyService(this.tree.contextKeyService);
aligner.tree = this.tree;
Expand Down
53 changes: 41 additions & 12 deletions src/vs/workbench/browser/parts/views/viewPane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import 'vs/css!./media/paneviewlet';
import * as nls from 'vs/nls';
import { Event, Emitter } from 'vs/base/common/event';
import { asCssVariable, foreground } from 'vs/platform/theme/common/colorRegistry';
import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { after, append, $, trackFocus, EventType, addDisposableListener, createCSSRule, asCSSUrl, Dimension, reset, asCssValueWithDefault } from 'vs/base/browser/dom';
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { Action, IAction, IActionRunner } from 'vs/base/common/actions';
Expand All @@ -23,7 +22,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { Extensions as ViewContainerExtensions, IView, IViewDescriptorService, ViewContainerLocation, IViewsRegistry, IViewContentDescriptor, defaultViewIcon, ViewContainerLocationToString } from 'vs/workbench/common/views';
import { IViewsService } from 'vs/workbench/services/views/common/viewsService';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { assertIsDefined } from 'vs/base/common/types';
import { assertIsDefined, PartialExcept } from 'vs/base/common/types';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { MenuId, Action2, IAction2Options, SubmenuItemAction } from 'vs/platform/actions/common/actions';
import { createActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
Expand Down Expand Up @@ -51,6 +50,8 @@ import { getDefaultHoverDelegate } from 'vs/base/browser/ui/hover/hoverDelegateF
import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle';
import type { IUpdatableHover } from 'vs/base/browser/ui/hover/hover';
import { IHoverService } from 'vs/platform/hover/browser/hover';
import { IListStyles } from 'vs/base/browser/ui/list/listWidget';
import { PANEL_BACKGROUND, PANEL_STICKY_SCROLL_BACKGROUND, PANEL_STICKY_SCROLL_BORDER, PANEL_STICKY_SCROLL_SHADOW, SIDE_BAR_BACKGROUND, SIDE_BAR_STICKY_SCROLL_BACKGROUND, SIDE_BAR_STICKY_SCROLL_BORDER, SIDE_BAR_STICKY_SCROLL_SHADOW } from 'vs/workbench/common/theme';

export enum ViewPaneShowActions {
/** Show the actions when the view is hovered. This is the default behavior. */
Expand Down Expand Up @@ -629,16 +630,8 @@ export abstract class ViewPane extends Pane implements IView {
return this.viewDescriptorService.getViewContainerByViewId(this.id)!.id;
}

protected getBackgroundColor(): string {
switch (this.viewDescriptorService.getViewLocationById(this.id)) {
case ViewContainerLocation.Panel:
return PANEL_BACKGROUND;
case ViewContainerLocation.Sidebar:
case ViewContainerLocation.AuxiliaryBar:
return SIDE_BAR_BACKGROUND;
}

return SIDE_BAR_BACKGROUND;
protected getLocationBasedColors(): IViewPaneLocationColors {
return getLocationBasedViewColors(this.viewDescriptorService.getViewLocationById(this.id));
}

focus(): void {
Expand Down Expand Up @@ -781,6 +774,42 @@ export abstract class FilterViewPane extends ViewPane {

}

export interface IViewPaneLocationColors {
background: string;
listOverrideStyles: PartialExcept<IListStyles, 'listBackground' | 'treeStickyScrollBackground'>;
}

export function getLocationBasedViewColors(location: ViewContainerLocation | null): IViewPaneLocationColors {
let background, stickyScrollBackground, stickyScrollBorder, stickyScrollShadow;

switch (location) {
case ViewContainerLocation.Panel:
background = PANEL_BACKGROUND;
stickyScrollBackground = PANEL_STICKY_SCROLL_BACKGROUND;
stickyScrollBorder = PANEL_STICKY_SCROLL_BORDER;
stickyScrollShadow = PANEL_STICKY_SCROLL_SHADOW;
break;

case ViewContainerLocation.Sidebar:
case ViewContainerLocation.AuxiliaryBar:
default:
background = SIDE_BAR_BACKGROUND;
stickyScrollBackground = SIDE_BAR_STICKY_SCROLL_BACKGROUND;
stickyScrollBorder = SIDE_BAR_STICKY_SCROLL_BORDER;
stickyScrollShadow = SIDE_BAR_STICKY_SCROLL_SHADOW;
}

return {
background,
listOverrideStyles: {
listBackground: background,
treeStickyScrollBackground: stickyScrollBackground,
treeStickyScrollBorder: stickyScrollBorder,
treeStickyScrollShadow: stickyScrollShadow
}
};
}

export abstract class ViewAction<T extends IView> extends Action2 {
override readonly desc: Readonly<IAction2Options> & { viewId: string };
constructor(desc: Readonly<IAction2Options> & { viewId: string }) {
Expand Down
44 changes: 43 additions & 1 deletion src/vs/workbench/common/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { localize } from 'vs/nls';
import { registerColor, editorBackground, contrastBorder, transparent, editorWidgetBackground, textLinkForeground, lighten, darken, focusBorder, activeContrastBorder, editorWidgetForeground, editorErrorForeground, editorWarningForeground, editorInfoForeground, treeIndentGuidesStroke, errorForeground, listActiveSelectionBackground, listActiveSelectionForeground, editorForeground, toolbarHoverBackground, inputBorder, widgetBorder } from 'vs/platform/theme/common/colorRegistry';
import { registerColor, editorBackground, contrastBorder, transparent, editorWidgetBackground, textLinkForeground, lighten, darken, focusBorder, activeContrastBorder, editorWidgetForeground, editorErrorForeground, editorWarningForeground, editorInfoForeground, treeIndentGuidesStroke, errorForeground, listActiveSelectionBackground, listActiveSelectionForeground, editorForeground, toolbarHoverBackground, inputBorder, widgetBorder, scrollbarShadow } from 'vs/platform/theme/common/colorRegistry';
import { IColorTheme } from 'vs/platform/theme/common/themeService';
import { Color } from 'vs/base/common/color';
import { ColorScheme } from 'vs/platform/theme/common/theme';
Expand Down Expand Up @@ -411,6 +411,27 @@ export const PANEL_SECTION_BORDER = registerColor('panelSection.border', {
hcLight: PANEL_BORDER
}, localize('panelSectionBorder', "Panel section border color used when multiple views are stacked horizontally in the panel. Panels are shown below the editor area and contain views like output and integrated terminal. Panel sections are views nested within the panels."));

export const PANEL_STICKY_SCROLL_BACKGROUND = registerColor('panelStickyScroll.background', {
dark: PANEL_BACKGROUND,
light: PANEL_BACKGROUND,
hcDark: PANEL_BACKGROUND,
hcLight: PANEL_BACKGROUND
}, localize('panelStickyScrollBackground', "Background color of sticky scroll in the panel."));

export const PANEL_STICKY_SCROLL_BORDER = registerColor('panelStickyScroll.border', {
dark: null,
light: null,
hcDark: null,
hcLight: null
}, localize('panelStickyScrollBorder', "Border color of sticky scroll in the panel."));

export const PANEL_STICKY_SCROLL_SHADOW = registerColor('panelStickyScroll.shadow', {
dark: scrollbarShadow,
light: scrollbarShadow,
hcDark: scrollbarShadow,
hcLight: scrollbarShadow
}, localize('panelStickyScrollShadow', "Shadow color of sticky scroll in the panel."));

// < --- Output Editor -->

const OUTPUT_VIEW_BACKGROUND = registerColor('outputView.background', {
Expand Down Expand Up @@ -899,6 +920,27 @@ export const ACTIVITY_BAR_TOP_BORDER = registerColor('sideBarActivityBarTop.bord
hcLight: SIDE_BAR_SECTION_HEADER_BORDER
}, localize('sideBarActivityBarTopBorder', "Border color between the activity bar at the top/bottom and the views."));

export const SIDE_BAR_STICKY_SCROLL_BACKGROUND = registerColor('sideBarStickyScroll.background', {
dark: SIDE_BAR_BACKGROUND,
light: SIDE_BAR_BACKGROUND,
hcDark: SIDE_BAR_BACKGROUND,
hcLight: SIDE_BAR_BACKGROUND
}, localize('sideBarStickyScrollBackground', "Background color of sticky scroll in the side bar."));

export const SIDE_BAR_STICKY_SCROLL_BORDER = registerColor('sideBarStickyScroll.border', {
dark: null,
light: null,
hcDark: null,
hcLight: null
}, localize('sideBarStickyScrollBorder', "Border color of sticky scroll in the side bar."));

export const SIDE_BAR_STICKY_SCROLL_SHADOW = registerColor('sideBarStickyScroll.shadow', {
dark: scrollbarShadow,
light: scrollbarShadow,
hcDark: scrollbarShadow,
hcLight: scrollbarShadow
}, localize('sideBarStickyScrollShadow', "Shadow color of sticky scroll in the side bar."));

// < --- Title Bar --- >

export const TITLE_BAR_ACTIVE_FOREGROUND = registerColor('titleBar.activeForeground', {
Expand Down
6 changes: 3 additions & 3 deletions src/vs/workbench/contrib/chat/browser/chatViewPane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,16 @@ export class ChatViewPane extends ViewPane implements IChatViewPane {
super.renderBody(parent);

const scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection([IContextKeyService, this.scopedContextKeyService]));

const locationBasedColors = this.getLocationBasedColors();
this._widget = this._register(scopedInstantiationService.createInstance(
ChatWidget,
ChatAgentLocation.Panel,
{ viewId: this.id },
{ supportsFileReferences: true },
{
listForeground: SIDE_BAR_FOREGROUND,
listBackground: this.getBackgroundColor(),
inputEditorBackground: this.getBackgroundColor(),
listBackground: locationBasedColors.background,
inputEditorBackground: locationBasedColors.background,
resultEditorBackground: editorBackground
}));
this._register(this.onDidChangeBodyVisibility(visible => {
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/contrib/comments/browser/commentsView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ export class CommentsPanel extends FilterViewPane implements ICommentsView {
private createTree(): void {
this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels, this));
this.tree = this._register(this.instantiationService.createInstance(CommentsList, this.treeLabels, this.treeContainer, {
overrideStyles: { listBackground: this.getBackgroundColor() },
overrideStyles: this.getLocationBasedColors().listOverrideStyles,
selectionNavigation: true,
filter: this.filter,
keyboardNavigationLabelProvider: {
Expand Down
4 changes: 1 addition & 3 deletions src/vs/workbench/contrib/debug/browser/breakpointsView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,7 @@ export class BreakpointsView extends ViewPane {
multipleSelectionSupport: false,
keyboardNavigationLabelProvider: { getKeyboardNavigationLabel: (e: IEnablement) => e },
accessibilityProvider: new BreakpointsAccessibilityProvider(this.debugService, this.labelService),
overrideStyles: {
listBackground: this.getBackgroundColor()
}
overrideStyles: this.getLocationBasedColors().listOverrideStyles
}) as WorkbenchList<BreakpointItem>;

CONTEXT_BREAKPOINTS_FOCUSED.bindTo(this.list.contextKeyService);
Expand Down
4 changes: 1 addition & 3 deletions src/vs/workbench/contrib/debug/browser/callStackView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,7 @@ export class CallStackView extends ViewPane {
}
},
expandOnlyOnTwistieClick: true,
overrideStyles: {
listBackground: this.getBackgroundColor()
}
overrideStyles: this.getLocationBasedColors().listOverrideStyles
});

this.tree.setInput(this.debugService.getModel());
Expand Down
4 changes: 1 addition & 3 deletions src/vs/workbench/contrib/debug/browser/loadedScriptsView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -483,9 +483,7 @@ export class LoadedScriptsView extends ViewPane {
},
filter: this.filter,
accessibilityProvider: new LoadedSciptsAccessibilityProvider(),
overrideStyles: {
listBackground: this.getBackgroundColor()
}
overrideStyles: this.getLocationBasedColors().listOverrideStyles
}
);

Expand Down
Loading

0 comments on commit 2fa8d0c

Please sign in to comment.