Skip to content
This repository was archived by the owner on Oct 7, 2020. It is now read-only.

Commit 80cc2c6

Browse files
authored
feat(fab): Add touch target (#2069)
closes #2064
1 parent 0544839 commit 80cc2c6

File tree

10 files changed

+116
-50
lines changed

10 files changed

+116
-50
lines changed

demos/src/app/app-routing.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const routes: Routes = [
3434
path: 'elevation-demo', loadChildren: () =>
3535
import('./components/elevation-demo/elevation.module').then(m => m.ElevationModule)
3636
},
37-
{path: 'fab-demo', loadChildren: () => import('./components/fab-demo/fab.module').then(m => m.FabModule)},
37+
{path: 'fab-demo', loadChildren: () => import('./components/fab/module').then(m => m.FabModule)},
3838
{
3939
path: 'form-field-demo', loadChildren: () =>
4040
import('./components/form-field-demo/form-field.module').then(m => m.FormFieldModule)

demos/src/app/components/fab-demo/routing.module.ts

Lines changed: 0 additions & 29 deletions
This file was deleted.

demos/src/app/components/fab-demo/api.html renamed to demos/src/app/components/fab/api.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ <h4 mdcSubtitle2>Properties</h4>
3030
</tr>
3131
<tr>
3232
<td>fluid: boolean</td>
33-
<td>Makes the Extended FAB fluid to container, such as screen width or the layout grid.</td>
33+
<td>Makes the Extended FAB fluid to container, such as screen width or
34+
the layout grid.</td>
3435
</tr>
3536
<tr>
3637
<td>label: string</td>
@@ -46,6 +47,11 @@ <h4 mdcSubtitle2>Properties</h4>
4647
<td>icon: string</td>
4748
<td>Optional. Apply a Material Icon.</td>
4849
</tr>
50+
<tr>
51+
<td>touch: boolean</td>
52+
<td>Set the mini fab touch target to 48 x 48 px. Only applies if FAB is set
53+
to mini as well.</td>
54+
</tr>
4955
</tbody>
5056
</table>
5157

demos/src/app/components/fab-demo/examples.html renamed to demos/src/app/components/fab/examples.html

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<div class="demo-content">
22
<h3 class="demo-content__headline">FAB</h3>
33
<div class="demo-layout__row">
4-
<button mdc-button (click)="demofab.mini = !demofab.mini">Mini: {{demofab.mini ? 'On' : 'Off'}}</button>
4+
<button mdc-button (click)="demofab.mini = !demofab.mini">Mini:
5+
{{demofab.mini ? 'On' : 'Off'}}</button>
56
</div>
67
<button mdc-fab #demofab>
78
<mdc-icon>edit</mdc-icon>
@@ -12,7 +13,8 @@ <h3 class="demo-content__headline">FAB</h3>
1213
<div class="demo-content">
1314
<h3 class="demo-content__headline">Using Font Awesome</h3>
1415
<div class="demo-layout__row">
15-
<button mdc-button (click)="demoFA.mini = !demoFA.mini">Mini: {{demoFA.mini ? 'On' : 'Off'}}</button>
16+
<button mdc-button (click)="demoFA.mini = !demoFA.mini">Mini:
17+
{{demoFA.mini ? 'On' : 'Off'}}</button>
1618
</div>
1719
<button mdc-fab #demoFA>
1820
<mdc-icon fontSet="fa" fontIcon="fa-keyboard-o"></mdc-icon>
@@ -32,7 +34,8 @@ <h3 class="demo-content__headline">Mini</h3>
3234
<h3 class="demo-content__headline">Extended FAB</h3>
3335
<div class="demo-layout__row">
3436
<div class="demo-container">
35-
<button mdc-fab extended icon="add_shopping_cart" label="Add to cart" class="blackFab"></button>
37+
<button mdc-fab extended icon="add_shopping_cart" label="Add to cart"
38+
class="blackFab"></button>
3639
</div>
3740
<div class="demo-container">
3841
<button mdc-fab extended label="Create" class="blackFab"></button>
@@ -63,7 +66,8 @@ <h3 class="demo-content__headline">Extended FAB</h3>
6366
<div class="demo-content">
6467
<h3 class="demo-content__headline">Extended FAB (Fluid)</h3>
6568
<div class="demo-layout__row">
66-
<button mdc-button (click)="extended.fluid = !extended.fluid">Fluid: {{extended.fluid ? 'On' : 'Off'}}</button>
69+
<button mdc-button (click)="extended.fluid = !extended.fluid">Fluid:
70+
{{extended.fluid ? 'On' : 'Off'}}</button>
6771
</div>
6872
<div class="demo-layout__row">
6973
<button #extended mdc-fab extended fluid label="Add to cart">
@@ -77,7 +81,8 @@ <h3 class="demo-content__headline">Extended FAB (Fluid)</h3>
7781
<h3 class="demo-content__headline">Exit/Entry Animation</h3>
7882
<div class="demo-layout__row">
7983
<button mdc-button (click)="exited.toggleExited()">Toggle Exited</button>
80-
<button mdc-button (click)="exited.mini = !exited.mini">Mini: {{exited.mini ? 'On' : 'Off'}}</button>
84+
<button mdc-button (click)="exited.mini = !exited.mini">Mini:
85+
{{exited.mini ? 'On' : 'Off'}}</button>
8186
</div>
8287
<button mdc-fab #exited (click)="exited.toggleExited()">
8388
<mdc-icon>save</mdc-icon>
@@ -136,11 +141,35 @@ <h3 class="demo-content__headline">Custom</h3>
136141
<div class="demo-content">
137142
<h3 class="demo-content__headline">Absolute Position</h3>
138143
<div class="demo-layout__row">
139-
<button mdc-button (click)="demoPosition.position = 'bottomLeft'">Bottom Left</button>
140-
<button mdc-button (click)="demoPosition.position = 'bottomRight'">Bottom Right</button>
144+
<button mdc-button (click)="demoPosition.position = 'bottomLeft'">Bottom
145+
Left</button>
146+
<button mdc-button (click)="demoPosition.position = 'bottomRight'">Bottom
147+
Right</button>
141148
<button mdc-button (click)="demoPosition.mini = !demoPosition.mini">Mini: {{demoPosition.mini ? 'On' :
142149
'Off'}}</button>
143150
</div>
144-
<button #demoPosition mdc-fab position='bottomRight' icon="add" class="demo-fab-position-zindex"></button>
151+
<button #demoPosition mdc-fab position='bottomRight' icon="add"
152+
class="demo-fab-position-zindex"></button>
145153
<example-viewer [example]="examplePosition"></example-viewer>
154+
</div>
155+
156+
<div class="demo-content">
157+
<h3 class="demo-content__headline">Accessibility</h3>
158+
<p>
159+
Material Design spec advises that touch targets should be at least 48x48px.
160+
While the FAB is 48x48px by default, the mini FAB is 40x40px. To meet this
161+
requirement, add the `touch` property.
162+
</p>
163+
<p>
164+
Note that the outer mdc-touch-target-wrapper element is only necessary if
165+
you want to avoid potentially overlapping touch targets on adjacent elements
166+
(due to collapsing margins). </p>
167+
<div class="demo-layout__row">
168+
<div class="mdc-touch-target-wrapper">
169+
<button mdc-fab mini touch>
170+
<mdc-icon>edit</mdc-icon>
171+
</button>
172+
</div>
173+
</div>
174+
<example-viewer [example]="exampleAccessibility"></example-viewer>
146175
</div>

demos/src/app/components/fab-demo/fab-demo.ts renamed to demos/src/app/components/fab/fab.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export class Api {}
99
export class Sass {}
1010

1111
@Component({template: '<component-viewer></component-viewer>'})
12-
export class FabDemo implements OnInit {
12+
export class Fab implements OnInit {
1313
@ViewChild(ComponentViewer, {static: true}) _componentViewer: ComponentViewer;
1414

1515
ngOnInit(): void {
@@ -115,4 +115,12 @@ export class Examples {
115115
examplePosition = {
116116
html: `<button mdc-fab position='bottomRight' icon="add"></button>`
117117
};
118+
119+
exampleAccessibility = {
120+
html: `<div class="mdc-touch-target-wrapper">
121+
<button mdc-fab mini touch>
122+
<mdc-icon>edit</mdc-icon>
123+
</button>
124+
</div>`
125+
};
118126
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {NgModule} from '@angular/core';
2+
import {Routes, RouterModule} from '@angular/router';
3+
4+
import {Api, Examples, Sass, Fab} from './fab';
5+
6+
export const ROUTE_DECLARATIONS = [
7+
Api,
8+
Examples,
9+
Sass,
10+
Fab
11+
];
12+
13+
const ROUTES: Routes = [
14+
{
15+
path: '', component: Fab,
16+
children: [
17+
{path: '', redirectTo: 'api'},
18+
{path: 'api', component: Api},
19+
{path: 'sass', component: Sass},
20+
{path: 'examples', component: Examples}
21+
]
22+
}
23+
];
24+
25+
@NgModule({
26+
imports: [RouterModule.forChild(ROUTES)],
27+
exports: [RouterModule]
28+
})
29+
export class RoutingModule {}

packages/fab/fab.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,15 @@ export class MdcFabLabel {}
3030
'[class.mdc-fab--mini]': 'mini',
3131
'[class.mdc-fab--exited]': 'exited',
3232
'[class.mdc-fab--extended]': 'extended',
33-
'[class.ngx-mdc-fab-extended--fluid]': 'fluid'
33+
'[class.ngx-mdc-fab-extended--fluid]': 'fluid',
34+
'[class.mdc-fab--touch]': 'touch && mini',
3435
},
3536
template: `
3637
<div class="mdc-fab__ripple"></div>
3738
<ng-content></ng-content>
3839
<mdc-icon class="mdc-fab__icon" *ngIf="icon">{{icon}}</mdc-icon>
3940
<span class="mdc-fab__label" *ngIf="label">{{label}}</span>
40-
`,
41+
<div class="mdc-fab__touch" *ngIf="touch && mini"></div>`,
4142
providers: [MdcRipple],
4243
encapsulation: ViewEncapsulation.None,
4344
changeDetection: ChangeDetectionStrategy.OnPush
@@ -52,6 +53,15 @@ export class MdcFab implements AfterContentInit, OnDestroy {
5253
}
5354
private _mini: boolean = false;
5455

56+
@Input()
57+
get touch(): boolean {
58+
return this._touch;
59+
}
60+
set touch(value: boolean) {
61+
this._touch = coerceBooleanProperty(value);
62+
}
63+
private _touch: boolean = false;
64+
5565
@Input()
5666
get exited(): boolean {
5767
return this._exited;

test/fab/fab.test.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { Component, DebugElement } from '@angular/core';
2-
import { fakeAsync, ComponentFixture, TestBed } from '@angular/core/testing';
3-
import { By } from '@angular/platform-browser';
1+
import {Component, DebugElement} from '@angular/core';
2+
import {fakeAsync, ComponentFixture, TestBed} from '@angular/core/testing';
3+
import {By} from '@angular/platform-browser';
44

5-
import { MdcFab, MdcFabModule, MdcIconModule } from '@angular-mdc/web';
5+
import {MdcFab, MdcFabModule, MdcIconModule} from '@angular-mdc/web';
66

77
describe('MdcFab', () => {
88
let fixture: ComponentFixture<any>;
@@ -66,6 +66,19 @@ describe('MdcFab', () => {
6666
expect(buttonDebugElement.nativeElement.classList.contains('mdc-fab--exited')).toBe(true);
6767
});
6868

69+
it('#should not apply class `touch` to normal fab', () => {
70+
testComponent.touch = true;
71+
fixture.detectChanges();
72+
expect(buttonDebugElement.nativeElement.classList.contains('mdc-fab--touch')).toBe(false);
73+
});
74+
75+
it('#should apply class `touch` to mini fab', () => {
76+
testComponent.touch = true;
77+
testComponent.mini = true;
78+
fixture.detectChanges();
79+
expect(buttonDebugElement.nativeElement.classList.contains('mdc-fab--touch')).toBe(true);
80+
});
81+
6982
it('#should apply class `exited` after toggleExited(true)', () => {
7083
buttonInstance.toggleExited(true);
7184
fixture.detectChanges();
@@ -166,6 +179,7 @@ describe('MdcFab', () => {
166179
[position]="myPosition"
167180
[extended]="extended"
168181
[fluid]="fluid"
182+
[touch]="touch"
169183
[mini]="mini">
170184
<mdc-icon>search</mdc-icon>
171185
</button>
@@ -175,6 +189,7 @@ class SimpleButton {
175189
mini: boolean = false;
176190
extended: boolean;
177191
fluid: boolean;
192+
touch: boolean = false;
178193
isExited: boolean = false;
179194
clickCount: number = 0;
180195
myPosition: string = 'bottomLeft';
@@ -185,8 +200,6 @@ class SimpleButton {
185200
}
186201

187202
@Component({
188-
template: `
189-
<button mdc-fab [icon]="favorite"></button>
190-
`,
203+
template: `<button mdc-fab [icon]="favorite"></button>`,
191204
})
192-
class SimpleFabButton { }
205+
class SimpleFabButton {}

0 commit comments

Comments
 (0)