Skip to content

Commit

Permalink
feat(): add progress-fab component.
Browse files Browse the repository at this point in the history
  • Loading branch information
devversion committed Apr 14, 2016
1 parent 03111c4 commit f16d70d
Show file tree
Hide file tree
Showing 14 changed files with 352 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/components/progress-bar/progress-bar.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@import "../../core/style/variables";
@import "../../core/style/default-theme";
@import "variables";
@import "default-theme";

$md-progress-bar-height: 5px !default;
$md-progress-bar-full-animation-duration: 2s !default;
Expand Down
4 changes: 2 additions & 2 deletions src/components/progress-circle/progress-circle.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@import "../../core/style/variables";
@import "variables";

@import "../../core/style/default-theme";
@import "default-theme";

/* Animation Durations */
$md-progress-circle-duration : 5.25s !default;
Expand Down
2 changes: 1 addition & 1 deletion src/components/progress-circle/progress-circle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class MdProgressCircle {
// total circumference.

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

Expand Down
25 changes: 25 additions & 0 deletions src/components/progress-fab/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# MdProgressFab
`MdProgressFab` is a normal FAB button surrounded with a `progress-circle`.

### Screenshots
![Preview](https://cloud.githubusercontent.com/assets/4987015/14406410/eaf20a54-fea6-11e5-8a24-4f751df7e80a.png)

## `[md-progress-fab]`
### Bound Properties

| Name | Type | Description |
| --- | --- | --- |
| `color` | `"primary" | "accent" | "warn"` | The color palette for the FAB button |
| `value` | `number` | Value for the `progress-circle`.<br/> Necessary when using the `determinate` mode. |
| `mode` | `"determinate" | "indeterminate"` | Mode for the `progress-circle`.<br/> |
| `progressColor` | `"primary" | "accent" | "warn"` | Color for the `progress-circle`.<br/> |


### Examples
A basic progress-fab will have the markup:
```html
<button md-progress-fab color="accent">
<i class="material-icons md-24">favorite</i>
</button>
```
It will use by default a `indeterminate` progress circle.
13 changes: 13 additions & 0 deletions src/components/progress-fab/progress-fab.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<span class="md-button-wrapper">
<ng-content></ng-content>

<div class="md-progress-wrap">
<md-progress-circle
[mode]="progressMode"
[value]="progressValue"
[attr.color]="progressColor">
</md-progress-circle>
</div>
</span>


34 changes: 34 additions & 0 deletions src/components/progress-fab/progress-fab.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@import "../button/button-base";

$md-fab-progress-stroke: 6px;

// Subtract 1px to avoid the ugly space between FAB button and progress circle.
$md-fab-progress-rectangle: ($md-fab-size + $md-fab-padding + $md-fab-progress-stroke / 2) - 1px;

:host {
@include md-fab($md-fab-size, $md-fab-padding);

margin: $md-fab-progress-stroke;

.md-progress-wrap {
position: absolute;
top: 50%;
left: 50%;

transform: translate3d(-50%, -50%, 0);

md-progress-circle {
width: $md-fab-progress-rectangle;
height: $md-fab-progress-rectangle;

svg {
overflow: visible;

circle {
stroke-width: $md-fab-progress-stroke;
}
}
}
}

}
123 changes: 123 additions & 0 deletions src/components/progress-fab/progress-fab.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import {
it,
describe,
expect,
beforeEach,
inject,
TestComponentBuilder
} from 'angular2/testing';
import {Component} from 'angular2/core';
import {By} from 'angular2/platform/browser';
import {MdProgressFab} from './progress-fab';
import {MdProgressCircle} from '../progress-circle/progress-circle';

export function main() {
describe('MdProgressFab', () => {
let builder: TestComponentBuilder;

beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
builder = tcb;
}));

it('should correctly apply the color attribute on the progress circle', (done: () => void) => {
return builder
.createAsync(TestApp)
.then((fixture) => {
let testComponent = fixture.debugElement.componentInstance;
let progressDebugElement = fixture.debugElement.query(By.css('md-progress-circle'));

testComponent.progressColor = 'primary';
fixture.detectChanges();

expect(progressDebugElement.nativeElement.getAttribute('color')).toBe('primary');

testComponent.progressColor = 'accent';
fixture.detectChanges();

expect(progressDebugElement.nativeElement.getAttribute('color')).toBe('accent');

done();
});
});

it('should correctly apply the mode on the progress circle', (done: () => void) => {
return builder
.createAsync(TestApp)
.then((fixture) => {
let testComponent = fixture.debugElement.componentInstance;
let progressComponent: MdProgressCircle = fixture.debugElement
.query(By.css('md-progress-circle')).componentInstance;

testComponent.progressMode = 'determinate';
fixture.detectChanges();

expect(progressComponent.mode).toBe('determinate');

testComponent.progressColor = 'indeterminate';
fixture.detectChanges();

expect(progressComponent.mode).toBe('determinate');

done();
});
});

it('should correctly apply the value on the progress circle', (done: () => void) => {
return builder
.createAsync(TestApp)
.then((fixture) => {
let testComponent = fixture.debugElement.componentInstance;
let progressComponent: MdProgressCircle = fixture.debugElement
.query(By.css('md-progress-circle')).componentInstance;

testComponent.progressValue = 50;
fixture.detectChanges();

expect(progressComponent._value).toBe(50);

testComponent.progressValue = 70;
fixture.detectChanges();

expect(progressComponent._value).toBe(70);

done();
});
});

it('should correctly apply the color on the button', (done: () => void) => {
return builder
.createAsync(TestApp)
.then((fixture) => {
let testComponent = fixture.debugElement.componentInstance;
let buttonDebugElement = fixture.debugElement.query(By.css('button'));

testComponent.buttonColor = 'primary';
fixture.detectChanges();

expect(buttonDebugElement.nativeElement.classList.contains('md-primary')).toBe(true);

testComponent.buttonColor = 'accent';
fixture.detectChanges();
expect(buttonDebugElement.nativeElement.classList.contains('md-accent')).toBe(true);

done();
});
});

});
}

