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

Commit 8e5f85b

Browse files
authored
feat(chips): Add touch target (#2071)
closes #2063
1 parent ea2fe58 commit 8e5f85b

File tree

12 files changed

+130
-61
lines changed

12 files changed

+130
-61
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const routes: Routes = [
2121
},
2222
{
2323
path: 'chips-demo', loadChildren: () =>
24-
import('./components/chips-demo/chips.module').then(m => m.ChipsModule)
24+
import('./components/chips/module').then(m => m.ChipsModule)
2525
},
2626
{path: 'theme-docs', loadChildren: () => import('./components/theme-docs/theme.module').then(m => m.ThemeModule)},
2727
{

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

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

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

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,22 @@ <h4 mdcSubtitle2>Properties</h4>
1717
<tbody>
1818
<tr>
1919
<td>choice: boolean</td>
20-
<td>Indicates that the chips in the set are choice chips, which allow a single selection from a set of options.</td>
20+
<td>Indicates that the chips in the set are choice chips, which allow a
21+
single selection from a set of options.</td>
2122
</tr>
2223
<tr>
2324
<td>filter: boolean</td>
24-
<td>Indicates that the chips in the set are filter chips, which allow multiple selection from a set of options.</td>
25+
<td>Indicates that the chips in the set are filter chips, which allow
26+
multiple selection from a set of options.</td>
2527
</tr>
2628
<tr>
2729
<td>input: boolean</td>
28-
<td>Indicates that the chips in the set are input chips, which enable user input by converting text into chips.</td>
30+
<td>Indicates that the chips in the set are input chips, which enable
31+
user input by converting text into chips.</td>
32+
</tr>
33+
<tr>
34+
<td>touch: boolean</td>
35+
<td>Set the component touch target to 48 x 48 px.</td>
2936
</tr>
3037
</tbody>
3138
</table>
@@ -39,7 +46,8 @@ <h4 mdcSubtitle2>Methods</h4>
3946
</tr>
4047
<tr>
4148
<td>select(chipId: string): void</td>
42-
<td>Selects the chip with the given id. Deselects all other chips if the chip set is of the choice variant.</td>
49+
<td>Selects the chip with the given id. Deselects all other chips if the
50+
chip set is of the choice variant.</td>
4351
</tr>
4452
</tbody>
4553
</table>
@@ -49,7 +57,8 @@ <h4 mdcSubtitle2>Events</h4>
4957
<tbody>
5058
<tr>
5159
<td>interaction: MdcChipInteractionEvent</td>
52-
<td>Indicates when a chip is interacted with (via click/tap or Enter key)</td>
60+
<td>Indicates when a chip is interacted with (via click/tap or Enter
61+
key)</td>
5362
</tr>
5463
<tr>
5564
<td>change: MdcChipSetChange</td>
@@ -78,27 +87,32 @@ <h4 mdcSubtitle2>Properties</h4>
7887
<tbody>
7988
<tr>
8089
<td>choice: boolean</td>
81-
<td>Indicates that the chips in the set are choice chips, which allow a single selection from a set of options.</td>
90+
<td>Indicates that the chips in the set are choice chips, which allow a
91+
single selection from a set of options.</td>
8292
</tr>
8393
<tr>
8494
<td>filter: boolean</td>
85-
<td>Indicates that the chips in the set are filter chips, which allow multiple selection from a set of options.</td>
95+
<td>Indicates that the chips in the set are filter chips, which allow
96+
multiple selection from a set of options.</td>
8697
</tr>
8798
<tr>
8899
<td>input: boolean</td>
89-
<td>Indicates that the chips in the set are input chips, which enable user input by converting text into chips.</td>
100+
<td>Indicates that the chips in the set are input chips, which enable
101+
user input by converting text into chips.</td>
90102
</tr>
91103
<tr>
92104
<td>label: string</td>
93105
<td>Sets the text content of the chip.</td>
94106
</tr>
95107
<tr>
96108
<td>value: string | string[]</td>
97-
<td>The value of the chip. Defaults to the content inside <code>mdc-chip</code>.</td>
109+
<td>The value of the chip. Defaults to the content inside
110+
<code>mdc-chip</code>.</td>
98111
</tr>
99112
<tr>
100113
<td>removable: boolean</td>
101-
<td>Sets whether a trailing icon click should trigger exit/removal of the chip. (Default is true)</td>
114+
<td>Sets whether a trailing icon click should trigger exit/removal of
115+
the chip. (Default is true)</td>
102116
</tr>
103117
<tr>
104118
<td>disableRipple: boolean</td>
@@ -122,11 +136,13 @@ <h4 mdcSubtitle2>Events</h4>
122136
<tbody>
123137
<tr>
124138
<td>interactionEvent: MdcChipInteractionEvent</td>
125-
<td>Indicates the chip was interacted with (via click/tap or Enter key)</td>
139+
<td>Indicates the chip was interacted with (via click/tap or Enter key)
140+
</td>
126141
</tr>
127142
<tr>
128143
<td>selectionChange: MdcChipSelectionEvent</td>
129-
<td>Indicates the chip's selection state has changed (for choice/filter chips)</td>
144+
<td>Indicates the chip's selection state has changed (for choice/filter
145+
chips)</td>
130146
</tr>
131147
<tr>
132148
<td>removalEvent: MdcChipRemovalEvent</td>
@@ -138,7 +154,8 @@ <h4 mdcSubtitle2>Events</h4>
138154
</tr>
139155
<tr>
140156
<td>trailingIconInteraction: MdcChipInteractionEvent</td>
141-
<td>Indicates the chip's trailing icon was interacted with (via click/tap or Enter key)</td>
157+
<td>Indicates the chip's trailing icon was interacted with (via
158+
click/tap or Enter key)</td>
142159
</tr>
143160
</tbody>
144161
</table>

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export class Api {}
1212
export class Sass {}
1313

