Introduce vertical cards (#12125)

* Introduce vertical cards

* Simplify and add a css type

* Feedback

* Update yarn.lock
This commit is contained in:
Amir Omidi
2020-09-04 15:15:58 -07:00
committed by GitHub
parent c2320831f7
commit 59bb827d2e
12 changed files with 255 additions and 85 deletions

View File

@@ -73,7 +73,16 @@ export class ResourceTypePickerDialog extends DialogBase {
return <azdata.RadioCard>{ return <azdata.RadioCard>{
id: resourceType.name, id: resourceType.name,
label: resourceType.displayName, label: resourceType.displayName,
icon: resourceType.icon icon: resourceType.icon,
descriptions: [
{
textValue: resourceType.displayName,
textStyles: {
'font-size': '12px',
'font-weight': 700
}
}
]
}; };
}), }),
iconHeight: '50px', iconHeight: '50px',

View File

@@ -105,14 +105,42 @@ export class SKURecommendationPage extends MigrationWizardPage {
const rbg = this.view!.modelBuilder.radioCardGroup(); const rbg = this.view!.modelBuilder.radioCardGroup();
rbg.component().cards = []; rbg.component().cards = [];
rbg.component().orientation = azdata.Orientation.Vertical;
rbg.component().iconHeight = '30px';
rbg.component().iconWidth = '30px';
products.forEach((product) => { products.forEach((product) => {
const imagePath = path.resolve(this.migrationStateModel.getExtensionPath(), 'media', product.icon ?? 'ads.svg'); const imagePath = path.resolve(this.migrationStateModel.getExtensionPath(), 'media', product.icon ?? 'ads.svg');
const descriptions: azdata.RadioCardDescription[] = [
{
textValue: product.name,
linkDisplayValue: 'Learn more',
displayLinkCodicon: true,
textStyles: {
'font-size': '1rem',
'font-weight': 550,
},
linkCodiconStyles: {
'font-size': '1em',
'color': 'royalblue'
}
},
{
textValue: '9 databases will be migrated',
linkDisplayValue: 'View/Change',
displayLinkCodicon: true,
linkCodiconStyles: {
'font-size': '1em',
'color': 'royalblue'
}
}
];
rbg.component().cards.push({ rbg.component().cards.push({
id: product.name, id: product.name,
icon: imagePath, icon: imagePath,
label: product.name descriptions
}); });
}); });

2
src/sql/azdata.d.ts vendored
View File

@@ -3040,7 +3040,7 @@ declare module 'azdata' {
export enum Orientation { export enum Orientation {
Horizontal = 'horizontal', Horizontal = 'horizontal',
Vertical = 'vertial' Vertical = 'vertical'
} }
export interface ToolbarLayout { export interface ToolbarLayout {

View File

@@ -202,22 +202,20 @@ declare module 'azdata' {
export interface RadioCard { export interface RadioCard {
id: string; id: string;
label: string; descriptions: RadioCardDescription[];
descriptions?: RadioCardDescription[];
icon?: string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri }; icon?: string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri };
} }
export interface RadioCardDescription { export interface RadioCardDescription {
ariaLabel: string; textValue: string;
labelHeader: string; linkDisplayValue?: string;
contents: RadioCardLabelValuePair[]; displayLinkCodicon?: boolean;
valueHeader?: string; textStyles?: CssStyles;
linkStyles?: CssStyles;
linkCodiconStyles?: CssStyles;
} }
export interface RadioCardLabelValuePair { export type CssStyles = { [key: string]: string | number };
label: string;
value?: string;
}
export interface RadioCardGroupComponentProperties extends ComponentProperties, TitledComponentProperties { export interface RadioCardGroupComponentProperties extends ComponentProperties, TitledComponentProperties {
cards: RadioCard[]; cards: RadioCard[];
@@ -226,13 +224,20 @@ declare module 'azdata' {
iconWidth?: string; iconWidth?: string;
iconHeight?: string; iconHeight?: string;
selectedCardId?: string; selectedCardId?: string;
orientation?: Orientation // Defaults to horizontal
} }
export type RadioCardSelectionChangedEvent = { cardId: string; card: RadioCard };
export type RadioCardLinkClickEvent = { cardId: string, card: RadioCard, selectorText: RadioCardDescription };
export interface RadioCardGroupComponent extends Component, RadioCardGroupComponentProperties { export interface RadioCardGroupComponent extends Component, RadioCardGroupComponentProperties {
/** /**
* The card object returned from this function is a clone of the internal representation - changes will not impact the original object * The card object returned from this function is a clone of the internal representation - changes will not impact the original object
*/ */
onSelectionChanged: vscode.Event<{ cardId: string; card?: RadioCard }>; onSelectionChanged: vscode.Event<RadioCardSelectionChangedEvent>;
onLinkClick: vscode.Event<RadioCardLinkClickEvent>;
} }
export interface SeparatorComponent extends Component { export interface SeparatorComponent extends Component {

View File

@@ -1696,7 +1696,9 @@ class RadioCardGroupComponentWrapper extends ComponentWrapper implements azdata.
constructor(proxy: MainThreadModelViewShape, handle: number, id: string) { constructor(proxy: MainThreadModelViewShape, handle: number, id: string) {
super(proxy, handle, ModelComponentTypes.RadioCardGroup, id); super(proxy, handle, ModelComponentTypes.RadioCardGroup, id);
this.properties = {}; this.properties = {};
this._emitterMap.set(ComponentEventType.onDidChange, new Emitter<any>());
this._emitterMap.set(ComponentEventType.onDidChange, new Emitter<azdata.RadioCardSelectionChangedEvent>());
this._emitterMap.set(ComponentEventType.onDidClick, new Emitter<azdata.RadioCardLinkClickEvent>());
} }
public get iconWidth(): string | undefined { public get iconWidth(): string | undefined {
@@ -1746,10 +1748,23 @@ class RadioCardGroupComponentWrapper extends ComponentWrapper implements azdata.
this.setProperty('selectedCardId', v); this.setProperty('selectedCardId', v);
} }
public get onSelectionChanged(): vscode.Event<any> { public get orientation(): azdata.Orientation | undefined {
return this.properties['orientation'];
}
public set orientation(orientation: azdata.Orientation | undefined) {
this.setProperty('orientation', orientation);
}
public get onSelectionChanged(): vscode.Event<azdata.RadioCardSelectionChangedEvent> {
let emitter = this._emitterMap.get(ComponentEventType.onDidChange); let emitter = this._emitterMap.get(ComponentEventType.onDidChange);
return emitter && emitter.event; return emitter && emitter.event;
} }
public get onLinkClick(): vscode.Event<azdata.RadioCardLinkClickEvent> {
let emitter = this._emitterMap.get(ComponentEventType.onDidClick);
return emitter && emitter.event;
}
} }
class TabbedPanelComponentWrapper extends ComponentWrapper implements azdata.TabbedPanelComponent { class TabbedPanelComponentWrapper extends ComponentWrapper implements azdata.TabbedPanelComponent {

View File

@@ -374,7 +374,7 @@ export enum CardType {
export enum Orientation { export enum Orientation {
Horizontal = 'horizontal', Horizontal = 'horizontal',
Vertical = 'vertial' Vertical = 'vertical'
} }
/** /**

View File

@@ -1,5 +1,7 @@
<div #cardDiv role="radio" *ngIf="label" [class]="getClass()" (click)="onCardClick()" [attr.aria-checked]="selected" (mouseover)="onCardHoverChanged($event)" <!-- The horizontal is for compatibility, we're going to get rid of this once card component can be removed -->
(mouseout)="onCardHoverChanged($event)" tabIndex="0" [style.width]="width" [style.height]="height"> <div #cardDiv role="radio" *ngIf="label" [class]="getClass() + ' horizontal'" (click)="onCardClick()"
[attr.aria-checked]="selected" (mouseover)="onCardHoverChanged($event)" (mouseout)="onCardHoverChanged($event)"
tabIndex="0" [style.width]="width" [style.height]="height">
<ng-container *ngIf="isVerticalButton || isDetailsCard"> <ng-container *ngIf="isVerticalButton || isDetailsCard">
<span *ngIf="hasStatus" class="card-status"> <span *ngIf="hasStatus" class="card-status">
<div class="status-content" [style.backgroundColor]="statusColor"></div> <div class="status-content" [style.backgroundColor]="statusColor"></div>
@@ -15,8 +17,10 @@
<h4 class="card-label">{{label}}</h4> <h4 class="card-label">{{label}}</h4>
<div *ngIf="descriptions.length > 0" class="model-card-description-container"> <div *ngIf="descriptions.length > 0" class="model-card-description-container">
<div *ngFor="let desc of descriptions"> <div *ngFor="let desc of descriptions">
<div *ngIf="desc.label; else separator" [style.font-weight]="desc.fontWeight" class="model-card-list-item-description"> <div *ngIf="desc.label; else separator" [style.font-weight]="desc.fontWeight"
<span>{{desc.label}}</span><span class="model-card-list-item-description-value">{{desc.value}}</span> class="model-card-list-item-description">
<span>{{desc.label}}</span><span
class="model-card-list-item-description-value">{{desc.value}}</span>
</div> </div>
<ng-template #separator> <ng-template #separator>
<div style="height: 12px"></div> <div style="height: 12px"></div>

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
.model-card { .horizontal .model-card {
position: relative; position: relative;
display: inline-block; display: inline-block;
height: 90%; height: 90%;
@@ -16,7 +16,7 @@
border-color: rgb(214, 214, 214); border-color: rgb(214, 214, 214);
} }
.model-card .card-content { .horizontal .model-card .card-content {
position: relative; position: relative;
display: inline-block; display: inline-block;
height: auto; height: auto;
@@ -26,7 +26,8 @@
min-width: 30px; min-width: 30px;
} }
.model-card .card-vertical-button { .horizontal .model-card .card-vertical-button,
.horizontal .model-card .text-container {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -38,17 +39,17 @@
min-width: 130px; min-width: 130px;
} }
.model-card .card-label { .horizontal .model-card .card-label {
font-size: 12px; font-size: 12px;
font-weight: bold; font-weight: bold;
} }
.model-card .card-value { .horizontal .model-card .card-value {
font-size: 12px; font-size: 12px;
line-height: 18px; line-height: 18px;
} }
.model-card .iconContainer { .horizontal .model-card .icon-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
@@ -60,7 +61,7 @@
border-color: rgb(214, 214, 214); border-color: rgb(214, 214, 214);
} }
.model-card .cardIcon { .horizontal .model-card .icon {
display: inline-block; display: inline-block;
flex-grow: 1; flex-grow: 1;
width: 100%; width: 100%;
@@ -72,7 +73,7 @@
background-size: contain; background-size: contain;
} }
.model-card .card-status { .horizontal .model-card .card-status {
position: absolute; position: absolute;
top: 7px; top: 7px;
left: 5px; left: 5px;
@@ -81,7 +82,7 @@
height: 22px; height: 22px;
} }
.model-card .status-content { .horizontal .model-card .status-content {
position: absolute; position: absolute;
top: 0px; top: 0px;
right: 0px; right: 0px;
@@ -91,7 +92,8 @@
text-align: center; text-align: center;
} }
.model-card-list-item .selection-indicator-container, .model-card .selection-indicator-container { .horizontal .model-card-list-item .selection-indicator-container,
.horizontal .model-card .selection-indicator-container {
position: absolute; position: absolute;
top: 5px; top: 5px;
right: 5px; right: 5px;
@@ -105,7 +107,8 @@
border-style: solid; border-style: solid;
} }
.model-card-list-item .selection-indicator-container, .model-card .selection-indicator-container { .horizontal .model-card-list-item .selection-indicator-container,
.horizontal .model-card .selection-indicator-container {
position: absolute; position: absolute;
overflow: hidden; overflow: hidden;
width: 16px; width: 16px;
@@ -117,17 +120,18 @@
border-style: solid; border-style: solid;
} }
.model-card-list-item .selection-indicator-container { .horizontal .model-card-list-item .selection-indicator-container {
top: 10px; top: 10px;
right: 10px; right: 10px;
} }
.model-card .selection-indicator-container { .horizontal .model-card .selection-indicator-container {
top: 5px; top: 5px;
right: 5px; right: 5px;
} }
.model-card-list-item .selection-indicator, .model-card .selection-indicator { .horizontal .model-card-list-item .selection-indicator,
.horizontal .model-card .selection-indicator {
margin: 4px; margin: 4px;
width: 8px; width: 8px;
height: 8px; height: 8px;
@@ -135,26 +139,26 @@
background-color: rgb(0, 120, 215); background-color: rgb(0, 120, 215);
} }
.model-card .model-table { .horizontal .model-card .model-table {
border-spacing: 5px; border-spacing: 5px;
} }
.model-table .table-row { .horizontal .model-table .table-row {
width: auto; width: auto;
clear: both; clear: both;
} }
.model-table .table-cell { .horizontal .model-table .table-cell {
vertical-align: top; vertical-align: top;
padding: 7px; padding: 7px;
} }
.model-table a { .horizontal .model-table a {
cursor: pointer; cursor: pointer;
text-decoration: underline text-decoration: underline
} }
.model-card-list-item { .horizontal .model-card-list-item {
display: inline-block; display: inline-block;
height: 100%; height: 100%;
width: 100%; width: 100%;
@@ -165,14 +169,14 @@
vertical-align: top; vertical-align: top;
} }
.model-card-list-item .list-item-content { .horizontal .model-card-list-item .list-item-content {
height: auto; height: auto;
padding: 5px 26px 5px 5px; padding: 5px 26px 5px 5px;
min-height: 30px; min-height: 30px;
min-width: 300px; min-width: 300px;
} }
.model-card-list-item .list-item-icon { .horizontal .model-card-list-item .list-item-icon {
background-position: 2px 2px; background-position: 2px 2px;
padding-left: 22px; padding-left: 22px;
font-size: 15px; font-size: 15px;
@@ -180,40 +184,40 @@
background-size: 16px 16px; background-size: 16px 16px;
} }
.model-card-list-item .list-item-description { .horizontal .model-card-list-item .list-item-description {
padding-left: 22px; padding-left: 22px;
} }
.model-card-description-container { .horizontal .model-card-description-container {
border-top-width: 1px; border-top-width: 1px;
border-top-style: solid; border-top-style: solid;
border-color: rgb(214, 214, 214); border-color: rgb(214, 214, 214);
padding: 5px; padding: 5px;
} }
.model-card-list-item-description { .horizontal .model-card-list-item-description {
text-align: left; text-align: left;
} }
.model-card-list-item-description-value { .horizontal .model-card-list-item-description-value {
float: right; float: right;
} }
.card-group { .horizontal .card-group {
display: flex; display: flex;
flex-flow: row; flex-flow: row;
} }
.model-card-description-table { .horizontal .model-card-description-table {
margin-bottom: 10px; margin-bottom: 10px;
} }
.model-card-description-label-column { .horizontal .model-card-description-label-column {
text-align: left; text-align: left;
width: 100%; width: 100%;
} }
.model-card-description-value-column { .horizontal .model-card-description-value-column {
text-align: right; text-align: right;
white-space: nowrap; white-space: nowrap;
} }

View File

@@ -0,0 +1,86 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/*
!!!!NOTICE!!!!
This CSS file is only to be used with vertical selector.
If you want to reuse some of the stuff here, just copy/paste them.
*/
.vertical .card-group {
display: flex;
flex-direction: column;
}
.vertical .model-card {
display: flex;
flex-direction: row;
align-items: center;
padding: 10px;
}
.vertical .model-card .model-card>* {
margin: 5px;
}
.vertical .model-card .selection-indicator-container {
width: 16px;
height: 16px;
border-radius: 50%;
background-color: white;
border-width: 1px;
border-color: rgb(214, 214, 214);
border-style: solid;
}
.vertical .model-card .selection-indicator {
border-radius: 50%;
width: 8px;
height: 8px;
background-color: rgb(0, 120, 215);
margin: 4px;
}
/* Icon container */
.vertical .model-card .icon-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding-right: 5px;
padding-left: 5px;
}
/* The icon itself */
.vertical .model-card .icon-container .icon {
display: inline-block;
width: 100%;
height: 100%;
max-width: 50px;
max-height: 50px;
background-position: center;
background-repeat: no-repeat;
background-size: contain;
}
.vertical .model-card .text-container {
display: flex;
flex-direction: column;
padding-left: 5px;
}
.vertical .model-card .text-container .inner-text-content {
display: flex;
flex-direction: row;
padding-bottom: 5px;
}
.vertical .model-card .text-value {
padding-right: 5px;
}
.vertical .model-card .link-value .codicon {
padding-left: 5px;
}

View File

@@ -1,31 +1,27 @@
<div role="radiogroup" *ngIf="cards" class="card-group" style="flex-wrap:wrap" [style.height]="height" <div role="radiogroup" *ngIf="cards" [class]="orientation + ' card-group'" class="card-group" style="flex-wrap:wrap"
[style.width]="width" [attr.aria-label]="ariaLabel" (keydown)="onKeyDown($event)"> [style.height]="height" [style.width]="width" [attr.aria-label]="ariaLabel" (keydown)="onKeyDown($event)">
<div #cardDiv role="radio" *ngFor="let card of cards" class="model-card" (click)="selectCard(card.id)" <div #cardDiv role="radio" *ngFor="let card of cards" class="model-card" (click)="selectCard(card.id)"
[attr.aria-checked]="isCardSelected(card.id)" [tabIndex]="getTabIndex(card.id)" [style.width]="cardWidth" [attr.aria-checked]="isCardSelected(card.id)" [tabIndex]="getTabIndex(card.id)" [style.width]="cardWidth"
[style.height]="cardHeight" (focus)="onCardFocus(card.id)" (blur)="onCardBlur(card.id)" style="flex:0 0 auto;"> [style.height]="cardHeight" (focus)="onCardFocus(card.id)" (blur)="onCardBlur(card.id)" style="flex:0 0 auto;">
<span class="selection-indicator-container">
<div *ngIf="isCardSelected(card.id)" class="selection-indicator"></div> <div class="selection-indicator-container">
</span> <div *ngIf="isCardSelected(card.id)" class="selection-indicator"></div>
<div class="card-vertical-button">
<div *ngIf="card.icon" class="iconContainer">
<div [class]="getIconClass(card.id)" [style.width]="iconWidth" [style.height]="iconHeight"></div>
</div> </div>
<h4 class="card-label">{{card.label}}</h4>
<div *ngIf="card.descriptions && card.descriptions.length > 0" class="model-card-description-container"> <div *ngIf="card.icon" class="icon-container">
<ng-container *ngFor="let desc of card.descriptions"> <div [class]="getIconClass(card.id)" [style.width]="iconWidth" [style.height]="iconHeight"> </div>
<table class="model-card-description-table" [attr.aria-label]="desc.ariaLabel"> </div>
<tr> <div class="text-container">
<th class="model-card-description-label-column">{{desc.labelHeader}}</th> <div *ngFor="let description of card.descriptions" class="inner-text-content">
<th class="model-card-description-value-column" *ngIf="desc.valueHeader"> <span class="text-value" [ngStyle]="description.textStyles">{{description.textValue}}</span>
{{desc.valueHeader}}</th> <a *ngIf="description.linkDisplayValue" class="link-value" href="#"
</tr> (click)="onLinkClick($event, card.id, description)"
<tr *ngFor="let content of desc.contents"> [ngStyle]="description.linkStyles">
<td class="model-card-description-label-column">{{content.label}}</td> {{description.linkDisplayValue}}
<td class="model-card-description-value-column" *ngIf="content.value">{{content.value}}</td> <span *ngIf="description.displayLinkCodicon && description.linkDisplayValue"
</tr> class="codicon codicon-link-external" [ngStyle]="description.linkCodiconStyles"></span>
</table> </a>
</ng-container> </div>
</div> </div>
</div> </div>
</div> </div>
</div>

View File

@@ -9,13 +9,15 @@ import { createIconCssClass } from 'sql/workbench/browser/modelComponents/iconUt
import * as DOM from 'vs/base/browser/dom'; import * as DOM from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes'; import { KeyCode } from 'vs/base/common/keyCodes';
import 'vs/css!./media/card'; import 'vs/css!./media/card';
import 'vs/css!./media/verticalCard';
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/platform/dashboard/browser/interfaces'; import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/platform/dashboard/browser/interfaces';
import { deepClone } from 'vs/base/common/objects'; import { deepClone } from 'vs/base/common/objects';
@Component({ @Component({
templateUrl: decodeURI(require.toUrl('./radioCardGroup.component.html')) templateUrl: decodeURI(require.toUrl('./radioCardGroup.component.html'))
}) })
export default class RadioCardGroup extends ComponentBase implements IComponent, OnDestroy { export default class RadioCardGroup extends ComponentBase implements IComponent, OnDestroy {
@Input() descriptor: IComponentDescriptor; @Input() descriptor: IComponentDescriptor;
@@ -94,27 +96,36 @@ export default class RadioCardGroup extends ComponentBase implements IComponent,
} }
public get cards(): azdata.RadioCard[] { public get cards(): azdata.RadioCard[] {
return this.getPropertyOrDefault<azdata.RadioCardGroupComponentProperties, azdata.RadioCard[]>((props) => props.cards, []); return this.getSpecficProperties().cards ?? [];
} }
public get cardWidth(): string | undefined { public get cardWidth(): string | undefined {
return this.getPropertyOrDefault<azdata.RadioCardGroupComponentProperties, string | undefined>((props) => props.cardWidth, undefined); return this.getSpecficProperties().cardWidth ?? undefined;
} }
public get cardHeight(): string | undefined { public get cardHeight(): string | undefined {
return this.getPropertyOrDefault<azdata.RadioCardGroupComponentProperties, string | undefined>((props) => props.cardHeight, undefined); return this.getSpecficProperties().cardHeight ?? undefined;
} }
public get iconWidth(): string | undefined { public get iconWidth(): string | undefined {
return this.getPropertyOrDefault<azdata.RadioCardGroupComponentProperties, string | undefined>((props) => props.iconWidth, undefined); return this.getSpecficProperties().iconWidth ?? undefined;
} }
public get iconHeight(): string | undefined { public get iconHeight(): string | undefined {
return this.getPropertyOrDefault<azdata.RadioCardGroupComponentProperties, string | undefined>((props) => props.iconHeight, undefined); return this.getSpecficProperties().iconHeight ?? undefined;
} }
public get selectedCardId(): string | undefined { public get selectedCardId(): string | undefined {
return this.getPropertyOrDefault<azdata.RadioCardGroupComponentProperties, string | undefined>((props) => props.selectedCardId, undefined); return this.getSpecficProperties().selectedCardId ?? undefined;
}
public get orientation(): string {
const x = this.getSpecficProperties().orientation ?? 'horizontal';
return x;
}
private getSpecficProperties(): azdata.RadioCardGroupComponentProperties {
return this.getProperties<azdata.RadioCardGroupComponentProperties>();
} }
public getIconClass(cardId: string): string { public getIconClass(cardId: string): string {
@@ -149,6 +160,18 @@ export default class RadioCardGroup extends ComponentBase implements IComponent,
}); });
} }
public onLinkClick(event: Event, cardId: string, textContents: azdata.RadioCardDescription): void {
event.stopPropagation();
this.fireEvent({
eventType: ComponentEventType.onDidClick,
args: {
cardId,
textContents: deepClone(textContents),
card: deepClone(this.getCardById(cardId))
}
});
}
public getCardElement(cardId: string): ElementRef { public getCardElement(cardId: string): ElementRef {
const card = this.getCardById(cardId); const card = this.getCardById(cardId);
return this.cardElements.toArray()[this.cards.indexOf(card)]; return this.cardElements.toArray()[this.cards.indexOf(card)];

View File

@@ -14,7 +14,7 @@ import { IComponentDescriptor, IComponent, IModelStore } from 'sql/platform/dash
export enum Orientation { export enum Orientation {
Horizontal = 'horizontal', Horizontal = 'horizontal',
Vertical = 'vertial' Vertical = 'vertical'
} }
export interface ToolbarLayout { export interface ToolbarLayout {