Skip to content

Commit 716319d

Browse files
authored
Merge branch 'master' into tabs
2 parents 97e3462 + ca132ea commit 716319d

11 files changed

+203
-10
lines changed

src/breadcrumb/breadcrumb-item.component.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import {
88
selector: "ibm-breadcrumb-item",
99
template: `
1010
<a class="bx--link"
11-
href="{{href}}"
12-
*ngIf="href; else content">
11+
href="{{skeleton ? href : '/#'}}"
12+
*ngIf="skeleton || href; else content">
1313
<ng-container *ngTemplateOutlet="content"></ng-container>
1414
</a>
1515
<ng-template #content>
@@ -19,5 +19,7 @@ import {
1919
export class BreadcrumbItemComponent {
2020
@Input() href: string;
2121

22+
@Input() skeleton = false;
23+
2224
@HostBinding("class.bx--breadcrumb-item") itemClass = true;
2325
}

src/breadcrumb/breadcrumb.component.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import {
22
Component,
3-
Input
3+
Input,
4+
ContentChildren,
5+
QueryList,
6+
AfterContentInit
47
} from "@angular/core";
58

69
import { BreadcrumbItem } from "./breadcrumb-item.interface";
10+
import { BreadcrumbItemComponent } from "./breadcrumb-item.component";
711

812
const MINIMUM_OVERFLOW_THRESHOLD = 4;
913

@@ -12,6 +16,7 @@ const MINIMUM_OVERFLOW_THRESHOLD = 4;
1216
template: `
1317
<nav #nav class="bx--breadcrumb"
1418
[ngClass]="{
19+
'bx--skeleton' : skeleton,
1520
'bx--breadcrumb--no-trailing-slash' : noTrailingSlash
1621
}"
1722
[attr.aria-label]="ariaLabel">
@@ -50,14 +55,27 @@ const MINIMUM_OVERFLOW_THRESHOLD = 4;
5055
</ng-template>
5156
</nav>`
5257
})
53-
export class Breadcrumb {
58+
export class Breadcrumb implements AfterContentInit {
59+
@ContentChildren(BreadcrumbItemComponent) children: QueryList<BreadcrumbItemComponent>;
60+
5461
@Input() items: Array<BreadcrumbItem>;
5562

5663
@Input() noTrailingSlash = false;
5764

5865
@Input() ariaLabel: string;
5966

6067
protected _threshold: number;
68+
protected _skeleton = false;
69+
70+
@Input()
71+
set skeleton(value: any) {
72+
this._skeleton = value;
73+
this.updateChildren();
74+
}
75+
76+
get skeleton(): any {
77+
return this._skeleton;
78+
}
6179

6280
@Input()
6381
set threshold(threshold: number) {
@@ -71,6 +89,10 @@ export class Breadcrumb {
7189
return this._threshold;
7290
}
7391

92+
ngAfterContentInit() {
93+
this.updateChildren();
94+
}
95+
7496
get shouldShowContent(): boolean {
7597
return !this.items;
7698
}
@@ -97,4 +119,10 @@ export class Breadcrumb {
97119
get last(): BreadcrumbItem {
98120
return this.shouldShowOverflow ? this.items[this.items.length - 1] : null;
99121
}
122+
123+
protected updateChildren() {
124+
if (this.children) {
125+
this.children.toArray().forEach(child => child.skeleton = this.skeleton);
126+
}
127+
}
100128
}

src/breadcrumb/breadcrumb.stories.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,16 @@ storiesOf("Breadcrumb", module)
5757
threshold: number("threshold", 4),
5858
items: createBreadcrumbItems
5959
}
60+
}))
61+
.add("Skeleton", () => ({
62+
template: `
63+
<ibm-breadcrumb skeleton="true" [noTrailingSlash]="noTrailingSlash">
64+
<ibm-breadcrumb-item></ibm-breadcrumb-item>
65+
<ibm-breadcrumb-item></ibm-breadcrumb-item>
66+
<ibm-breadcrumb-item></ibm-breadcrumb-item>
67+
<ibm-breadcrumb-item></ibm-breadcrumb-item>
68+
</ibm-breadcrumb>`,
69+
props: {
70+
noTrailingSlash: boolean("noTrailingSlash", true)
71+
}
6072
}));

src/checkbox/checkbox.component.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,12 @@ export class CheckboxChange {
7070
[attr.aria-checked]="(indeterminate ? 'mixed' : checked)"
7171
(change)="onChange($event)"
7272
(click)="onClick($event)">
73-
<label [for]="id" class="bx--checkbox-label">
73+
<label
74+
[for]="id"
75+
class="bx--checkbox-label"
76+
[ngClass]="{
77+
'bx--skeleton' : skeleton
78+
}">
7479
<ng-content></ng-content>
7580
</label>
7681
`,
@@ -107,6 +112,10 @@ export class Checkbox implements ControlValueAccessor, AfterViewInit {
107112
* Set to `true` for a disabled checkbox.
108113
*/
109114
@Input() disabled = false;
115+
/**
116+
* Set to `true` for a loading checkbox.
117+
*/
118+
@Input() skeleton = false;
110119
/**
111120
* Sets the name attribute on the `input` element.
112121
*/

src/checkbox/checkbox.stories.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,7 @@ storiesOf("Checkbox", module).addDecorator(
2828
onChange: action("Change fired!"),
2929
onIndeterminateChange: action("Indeterminate change fired!")
3030
}
31-
}));
31+
}))
32+
.add("Skeleton", () => ({
33+
template: `<ibm-checkbox skeleton="true"></ibm-checkbox>`
34+
}));