1414
@Component({template: '<component-viewer></component-viewer>'})
15-
export class ChipsDemo implements OnInit {
15+
export class Chips implements OnInit {
1616
@ViewChild(ComponentViewer, {static: true}) _componentViewer: ComponentViewer;
1717

1818
ngOnInit(): void {
@@ -304,4 +304,10 @@ formControl = new FormControl('steak-0', Validators.required);
304304
305305
@ViewChild('form') form: NgForm;`
306306
};
307+
308+
exampleAccessibility = {
309+
html: `<div class="mdc-touch-target-wrapper">
310+
<mdc-chip touch label="My Accessibility Chip"></mdc-chip>
311+
</div>`
312+
};
307313
}

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

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<div class="demo-content">
22
<div class="demo-layout__row">
3-
<button mdc-button (click)="simplechip.disableRipple = !simplechip.disableRipple">Disable
3+
<button mdc-button
4+
(click)="simplechip.disableRipple = !simplechip.disableRipple">Disable
45
Ripple: {{simplechip.disableRipple ? 'On' : 'Off'}}</button>
56
</div>
67
<mdc-chip-set>
@@ -129,7 +130,8 @@ <h3 class="demo-content__headline">Action Chips</h3>
129130

130131
<div class="demo-content">
131132
<h3 class="demo-content__headline">Choice with value</h3>
132-
<mdc-chip-set choice #chipSetValue (change)="onChipSetChange($event)" (interaction)="onChipInteraction($event)" [value]="demoChipValue">
133+
<mdc-chip-set choice #chipSetValue (change)="onChipSetChange($event)"
134+
(interaction)="onChipInteraction($event)" [value]="demoChipValue">
133135
<mdc-chip *ngFor="let food of foods" [value]="food.value"
134136
(selectionChange)="onChipSelection($event)">
135137
{{food.viewValue}}
@@ -242,4 +244,22 @@ <h3 class="demo-content__headline">Custom</h3>
242244
</mdc-chip-set>
243245
</div>
244246
<example-viewer [example]="exampleCustom"></example-viewer>
247+
</div>
248+
249+
<div class="demo-content">
250+
<h3 class="demo-content__headline">Accessibility</h3>
251+
<p>
252+
Material Design spec advises that touch targets should be at least 48 x 48
253+
px. To meet this requirement, add the `touch` property.
254+
</p>
255+
<p>
256+
Note that the outer mdc-touch-target-wrapper element is only necessary if
257+
you want to avoid potentially overlapping touch targets on adjacent elements
258+
(due to collapsing margins). </p>
259+
<div class="demo-layout__row">
260+
<div class="mdc-touch-target-wrapper">
261+
<mdc-chip touch label="My Accessibility Chip"></mdc-chip>
262+
</div>
263+
</div>
264+
<example-viewer [example]="exampleAccessibility"></example-viewer>
245265
</div>
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, Chips} from './chips';
5+
6+
export const ROUTE_DECLARATIONS = [
7+
Api,
8+
Examples,
9+
Sass,
10+
Chips
11+
];
12+
13+
const ROUTES: Routes = [
14+
{
15+
path: '', component: Chips,
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/chips/chip-directives.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,28 @@ import {
55
} from '@angular/core';
66

77
@Directive({
8-
selector: 'mdc-chip-text, [mdcChipText]',
8+
selector: 'mdc-chip-primary-action, [mdcChipPrimaryAction]',
99
host: {
1010
'[attr.role]': 'role',
1111
'[attr.tabindex]': 'tabIndex',
12-
'class': 'mdc-chip__text mdc-chip__action--primary'
12+
'class': 'mdc-chip__action--primary'
1313
}
1414
})
15-
export class MdcChipText {
15+
export class MdcChipPrimaryAction {
1616
@Input() role: string | null = 'button';
1717
@Input() tabIndex: number | null = null;
1818

19-
constructor(public elementRef: ElementRef<HTMLElement>) {}
19+
_root!: HTMLElement;
20+
21+
constructor(public elementRef: ElementRef<HTMLElement>) {
22+
this._root = this.elementRef.nativeElement;
23+
}
2024
}
25+
26+
@Directive({
27+
selector: 'mdc-chip-text, [mdcChipText]',
28+
host: {
29+
'class': 'mdc-chip__text'
30+
}
31+
})
32+
export class MdcChipText {}

packages/chips/chip.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import {
4444
MdcChipRemovalEvent,
4545
MdcChipSelectionEvent
4646
} from './types';
47-
import {MdcChipText} from './chip-directives';
47+
import {MdcChipPrimaryAction, MdcChipText} from './chip-directives';
4848

4949
import {
5050
MDCChipAdapter,
@@ -88,20 +88,21 @@ export class MdcChipCheckmark {
8888
'role': 'row',
8989
'class': 'mdc-chip',
9090
'[class.mdc-chip--selected]': 'selected',
91+
'[class.mdc-chip--touch]': 'touch',
9192
'(click)': '_handleInteraction($event)',
9293
'(keydown)': '_onKeydown($event)'
9394
},
9495
template: `
9596
<div class="mdc-chip__ripple"></div>
9697
<ng-content select="mdc-chip-icon[leading]"></ng-content>
9798
<mdc-chip-checkmark *ngIf="filter"></mdc-chip-checkmark>
98-
<span role="gridcell" *ngIf="label">
99-
<mdc-chip-text>{{label}}</mdc-chip-text>
100-
</span>
10199
<span role="gridcell">
102-
<ng-content></ng-content>
103-
</span>
104-
`,
100+
<mdc-chip-primary-action>
101+
<div class="mdc-chip__touch" *ngIf="touch"></div>
102+
<mdc-chip-text *ngIf="label">{{label}}</mdc-chip-text>
103+
<ng-content></ng-content>
104+
</mdc-chip-primary-action>
105+
</span>`,
105106
encapsulation: ViewEncapsulation.None,
106107
changeDetection: ChangeDetectionStrategy.OnPush,
107108
providers: [MdcRipple]
@@ -175,6 +176,15 @@ export class MdcChip extends MDCComponent<MDCChipFoundation> implements AfterVie
175176
}
176177
private _removable = true;
177178

179+
@Input()
180+
get touch(): boolean {
181+
return this._touch;
182+
}
183+
set touch(value: boolean) {
184+
this._touch = coerceBooleanProperty(value);
185+
}
186+
private _touch: boolean = false;
187+
178188
/** Whether the chip ripple is disabled. */
179189
@Input()
180190
get disableRipple(): boolean {
@@ -217,7 +227,8 @@ export class MdcChip extends MDCComponent<MDCChipFoundation> implements AfterVie
217227

218228
@ContentChild(MdcChipCheckmark, {static: false}) _checkmark?: MdcChipCheckmark;
219229
@ContentChildren(forwardRef(() => MdcChipIcon), {descendants: true}) _icons!: QueryList<MdcChipIcon>;
220-
@ViewChild(MdcChipText, {static: true}) _primaryAction!: ElementRef<HTMLElement>;
230+
@ViewChild(MdcChipPrimaryAction, {static: true}) _primaryAction!: MdcChipPrimaryAction;
231+
@ViewChild(MdcChipText, {static: true}) _chipText!: MdcChipText;
221232

222233
getDefaultFoundation() {
223234
const adapter: MDCChipAdapter = {
@@ -230,7 +241,7 @@ export class MdcChip extends MDCComponent<MDCChipFoundation> implements AfterVie
230241
this.leadingIcon?.elementRef?.nativeElement?.classList?.remove(className),
231242
eventTargetHasClass: (target: EventTarget | null, className: string) =>
232243
(target && (target as Element).classList) ? (target as Element).classList.contains(className) : false,
233-
focusPrimaryAction: () => this._primaryAction?.nativeElement?.focus(),
244+
focusPrimaryAction: () => this._primaryAction._root.focus(),
234245
focusTrailingAction: () => this.trailingIcon?.elementRef?.nativeElement?.focus(),
235246
notifyInteraction: () => this.interactionEvent.emit({
236247
chipId: this._id,
@@ -267,7 +278,7 @@ export class MdcChip extends MDCComponent<MDCChipFoundation> implements AfterVie
267278
this.trailingIcon?.elementRef?.nativeElement?.setAttribute(attr, value),
268279
hasLeadingIcon: () => !!this.leadingIcon,
269280
hasTrailingAction: () => !!this.trailingIcon,
270-
setPrimaryActionAttr: (attr: string, value: string) => this._elementRef.nativeElement.setAttribute(attr, value),
281+
setPrimaryActionAttr: (attr: string, value: string) => this._primaryAction._root.setAttribute(attr, value),
271282
getRootBoundingClientRect: () => this._root.getBoundingClientRect(),
272283
getCheckmarkBoundingClientRect: () =>
273284
this._checkmark?.elementRef?.nativeElement?.getBoundingClientRect() ?? null,

0 commit comments

Comments
 (0)