-
@@ -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: `
-