Skip to content

Commit e821cea

Browse files
committed
feat(): add progress-fab component.
1 parent d4a3cde commit e821cea

12 files changed

+348
-3
lines changed

src/components/progress-circle/progress-circle.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export class MdProgressCircle {
5656
// total circumference.
5757

5858
// The total circumference is calculated based on the radius we use, 45.
59-
// PI * 2 * 45
59+
// PI * 2 * 40
6060
return 251.3274 * (100 - this._value) / 100;
6161
}
6262

src/components/progress-fab/README.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# MdProgressFab
2+
`MdProgressFab` is a normal FAB button surrounded with a `progress-circle`.
3+
4+
### Screenshots
5+
![Preview](https://cloud.githubusercontent.com/assets/4987015/14406410/eaf20a54-fea6-11e5-8a24-4f751df7e80a.png)
6+
7+
## `[md-progress-fab]`
8+
### Bound Properties
9+
10+
| Name | Type | Description |
11+
| --- | --- | --- |
12+
| `color` | `"primary" | "accent" | "warn"` | The color palette for the FAB button |
13+
| `value` | `number` | Value for the `progress-circle`.<br/> Necessary when using the `determinate` mode. |
14+
| `mode` | `"determinate" | "indeterminate"` | Mode for the `progress-circle`.<br/> |
15+
| `progressColor` | `"primary" | "accent" | "warn"` | Color for the `progress-circle`.<br/> |
16+
17+
18+
### Examples
19+
A basic progress-fab will have the markup:
20+
```html
21+
<button md-progress-fab color="accent">
22+
<i class="material-icons md-24">favorite</i>
23+
</button>
24+
```
25+
It will use by default a `indeterminate` progress circle.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<span class="md-button-wrapper">
2+
<ng-content></ng-content>
3+
4+
<div class="md-progress-wrap">
5+
<md-progress-circle
6+
[mode]="progressMode"
7+
[value]="progressValue"
8+
[attr.color]="progressColor">
9+
</md-progress-circle>
10+
</div>
11+
</span>
12+
13+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
@import "../button/button-base";
2+
3+
$md-fab-progress-stroke: 6px;
4+
5+
// Subtract 1px to avoid the ugly space between FAB button and progress circle.
6+
$md-fab-progress-rectangle: ($md-fab-size + $md-fab-padding + $md-fab-progress-stroke / 2) - 1px;
7+
8+
:host {
9+
@include md-fab($md-fab-size, $md-fab-padding);
10+
11+
margin: $md-fab-progress-stroke;
12+
13+
.md-progress-wrap {
14+
position: absolute;
15+
top: 50%;
16+
left: 50%;
17+
18+
transform: translate3d(-50%, -50%, 0);
19+
20+
md-progress-circle {
21+
width: $md-fab-progress-rectangle;
22+
height: $md-fab-progress-rectangle;
23+
24+
svg {
25+
overflow: visible;
26+
27+
circle {
28+
stroke-width: $md-fab-progress-stroke;
29+
}
30+
}
31+
}
32+
}
33+
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import {
2+
it,
3+
describe,
4+
expect,
5+
beforeEach,
6+
inject,
7+
TestComponentBuilder
8+
} from 'angular2/testing';
9+
import {Component} from 'angular2/core';
10+
import {By} from 'angular2/platform/browser';
11+
import {MdProgressFab} from './progress-fab';
12+
import {MdProgressCircle} from '../progress-circle/progress-circle';
13+
14+
export function main() {
15+
describe('MdProgressFab', () => {
16+
let builder: TestComponentBuilder;
17+
18+
beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
19+
builder = tcb;
20+
}));
21+
22+
it('should correctly apply the color attribute on the progress circle', (done: () => void) => {
23+
return builder
24+
.createAsync(TestApp)
25+
.then((fixture) => {
26+
let testComponent = fixture.debugElement.componentInstance;
27+
let progressDebugElement = fixture.debugElement.query(By.css('md-progress-circle'));
28+
29+
testComponent.progressColor = 'primary';
30+
fixture.detectChanges();
31+
32+
expect(progressDebugElement.nativeElement.getAttribute('color')).toBe('primary');
33+
34+
testComponent.progressColor = 'accent';
35+
fixture.detectChanges();
36+
37+
expect(progressDebugElement.nativeElement.getAttribute('color')).toBe('accent');
38+
39+
done();
40+
});
41+
});
42+
43+
it('should correctly apply the mode on the progress circle', (done: () => void) => {
44+
return builder
45+
.createAsync(TestApp)
46+
.then((fixture) => {
47+
let testComponent = fixture.debugElement.componentInstance;
48+
let progressComponent: MdProgressCircle = fixture.debugElement
49+
.query(By.css('md-progress-circle')).componentInstance;
50+
51+
testComponent.progressMode = 'determinate';
52+
fixture.detectChanges();
53+
54+
expect(progressComponent.mode).toBe('determinate');
55+
56+
testComponent.progressColor = 'indeterminate';
57+
fixture.detectChanges();
58+
59+
expect(progressComponent.mode).toBe('determinate');
60+
61+
done();
62+
});
63+
});
64+
65+
it('should correctly apply the value on the progress circle', (done: () => void) => {
66+
return builder
67+
.createAsync(TestApp)
68+
.then((fixture) => {
69+
let testComponent = fixture.debugElement.componentInstance;
70+
let progressComponent: MdProgressCircle = fixture.debugElement
71+
.query(By.css('md-progress-circle')).componentInstance;
72+
73+
testComponent.progressValue = 50;
74+
fixture.detectChanges();
75+
76+
expect(progressComponent._value).toBe(50);
77+
78+
testComponent.progressValue = 70;
79+
fixture.detectChanges();
80+
81+
expect(progressComponent._value).toBe(70);
82+
83+
done();
84+
});
85+
});
86+
87+
it('should correctly apply the color on the button', (done: () => void) => {
88+
return builder
89+
.createAsync(TestApp)
90+
.then((fixture) => {
91+
let testComponent = fixture.debugElement.componentInstance;
92+
let buttonDebugElement = fixture.debugElement.query(By.css('button'));
93+
94+
testComponent.buttonColor = 'primary';
95+
fixture.detectChanges();
96+
97+
expect(buttonDebugElement.nativeElement.classList.contains('md-primary')).toBe(true);
98+
99+
testComponent.buttonColor = 'accent';
100+
fixture.detectChanges();
101+
expect(buttonDebugElement.nativeElement.classList.contains('md-accent')).toBe(true);
102+
103+
done();
104+
});
105+
});
106+
107+
});
108+
}
109+
110+
@Component({
111+
selector: 'test-app',
112+
template: `
113+
<button md-progress-fab [color]="buttonColor" [progressColor]="progressColor"
114+
[mode]="progressMode" [value]="progressValue">
115+
</button>`,
116+
directives: [MdProgressFab]
117+
})
118+
class TestApp {
119+
buttonColor: string = 'primary';
120+
progressColor: string = 'accent';
121+
progressMode: string = 'indeterminate';
122+
progressValue: number = 0;
123+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import {
2+
Component,
3+
ChangeDetectionStrategy,
4+
Renderer,
5+
ElementRef,
6+
Input
7+
} from 'angular2/core';
8+
import {MdProgressCircle} from '../progress-circle/progress-circle';
9+
import {MdButton} from '../button/button';
10+
11+
@Component({
12+
selector: '[md-progress-fab]:not(a)',
13+
templateUrl: './components/progress-fab/progress-fab.html',
14+
styleUrls: ['./components/progress-fab/progress-fab.css'],
15+
directives: [MdProgressCircle],
16+
inputs: ['color'],
17+
host: {
18+
'[class.md-button-focus]': 'isKeyboardFocused',
19+
'(mousedown)': 'setMousedown()',
20+
'(focus)': 'setKeyboardFocus()',
21+
'(blur)': 'removeKeyboardFocus()'
22+
},
23+
changeDetection: ChangeDetectionStrategy.OnPush,
24+
})
25+
export class MdProgressFab extends MdButton {
26+
27+
@Input('mode') progressMode: string = 'indeterminate';
28+
@Input('value') progressValue: number;
29+
@Input('progressColor') progressColor: string;
30+
31+
constructor(elementRef: ElementRef, renderer: Renderer) {
32+
super(elementRef, renderer);
33+
}
34+
35+
}

src/demo-app/button/button-demo.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
import {Component} from 'angular2/core';
22
import {MdButton, MdAnchor} from '../../components/button/button';
3+
import {MdProgressFab} from '../../components/progress-fab/progress-fab';
34

45
@Component({
56
selector: 'button-demo',
67
templateUrl: 'demo-app/button/button-demo.html',
78
styleUrls: ['demo-app/button/button-demo.css'],
8-
directives: [MdButton, MdAnchor]
9+
directives: [MdButton, MdAnchor, MdProgressFab]
910
})
1011
export class ButtonDemo {
1112
isDisabled: boolean = false;
1213
clickCounter: number = 0;
14+
fabProgressValue: number = 0;
15+
16+
constructor() {
17+
18+
setInterval(() => this.increaseFabProgress(), 200);
19+
}
20+
21+
increaseFabProgress() {
22+
this.fabProgressValue += 7;
23+
}
1324
}

src/demo-app/demo-app.html

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ <h1>Angular Material2 Demos</h1>
55
<li><a [routerLink]="['CardDemo']">Card demo</a></li>
66
<li><a [routerLink]="['ProgressCircleDemo']">Progress Circle demo</a></li>
77
<li><a [routerLink]="['ProgressBarDemo']">Progress Bar demo</a></li>
8+
<li><a [routerLink]="['ProgressFabDemo']">Progress Fab demo</a></li>
89
<li><a [routerLink]="['PortalDemo']">Portal demo</a></li>
910
<li><a [routerLink]="['OverlayDemo']">Overlay demo</a></li>
1011
<li><a [routerLink]="['CheckboxDemo']">Checkbox demo</a></li>

src/demo-app/demo-app.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {ListDemo} from './list/list-demo';
1616
import {InputDemo} from './input/input-demo';
1717
import {LiveAnnouncerDemo} from './live-announcer/live-announcer-demo';
1818
import {GesturesDemo} from './gestures/gestures-demo';
19+
import {ProgressFabDemo} from './progress-fab/progress-fab-demo';
1920

2021
@Component({
2122
selector: 'home',
@@ -46,6 +47,7 @@ export class Home {}
4647
new Route({path: '/toolbar', name: 'ToolbarDemo', component: ToolbarDemo}),
4748
new Route({path: '/list', name: 'ListDemo', component: ListDemo}),
4849
new Route({path: '/live-announcer', name: 'LiveAnnouncerDemo', component: LiveAnnouncerDemo}),
49-
new Route({path: '/gestures', name: 'GesturesDemo', component: GesturesDemo})
50+
new Route({path: '/gestures', name: 'GesturesDemo', component: GesturesDemo}),
51+
new Route({path: '/progress-fab', name: 'ProgressFabDemo', component: ProgressFabDemo}),
5052
])
5153
export class DemoApp { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<div class="demo-progress-fab">
2+
3+
<md-card class="demo-progress-card">
4+
<md-toolbar color="primary">Basic</md-toolbar>
5+
<md-card-content>
6+
<div class="demo-content">
7+
<button md-progress-fab color="accent">
8+
<i class="material-icons md-24">favorite</i>
9+
</button>
10+
11+
<button md-progress-fab
12+
color="primary"
13+
progressColor="warn"
14+
mode="determinate"
15+
[value]="fabProgressValue">
16+
17+
<i class="material-icons md-24">feedback</i>
18+
</button>
19+
</div>
20+
</md-card-content>
21+
</md-card>
22+
23+
<md-card class="demo-progress-card">
24+
<md-toolbar color="primary">Determinate</md-toolbar>
25+
<md-card-content>
26+
<div class="demo-content">
27+
28+
<button md-progress-fab
29+
class="demo-determinate-progress"
30+
[color]="determinateColor"
31+
progressColor="warn"
32+
mode="determinate"
33+
[value]="fabProgressValue"
34+
[class.hide-progress]="determinateHidden">
35+
36+
<i class="material-icons md-24">feedback</i>
37+
</button>
38+
</div>
39+
</md-card-content>
40+
</md-card>
41+
42+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
.demo-progress-fab {
2+
3+
.demo-progress-card {
4+
padding: 0;
5+
margin: 16px;
6+
7+
.demo-content {
8+
padding: 7px;
9+
10+
.demo-determinate-progress.hide-progress {
11+
.md-progress-wrap {
12+
md-progress-circle {
13+
transition-duration: 0.7s;
14+
transition-property: transform, opacity;
15+
transition-timing-function: ease-out;
16+
17+
transform: scale(0.8);
18+
opacity: 0;
19+
}
20+
}
21+
}
22+
23+
}
24+
}
25+
26+
}

0 commit comments

Comments
 (0)