From be83b31e378774ed14879fb1889c47422e68bea5 Mon Sep 17 00:00:00 2001 From: Alan Ren Date: Thu, 26 Mar 2020 20:41:09 -0700 Subject: [PATCH] dashboard improvement (#9730) * dashboard improvement - WIP (#8836) * wip * wip * tabgroup * tab group * agent views * clean up * formats * feedback * fix error * contribute top level server/db dashboard tab (#8868) * tabbedPanel component (#8861) * tabbed panel * tabbed panel * fix errors * revert main.ts changes * use margin * address comments * remove orientation property * content tab group (#8878) * add databases tab * use more extensible approach * remove unnecessary code * add when expression * objects tab for database dashboard (#8892) * fix build errors * fix build error * Dashboard toolbar (#9118) * remove old toolbar with only edit and refresh * remove tasks widgets from server and databases dashboards * adding toolbar to dashboardpage and clicking new query works * restore and new notebook now do something * add backup to toolbar for database dashboards * new notebook connects to db * only show backup and restore for non-azure * new backup and restore svgs * clean up * got toolbar actions to show up from contribution * some cleanup and add database dashboard toolbar contributions * don't show all tasks when there should be no tasks * fix toolbar showing multiple times when switching opening another dashboard from OE * only show toolbar for home page * update to new icons - same icons for light and dark theme * don't show separator if there aren't any actions * read toolbar actions from tasks-widget * remove tasks widget from home dashboard page * show extension's actions in toolbar * clean up * more cleaning up * fix extension actions not always loading the first time * add configure dashboard * remove old edit icon css * change tasks back to original order * make sure tasks widget is the one being removed * collapsible tab panel (#9221) * collapsible vertical tab panel * fix lint error * comments batch 1 * pr comments * update new query icon (#9351) * Update toolbar actions (#9313) * remove edit and configure dashboard and add refresh to toolbar for other dashboard pages too * Add refresh for tabs that have container type with refresh implemented * change refresh to only refresh the current tab * remove map for tab to actions * add back configure dashboard to home toolbar * check if index is -1 before trying to remove tasks widget from widgets * Move objects widget back to database home tab (#9432) * move objects widget back to database home tab and reorder toolbar * change order of actions back to previous order * Allow extensions to add actions to home toolbar (#9269) * add support for extensions to add actions to home toolbar * fix spacing * use menu contribution point * undo previous changes that added dashboardToolbarHomeAction contribution * remove home from name * add context key for tab name * allow actions to also be added to the toolbar of other tabs * add extension contributed actions even if no tasks-widget * fix refresh being added twice after merging * hide the tab list when collapsed (#9529) * update the order of css selectors (#9606) * Update dashboard style to be closer to mockups (#9570) * update style to be closer to mockups * tab panel styling * change back tab styling for tabs in a tab contributed by an extension * change color of borders when theme changes * set dark theme active tab background to same as OE for now * update border colors * move colors to theme file * fix a few issues (#9690) * couple fixes * comments * small dashboard toolbar fixes (#9695) * fix backup icon in toolbar * fix database page toolbar border color * add back center center in common-icons.css (#9703) * change padding so bottom border shows again (#9710) * tab panel fixes (#9724) * tab panel fixes * fix package.nls.json * feedbacks (#9761) * feedbacks * remove comments Co-authored-by: Kim Santiago <31145923+kisantia@users.noreply.github.com> --- .../src/test/views/utils.ts | 1 + extensions/mssql/package.json | 2 +- .../mssql/resources/dark/database_inverse.svg | 1 + .../mssql/resources/dark/new_notebook.svg | 3 + .../resources/dark/new_notebook_inverse.svg | 1 - extensions/mssql/resources/light/database.svg | 1 + .../mssql/resources/light/new_notebook.svg | 4 +- src/sql/azdata.proposed.d.ts | 73 ++++ .../base/browser/ui/panel/media/collapse.svg | 1 + .../ui/panel/media/collapse_inverse.svg | 12 + .../base/browser/ui/panel/media/expand.svg | 1 + .../browser/ui/panel/media/expand_inverse.svg | 12 + src/sql/base/browser/ui/panel/media/panel.css | 67 +++- .../base/browser/ui/panel/media/tabHeader.css | 2 +- .../base/browser/ui/panel/panel.component.ts | 84 ++++- .../base/browser/ui/panel/tab.component.ts | 3 + .../browser/ui/panel/tabHeader.component.ts | 33 +- src/sql/media/icons/backup.svg | 5 +- src/sql/media/icons/backup_inverse.svg | 1 - src/sql/media/icons/common-icons.css | 50 +-- src/sql/media/icons/configdashboard.svg | 1 - .../media/icons/configdashboard_inverse.svg | 1 - src/sql/media/icons/configuredashboard.svg | 3 + src/sql/media/icons/edit.svg | 4 +- src/sql/media/icons/edit_inverse.svg | 1 - src/sql/media/icons/extensions.svg | 3 + src/sql/media/icons/newquery.svg | 4 +- src/sql/media/icons/newquery_inverse.svg | 1 - src/sql/media/icons/refresh.svg | 4 +- src/sql/media/icons/refresh_inverse.svg | 1 - src/sql/media/icons/restore.svg | 5 +- src/sql/media/icons/restore_inverse.svg | 1 - .../platform/dashboard/browser/interfaces.ts | 1 + .../api/browser/mainThreadModelView.ts | 3 +- .../workbench/api/common/extHostModelView.ts | 46 +++ .../api/common/sqlExtHost.api.impl.ts | 3 +- .../workbench/api/common/sqlExtHostTypes.ts | 11 + src/sql/workbench/browser/actions.ts | 2 +- .../modelComponents/media/tabbedPanel.css | 53 +++ .../tabbedPanel.component.html | 20 ++ .../modelComponents/tabbedPanel.component.ts | 96 +++++ .../dashboardNavSection.component.ts | 2 +- .../dashboardNavSection.contribution.ts | 39 +- .../dashboardWidgetWrapper.component.html | 3 +- .../dashboardWidgetWrapper.component.ts | 14 +- .../contrib/dashboard/browser/core/actions.ts | 28 +- .../browser/core/dashboardPage.component.html | 6 +- .../browser/core/dashboardPage.component.ts | 335 ++++++++++++++---- .../dashboard/browser/core/dashboardPage.css | 40 +++ .../dashboard/browser/core/dashboardPanel.css | 2 +- .../browser/core/dashboardPanelStyles.ts | 39 +- .../browser/core/dashboardTab.contribution.ts | 103 +++++- .../dashboard/browser/core/dashboardWidget.ts | 4 +- .../dashboard/browser/core/media/default.svg | 3 + .../browser/core/media/default_inverse.svg | 10 + .../dashboard/browser/core/media/home.svg | 1 + .../browser/core/media/home_inverse.svg | 15 + .../browser/dashboard.component.html | 2 - .../dashboard/browser/dashboard.component.ts | 32 -- .../contrib/dashboard/browser/dashboard.css | 16 - .../dashboard/browser/dashboardIconUtil.ts | 42 +++ .../dashboard/browser/dashboardRegistry.ts | 19 +- .../pages/dashboardPageContribution.ts | 2 +- .../pages/databaseDashboardPage.component.ts | 19 +- .../databaseDashboardPage.contribution.ts | 7 +- .../pages/serverDashboardPage.component.ts | 18 +- .../pages/serverDashboardPage.contribution.ts | 4 +- .../propertiesWidget.component.html | 2 +- .../properties/propertiesWidget.component.ts | 20 +- .../propertiesWidget.component.test.ts | 2 +- .../browser/agentView.component.ts | 2 +- .../browser/components.contribution.ts | 5 +- .../dashboard/browser/common/interfaces.ts | 11 +- .../services/dialog/browser/dialog.module.ts | 4 +- src/vs/platform/actions/common/actions.ts | 1 + .../api/common/menusExtensionPoint.ts | 1 + src/vs/workbench/common/theme.ts | 15 + 77 files changed, 1187 insertions(+), 302 deletions(-) create mode 100644 extensions/mssql/resources/dark/database_inverse.svg create mode 100644 extensions/mssql/resources/dark/new_notebook.svg delete mode 100644 extensions/mssql/resources/dark/new_notebook_inverse.svg create mode 100644 extensions/mssql/resources/light/database.svg create mode 100644 src/sql/base/browser/ui/panel/media/collapse.svg create mode 100644 src/sql/base/browser/ui/panel/media/collapse_inverse.svg create mode 100644 src/sql/base/browser/ui/panel/media/expand.svg create mode 100644 src/sql/base/browser/ui/panel/media/expand_inverse.svg delete mode 100644 src/sql/media/icons/backup_inverse.svg delete mode 100644 src/sql/media/icons/configdashboard.svg delete mode 100644 src/sql/media/icons/configdashboard_inverse.svg create mode 100644 src/sql/media/icons/configuredashboard.svg delete mode 100644 src/sql/media/icons/edit_inverse.svg create mode 100644 src/sql/media/icons/extensions.svg delete mode 100644 src/sql/media/icons/newquery_inverse.svg delete mode 100644 src/sql/media/icons/refresh_inverse.svg delete mode 100644 src/sql/media/icons/restore_inverse.svg create mode 100644 src/sql/workbench/browser/modelComponents/media/tabbedPanel.css create mode 100644 src/sql/workbench/browser/modelComponents/tabbedPanel.component.html create mode 100644 src/sql/workbench/browser/modelComponents/tabbedPanel.component.ts create mode 100644 src/sql/workbench/contrib/dashboard/browser/core/media/default.svg create mode 100644 src/sql/workbench/contrib/dashboard/browser/core/media/default_inverse.svg create mode 100644 src/sql/workbench/contrib/dashboard/browser/core/media/home.svg create mode 100644 src/sql/workbench/contrib/dashboard/browser/core/media/home_inverse.svg delete mode 100644 src/sql/workbench/contrib/dashboard/browser/dashboard.css create mode 100644 src/sql/workbench/contrib/dashboard/browser/dashboardIconUtil.ts diff --git a/extensions/machine-learning-services/src/test/views/utils.ts b/extensions/machine-learning-services/src/test/views/utils.ts index 7f36593597..0d7467203f 100644 --- a/extensions/machine-learning-services/src/test/views/utils.ts +++ b/extensions/machine-learning-services/src/test/views/utils.ts @@ -182,6 +182,7 @@ export function createViewContext(): ViewTestContext { loadingComponent: () => loadingBuilder, fileBrowserTree: undefined!, hyperlink: undefined!, + tabbedPanel: undefined!, separator: undefined! } }; diff --git a/extensions/mssql/package.json b/extensions/mssql/package.json index 5698d67ed1..2d0413b8b3 100644 --- a/extensions/mssql/package.json +++ b/extensions/mssql/package.json @@ -52,7 +52,7 @@ "command": "mssqlCluster.task.newNotebook", "title": "%notebook.command.new%", "icon": { - "dark": "resources/dark/new_notebook_inverse.svg", + "dark": "resources/dark/new_notebook.svg", "light": "resources/light/new_notebook.svg" } }, diff --git a/extensions/mssql/resources/dark/database_inverse.svg b/extensions/mssql/resources/dark/database_inverse.svg new file mode 100644 index 0000000000..fbb38a2836 --- /dev/null +++ b/extensions/mssql/resources/dark/database_inverse.svg @@ -0,0 +1 @@ +Database_Inverse@2x \ No newline at end of file diff --git a/extensions/mssql/resources/dark/new_notebook.svg b/extensions/mssql/resources/dark/new_notebook.svg new file mode 100644 index 0000000000..6557616999 --- /dev/null +++ b/extensions/mssql/resources/dark/new_notebook.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/mssql/resources/dark/new_notebook_inverse.svg b/extensions/mssql/resources/dark/new_notebook_inverse.svg deleted file mode 100644 index e0072afee1..0000000000 --- a/extensions/mssql/resources/dark/new_notebook_inverse.svg +++ /dev/null @@ -1 +0,0 @@ -new_notebook_inverse \ No newline at end of file diff --git a/extensions/mssql/resources/light/database.svg b/extensions/mssql/resources/light/database.svg new file mode 100644 index 0000000000..c11f929ce4 --- /dev/null +++ b/extensions/mssql/resources/light/database.svg @@ -0,0 +1 @@ +Database@2x \ No newline at end of file diff --git a/extensions/mssql/resources/light/new_notebook.svg b/extensions/mssql/resources/light/new_notebook.svg index 9618487568..6557616999 100644 --- a/extensions/mssql/resources/light/new_notebook.svg +++ b/extensions/mssql/resources/light/new_notebook.svg @@ -1 +1,3 @@ -new_notebook \ No newline at end of file + + + diff --git a/src/sql/azdata.proposed.d.ts b/src/sql/azdata.proposed.d.ts index c1de32754c..aeafcb309d 100644 --- a/src/sql/azdata.proposed.d.ts +++ b/src/sql/azdata.proposed.d.ts @@ -127,6 +127,7 @@ declare module 'azdata' { export interface ModelBuilder { radioCardGroup(): ComponentBuilder; + tabbedPanel(): TabbedPanelComponentBuilder; separator(): ComponentBuilder; } @@ -200,6 +201,78 @@ declare module 'azdata' { export interface ImageComponentProperties extends ComponentProperties, ComponentWithIconProperties { } + /** + * Panel component with tabs + */ + export interface TabbedPanelComponent extends Container { + /** + * An event triggered when the selected tab is changed. + * The event argument is the id of the selected tab. + */ + onTabChanged: vscode.Event; + } + + /** + * Defines the tab orientation of TabbedPanelComponent + */ + export enum TabOrientation { + Vertical = 'vertical', + Horizontal = 'horizontal' + } + + /** + * Layout of TabbedPanelComponent, can be used to initialize the component when using ModelBuilder + */ + export interface TabbedPanelLayout { + orientation: TabOrientation; + } + + /** + * Represents the tab of TabbedPanelComponent + */ + export interface Tab { + /** + * Title of the tab + */ + title: string; + + /** + * Content component of the tab + */ + content: Component; + + /** + * Id of the tab + */ + id: string; + } + + /** + * Represents the tab group of TabbedPanelComponent + */ + export interface TabGroup { + /** + * Title of the tab group + */ + title: string; + + /** + * children of the tab group + */ + tabs: Tab[]; + } + + /** + * Builder for TabbedPannelComponent + */ + export interface TabbedPanelComponentBuilder extends ContainerBuilder { + /** + * Add the tabs to the component + * @param tabs tabs/tab groups to be added + */ + withTabs(tabs: (Tab | TabGroup)[]): ContainerBuilder; + } + export interface InputBoxProperties extends ComponentProperties { validationErrorMessage?: string; } diff --git a/src/sql/base/browser/ui/panel/media/collapse.svg b/src/sql/base/browser/ui/panel/media/collapse.svg new file mode 100644 index 0000000000..b263806e32 --- /dev/null +++ b/src/sql/base/browser/ui/panel/media/collapse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/sql/base/browser/ui/panel/media/collapse_inverse.svg b/src/sql/base/browser/ui/panel/media/collapse_inverse.svg new file mode 100644 index 0000000000..76b943a430 --- /dev/null +++ b/src/sql/base/browser/ui/panel/media/collapse_inverse.svg @@ -0,0 +1,12 @@ + + + + background + + + + Layer 1 + + + + \ No newline at end of file diff --git a/src/sql/base/browser/ui/panel/media/expand.svg b/src/sql/base/browser/ui/panel/media/expand.svg new file mode 100644 index 0000000000..8e0ad52a9f --- /dev/null +++ b/src/sql/base/browser/ui/panel/media/expand.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/sql/base/browser/ui/panel/media/expand_inverse.svg b/src/sql/base/browser/ui/panel/media/expand_inverse.svg new file mode 100644 index 0000000000..210b0f3b46 --- /dev/null +++ b/src/sql/base/browser/ui/panel/media/expand_inverse.svg @@ -0,0 +1,12 @@ + + + + background + + + + Layer 1 + + + + \ No newline at end of file diff --git a/src/sql/base/browser/ui/panel/media/panel.css b/src/sql/base/browser/ui/panel/media/panel.css index 5338c597ba..b68539e8b1 100644 --- a/src/sql/base/browser/ui/panel/media/panel.css +++ b/src/sql/base/browser/ui/panel/media/panel.css @@ -59,7 +59,7 @@ panel { display: flex; padding-left: 5px; padding-right: 5px; - min-width: 65px; + cursor: pointer; } .tabbedPanel.vertical .tabList .tab-header { @@ -67,17 +67,16 @@ panel { text-transform: none; text-overflow: ellipsis; overflow: hidden; - width: 65px; + width: auto; height: 50px; line-height: 45px; } -.tabbedPanel .tabList .tab .tabLabel.codicon { +.tabbedPanel .tabList .tab .tabIcon.codicon { background-repeat: no-repeat; - background-position: center center; - background-size: 20px; - padding: 20px 25px; - line-height: 50px; + background-position: 2px center; + background-size: 16px; + padding: 2px 2px 2px 22px; } .tabbedPanel .tabList .actions-container { @@ -117,24 +116,20 @@ panel { height: 100%; } -.tabbedPanel.vertical .tabList { - flex-direction: column; -} - .tabbedPanel > .tab-content { flex: 1; position: relative; } -.tabbedPanel.vertical > .title > .tabList { +.tabbedPanel.vertical > .title > .tabContainer > .monaco-scrollable-element > .tabList { flex-flow: column; } -.tabbedPanel.horizontal > .title > .tabList { +.tabbedPanel.horizontal > .title > .tabContainer > .monaco-scrollable-element > .tabList { flex-flow: row; } -.tabbedPanel > .title > .monaco-scrollable-element { +.tabbedPanel > .title > .tabContainer > .monaco-scrollable-element { flex: 0 1 auto; width: inherit; } @@ -147,3 +142,47 @@ panel { width: 100%; height: 100%; } + +.tabbedPanel .tab-group-header { + font-weight: bold; + margin: 15px 5px 3px 5px; + line-height: 35px; + height: 35px; + border-style: solid; + border-width: 0 0 1px 0; + border-color: rgb(214, 214, 214); +} + +.tabbedPanel .action-container { + display: flex; + flex-flow: row-reverse; +} + +.tabbedPanel .tab-action { + width: 15px; + height: 15px; + padding: 0px; + border: 0px; + background-color: transparent; + background-position: 2px center; + background-repeat: no-repeat; + background-size: 11px 11px; +} + +.vs .tabbedPanel .tab-action.collapse{ + background-image: url("collapse.svg"); +} + +.vs-dark .tabbedPanel .tab-action.collapse, +.hc-black .tabbedPanel .tab-action.collapse { + background-image: url("collapse_inverse.svg"); +} + +.vs .tabbedPanel .tab-action.expand { + background-image: url("expand.svg"); +} + +.vs-dark .tabbedPanel .tab-action.expand, +.hc-black .tabbedPanel .tab-action.expand { + background-image: url("expand_inverse.svg"); +} diff --git a/src/sql/base/browser/ui/panel/media/tabHeader.css b/src/sql/base/browser/ui/panel/media/tabHeader.css index bbf06dda0b..35fa24986f 100644 --- a/src/sql/base/browser/ui/panel/media/tabHeader.css +++ b/src/sql/base/browser/ui/panel/media/tabHeader.css @@ -17,4 +17,4 @@ tab-header .tab-header.active .action-label, /* always show it for active tab tab-header .tab-header:hover .action-label, /* always show it on hover */ tab-header .tab-header:focus .action-label { /* always show it on focus */ opacity: 1; -} \ No newline at end of file +} diff --git a/src/sql/base/browser/ui/panel/panel.component.ts b/src/sql/base/browser/ui/panel/panel.component.ts index 4ac6ddaf18..fd658c22e7 100644 --- a/src/sql/base/browser/ui/panel/panel.component.ts +++ b/src/sql/base/browser/ui/panel/panel.component.ts @@ -5,7 +5,7 @@ import { Component, ContentChildren, QueryList, Inject, forwardRef, NgZone, - Input, EventEmitter, Output, ViewChild, ElementRef + Input, EventEmitter, Output, ViewChild, ElementRef, ChangeDetectorRef, ViewChildren } from '@angular/core'; import { TabComponent } from 'sql/base/browser/ui/panel/tab.component'; @@ -19,6 +19,10 @@ import { mixin } from 'vs/base/common/objects'; import { Disposable } from 'vs/base/common/lifecycle'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { firstIndex } from 'vs/base/common/arrays'; +import * as nls from 'vs/nls'; +import { TabHeaderComponent } from 'sql/base/browser/ui/panel/tabHeader.component'; +import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { KeyCode } from 'vs/base/common/keyCodes'; export interface IPanelOptions { /** @@ -48,9 +52,19 @@ let idPool = 0;
-
+
+ +
+
- + + + + +
+ {{tab.title}} +
+
@@ -71,6 +85,7 @@ export class PanelComponent extends Disposable { @Input() public options?: IPanelOptions; @Input() public actions?: Array; @ContentChildren(TabComponent) private readonly _tabs!: QueryList; + @ViewChildren(TabHeaderComponent) private readonly _tabHeaders!: QueryList; @ViewChild(ScrollableDirective) private scrollable?: ScrollableDirective; @Output() public onTabChange = new EventEmitter(); @@ -79,16 +94,32 @@ export class PanelComponent extends Disposable { private _activeTab?: TabComponent; private _actionbar?: ActionBar; private _mru: TabComponent[] = []; + private _tabExpanded: boolean = true; protected AutoScrollbarVisibility = ScrollbarVisibility.Auto; // used by angular template protected HiddenScrollbarVisibility = ScrollbarVisibility.Hidden; // used by angular template protected NavigationBarLayout = NavigationBarLayout; // used by angular template @ViewChild('panelActionbar', { read: ElementRef }) private _actionbarRef!: ElementRef; - constructor(@Inject(forwardRef(() => NgZone)) private _zone: NgZone) { + constructor( + @Inject(forwardRef(() => NgZone)) private _zone: NgZone, + @Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef) { super(); } + public get toggleTabPanelButtonCssClass(): string { + return this._tabExpanded ? 'tab-action collapse' : 'tab-action expand'; + } + + public get toggleTabPanelButtonAriaLabel(): string { + return this._tabExpanded ? nls.localize('hideTextLabel', "Hide text labels") : nls.localize('showTextLabel', "Show text labels"); + } + + toggleTabPanel(): void { + this._tabExpanded = !this._tabExpanded; + this._cd.detectChanges(); + } + ngOnInit(): void { this.options = mixin(this.options || {}, defaultOptions, false); } @@ -245,4 +276,49 @@ export class PanelComponent extends Disposable { public layout() { this._activeTab?.layout(); } + + onKey(e: KeyboardEvent): void { + const event = new StandardKeyboardEvent(e); + let eventHandled: boolean = false; + if (event.equals(KeyCode.DownArrow) || event.equals(KeyCode.RightArrow)) { + this.focusNextTab(); + eventHandled = true; + } else if (event.equals(KeyCode.UpArrow) || event.equals(KeyCode.LeftArrow)) { + this.focusPreviousTab(); + eventHandled = true; + } + + if (eventHandled) { + event.preventDefault(); + event.stopPropagation(); + } + } + + private focusPreviousTab(): void { + const currentIndex = this.focusedTabHeaderIndex; + if (currentIndex !== -1) { + // Move to the previous tab, if we are at the first tab then move to the last tab. + this.focusOnTabHeader(currentIndex === 0 ? this._tabHeaders.length - 1 : currentIndex - 1); + } + } + + private focusNextTab(): void { + const currentIndex = this.focusedTabHeaderIndex; + if (currentIndex !== -1) { + // Move to the next tab, if we are at the last tab then move to the first tab. + this.focusOnTabHeader(currentIndex === this._tabHeaders.length - 1 ? 0 : currentIndex + 1); + } + } + + private focusOnTabHeader(index: number): void { + if (index >= 0 && index <= this._tabHeaders.length - 1) { + this._tabHeaders.toArray()[index].focusOnTabHeader(); + } + } + + private get focusedTabHeaderIndex(): number { + return this._tabHeaders.toArray().findIndex((header) => { + return header.nativeElement === document.activeElement; + }); + } } diff --git a/src/sql/base/browser/ui/panel/tab.component.ts b/src/sql/base/browser/ui/panel/tab.component.ts index 226b331bdd..0cca4bc2c0 100644 --- a/src/sql/base/browser/ui/panel/tab.component.ts +++ b/src/sql/base/browser/ui/panel/tab.component.ts @@ -12,6 +12,8 @@ export abstract class TabChild extends AngularDisposable { public abstract layout(): void; } +export type TabType = 'tab' | 'group-header'; + @Component({ selector: 'tab', template: ` @@ -29,6 +31,7 @@ export class TabComponent implements OnDestroy { @Input() public iconClass?: string; public _active = false; @Input() public identifier!: string; + @Input() public type: TabType = 'tab'; @Input() private visibilityType: 'if' | 'visibility' = 'if'; private rendered = false; private destroyed: boolean = false; diff --git a/src/sql/base/browser/ui/panel/tabHeader.component.ts b/src/sql/base/browser/ui/panel/tabHeader.component.ts index a10ad3e4d5..4781c4b935 100644 --- a/src/sql/base/browser/ui/panel/tabHeader.component.ts +++ b/src/sql/base/browser/ui/panel/tabHeader.component.ts @@ -19,10 +19,13 @@ import { CloseTabAction } from 'sql/base/browser/ui/panel/tabActions'; @Component({ selector: 'tab-header', template: ` -