src/progress-indicator/progress-indicator.component.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ import { Component, Input } from "@angular/core";
33
@Component({
44
selector: "ibm-progress-indicator",
55
template: `
6-
<ul data-progress data-progress-current class="bx--progress">
6+
<ul
7+
data-progress
8+
data-progress-current
9+
class="bx--progress"
10+
[ngClass]="{
11+
'bx--skeleton': skeleton
12+
}">
713
<li
814
class="bx--progress-step bx--progress-step--{{step.state}}"
915
*ngFor="let step of steps; let i = index">
@@ -27,5 +33,15 @@ import { Component, Input } from "@angular/core";
2733
`
2834
})
2935
export class ProgressIndicator {
36+
static skeletonSteps(stepCount: number) {
37+
const steps = [];
38+
for (let i = 0; i < stepCount; i++) {
39+
steps.push({"state": ["incomplete"]});
40+
}
41+
42+
return steps;
43+
}
44+
3045
@Input() steps = [];
46+
@Input() skeleton = false;
3147
}

src/progress-indicator/progrss-indicator.stories.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,40 @@
1+
import {
2+
Component,
3+
Input,
4+
OnInit
5+
} from "@angular/core";
16
import { storiesOf, moduleMetadata } from "@storybook/angular";
27
import { withNotes } from "@storybook/addon-notes";
38
import { action } from "@storybook/addon-actions";
49
import { withKnobs, boolean, object } from "@storybook/addon-knobs/angular";
510

611
import { ProgressIndicatorModule } from "../";
12+
import { ProgressIndicator } from "./progress-indicator.component";
13+
14+
@Component({
15+
selector: "app-skeleton-progress-indicator",
16+
template: `
17+
<ibm-progress-indicator [steps]="skeletonSteps" skeleton="true">
18+
</ibm-progress-indicator>
19+
`
20+
})
21+
class SkeletonStory implements OnInit {
22+
@Input() skeletonSteps = [];
23+
24+
ngOnInit() {
25+
// Creates an empty progress indicator with 4 steps
26+
this.skeletonSteps = ProgressIndicator.skeletonSteps(4);
27+
}
28+
}
729

830
storiesOf("ProgressIndicator", module)
931
.addDecorator(
1032
moduleMetadata({
1133
imports: [
1234
ProgressIndicatorModule
35+
],
36+
declarations: [
37+
SkeletonStory
1338
]
1439
})
1540
)
@@ -47,4 +72,9 @@ storiesOf("ProgressIndicator", module)
4772
}
4873
]
4974
}
75+
}))
76+
.add("Skeleton", () => ({
77+
template: `
78+
<app-skeleton-progress-indicator></app-skeleton-progress-indicator>
79+
`
5080
}));