@Component({
selector: 'test-app',
template: `
<button md-progress-fab [color]="buttonColor" [progressColor]="progressColor"
[mode]="progressMode" [value]="progressValue">
</button>`,
directives: [MdProgressFab]
})
class TestApp {
buttonColor: string = 'primary';
progressColor: string = 'accent';
progressMode: string = 'indeterminate';
progressValue: number = 0;
}
35 changes: 35 additions & 0 deletions src/components/progress-fab/progress-fab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
Component,
ChangeDetectionStrategy,
Renderer,
ElementRef,
Input
} from 'angular2/core';
import {MdProgressCircle} from '../progress-circle/progress-circle';
import {MdButton} from '../button/button';

@Component({
selector: '[md-progress-fab]:not(a)',
templateUrl: './components/progress-fab/progress-fab.html',
styleUrls: ['./components/progress-fab/progress-fab.css'],
directives: [MdProgressCircle],
inputs: ['color'],
host: {
'[class.md-button-focus]': 'isKeyboardFocused',
'(mousedown)': 'setMousedown()',
'(focus)': 'setKeyboardFocus()',
'(blur)': 'removeKeyboardFocus()'
},
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MdProgressFab extends MdButton {

@Input('mode') progressMode: string = 'indeterminate';
@Input('value') progressValue: number;
@Input('progressColor') progressColor: string;

constructor(elementRef: ElementRef, renderer: Renderer) {
super(elementRef, renderer);
}

}
13 changes: 12 additions & 1 deletion src/demo-app/button/button-demo.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import {Component} from 'angular2/core';
import {MdButton, MdAnchor} from '../../components/button/button';
import {MdProgressFab} from '../../components/progress-fab/progress-fab';

@Component({
selector: 'button-demo',
templateUrl: 'demo-app/button/button-demo.html',
styleUrls: ['demo-app/button/button-demo.css'],
directives: [MdButton, MdAnchor]
directives: [MdButton, MdAnchor, MdProgressFab]
})
export class ButtonDemo {
isDisabled: boolean = false;
clickCounter: number = 0;
fabProgressValue: number = 0;

constructor() {

setInterval(() => this.increaseFabProgress(), 200);
}

increaseFabProgress() {
this.fabProgressValue += 7;
}
}
1 change: 1 addition & 0 deletions src/demo-app/demo-app.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ <h1>Angular Material2 Demos</h1>
<li><a [routerLink]="['CardDemo']">Card demo</a></li>
<li><a [routerLink]="['ProgressCircleDemo']">Progress Circle demo</a></li>
<li><a [routerLink]="['ProgressBarDemo']">Progress Bar demo</a></li>
<li><a [routerLink]="['ProgressFabDemo']">Progress Fab demo</a></li>
<li><a [routerLink]="['PortalDemo']">Portal demo</a></li>
<li><a [routerLink]="['OverlayDemo']">Overlay demo</a></li>
<li><a [routerLink]="['CheckboxDemo']">Checkbox demo</a></li>
Expand Down
4 changes: 3 additions & 1 deletion src/demo-app/demo-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {ListDemo} from './list/list-demo';
import {InputDemo} from './input/input-demo';
import {LiveAnnouncerDemo} from './live-announcer/live-announcer-demo';
import {GesturesDemo} from './gestures/gestures-demo';
import {ProgressFabDemo} from './progress-fab/progress-fab-demo';

@Component({
selector: 'home',
Expand Down Expand Up @@ -46,6 +47,7 @@ export class Home {}
new Route({path: '/toolbar', name: 'ToolbarDemo', component: ToolbarDemo}),
new Route({path: '/list', name: 'ListDemo', component: ListDemo}),
new Route({path: '/live-announcer', name: 'LiveAnnouncerDemo', component: LiveAnnouncerDemo}),
new Route({path: '/gestures', name: 'GesturesDemo', component: GesturesDemo})
new Route({path: '/gestures', name: 'GesturesDemo', component: GesturesDemo}),
new Route({path: '/progress-fab', name: 'ProgressFabDemo', component: ProgressFabDemo}),
])
export class DemoApp { }
42 changes: 42 additions & 0 deletions src/demo-app/progress-fab/progress-fab-demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<div class="demo-progress-fab">

<md-card class="demo-progress-card">
<md-toolbar color="primary">Basic</md-toolbar>
<md-card-content>
<div class="demo-content">
<button md-progress-fab color="accent">
<i class="material-icons md-24">favorite</i>
</button>

<button md-progress-fab
color="primary"
progressColor="warn"
mode="determinate"
[value]="fabProgressValue">

<i class="material-icons md-24">feedback</i>
</button>
</div>
</md-card-content>
</md-card>

<md-card class="demo-progress-card">
<md-toolbar color="primary">Determinate</md-toolbar>
<md-card-content>
<div class="demo-content">

<button md-progress-fab
class="demo-determinate-progress"
[color]="determinateColor"
progressColor="warn"
mode="determinate"
[value]="fabProgressValue"
[class.hide-progress]="determinateHidden">

<i class="material-icons md-24">feedback</i>
</button>
</div>
</md-card-content>
</md-card>

</div>
26 changes: 26 additions & 0 deletions src/demo-app/progress-fab/progress-fab-demo.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.demo-progress-fab {

.demo-progress-card {
padding: 0;
margin: 16px;

.demo-content {
padding: 7px;

.demo-determinate-progress.hide-progress {
.md-progress-wrap {
md-progress-circle {
transition-duration: 0.7s;
transition-property: transform, opacity;
transition-timing-function: ease-out;

transform: scale(0.8);
opacity: 0;
}
}
}

}
}

}
Loading

0 comments on commit f16d70d

Please sign in to comment.