src/structured-list/list-column.component.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,14 @@ import { Component, HostBinding, Input } from "@angular/core";
1212
*/
1313
@Component({
1414
selector: "ibm-list-column",
15-
template: `<ng-content></ng-content>`
15+
template: `
16+
<span *ngIf="skeleton"></span>
17+
<ng-content></ng-content>
18+
`
1619
})
1720
export class ListColumn {
21+
@Input() skeleton = false;
22+
1823
@HostBinding("class.bx--structured-list-th") isHeaderColumn = true;
1924
@HostBinding("class.bx--structured-list-td") isBodyColumn = true;
2025
/**

src/structured-list/list-header.component.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import {
33
HostBinding,
44
ContentChildren,
55
QueryList,
6-
AfterContentInit
6+
AfterContentInit,
7+
Input
78
} from "@angular/core";
89
import { ListColumn } from "./list-column.component";
910

@@ -31,17 +32,36 @@ import { ListColumn } from "./list-column.component";
3132
export class ListHeader implements AfterContentInit {
3233
@HostBinding("class.bx--structured-list-thead") wrapper = true;
3334

35+
@Input()
36+
set skeleton(value: any) {
37+
this._skeleton = value;
38+
this.updateChildren();
39+
}
40+
41+
get skeleton(): any {
42+
return this._skeleton;
43+
}
44+
3445
@ContentChildren(ListColumn) columns: QueryList<ListColumn>;
3546

3647
/**
3748
* Set by the containing `StructuredList`. Adds a dummy header for the selection column when set to true.
3849
*/
3950
selection = false;
4051

52+
protected _skeleton = false;
53+
4154
ngAfterContentInit() {
4255
this.columns.forEach(column => {
4356
column.isBodyColumn = false;
4457
column.isHeaderColumn = true;
4558
});
59+
this.updateChildren();
60+
}
61+
62+
protected updateChildren() {
63+
if (this.columns) {
64+
this.columns.toArray().forEach(child => child.skeleton = this.skeleton);
65+
}
4666
}
4767
}

src/structured-list/structured-list.component.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ import { NG_VALUE_ACCESSOR, ControlValueAccessor } from "@angular/forms";
5858
'bx--structured-list--border': border,
5959
'bx--structured-list--selection': selection,
6060
'bx--structured-list--condensed': condensed,
61-
'bx--structured-list-content--nowrap': nowrap
61+
'bx--structured-list-content--nowrap': nowrap,
62+
'bx--skeleton': skeleton
6263
}">
6364
<ng-content select="ibm-list-header"></ng-content>
6465
<div class="bx--structured-list-tbody">
@@ -99,6 +100,23 @@ export class StructuredList implements AfterContentInit, ControlValueAccessor {
99100
* Used when `selection = true` as the row radio group `name`
100101
*/
101102
@Input() name = `structured-list-${StructuredList.listCount++}`;
103+
104+
/**
105+
* Sets the skeleton value for all `ListHeader` to the skeleton value of `StructuredList`.
106+
*/
107+
@Input()
108+
set skeleton(value: any) {
109+
this._skeleton = value;
110+
this.updateChildren();
111+
}
112+
113+
/**
114+
* Returns the skeleton value in the `StructuredList` if there is one.
115+
*/
116+
get skeleton(): any {
117+
return this._skeleton;
118+
}
119+
102120
/**
103121
* Emits an event when the row selection changes.
104122
*
@@ -116,6 +134,8 @@ export class StructuredList implements AfterContentInit, ControlValueAccessor {
116134
@ContentChildren(ListRow) rows: QueryList<ListRow>;
117135
@ContentChildren(ListHeader) headers: QueryList<ListHeader>;
118136

137+
protected _skeleton = false;
138+
119139
onChange = (_: any) => { };
120140

121141
onTouched = () => { };
@@ -138,6 +158,7 @@ export class StructuredList implements AfterContentInit, ControlValueAccessor {
138158
this.onChange(row.value);
139159
});
140160
});
161+
this.updateChildren();
141162
}
142163

143164
writeValue(value: any) {
@@ -158,4 +179,10 @@ export class StructuredList implements AfterContentInit, ControlValueAccessor {
158179
registerOnTouched(fn: any) {
159180
this.onTouched = fn;
160181
}
182+
183+
protected updateChildren() {
184+
if (this.headers) {
185+
this.headers.toArray().forEach(child => child.skeleton = this.skeleton);
186+
}
187+
}
161188
}

0 commit comments

Comments
 (0)