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

Commit 84451c1

Browse files
Ruben Oliveira Chiavonetrimox
authored andcommitted
feat(button): Add trailing icon support (#1676)
Closes #1602
1 parent 2db621b commit 84451c1

File tree

6 files changed

+156
-8
lines changed

6 files changed

+156
-8
lines changed

demos/src/app/components/button-demo/api.html

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ <h4 mdcSubtitle2>Properties</h4>
4444
<td>disabled: boolean</td>
4545
<td>Disables the button.</td>
4646
</tr>
47+
<tr>
48+
<td>label: string</td>
49+
<td>Indicates the element containing the button's text label.</td>
50+
</tr>
4751
</tbody>
4852
</table>
4953

@@ -56,4 +60,14 @@ <h4 mdcSubtitle2>Methods</h4>
5660
</tr>
5761
</tbody>
5862
</table>
59-
</div>
63+
</div>
64+
65+
<div class="docs-api">
66+
<h3 mdcHeadline6>MdcButtonLabel</h3>
67+
<p>
68+
Selector:
69+
<span class="docs-api-class-selector-name">mdc-button-label</span>
70+
<span class="docs-api-class-selector-name">[mdcButtonLabel]</span>
71+
</p>
72+
Exported as: <span class="docs-api-class-selector-name">mdcButtonLabel</span>
73+
</div>

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,20 @@ export class Examples {
112112
@include mdc-button-shape-radius(8px);
113113
}`
114114
};
115+
116+
trailingIconExample = {
117+
html: `<button mdc-button>
118+
<span mdcButtonLabel>Trailing Icon</span>
119+
<mdc-icon>favorite</mdc-icon>
120+
</button>
121+
122+
<button mdc-button secondary raised>
123+
<mdc-button-label>Trailing Icon</mdc-button-label>
124+
<mdc-icon>favorite</mdc-icon>
125+
</button>
126+
127+
<button mdc-button outlined label="Trailing Icon">
128+
<mdc-icon>favorite</mdc-icon>
129+
</button>`
130+
};
115131
}

demos/src/app/components/button-demo/examples.html

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,34 @@ <h3 class="demo-content__headline">Shaped</h3>
105105
</div>
106106
</div>
107107
<example-viewer [example]="shapedExample"></example-viewer>
108-
</div>
108+
</div>
109+
110+
<div class="demo-content">
111+
<h3 class="demo-content__headline">Trailing icon</h3>
112+
<p>
113+
Certain icons make more sense to appear after the button's text label rather than before. This can be accomplished by putting the icon markup <i>after</i> the mdcButtonLabel element.
114+
</p>
115+
<p>
116+
NOTE: The mdc-button-label element is required in order for the trailing icon to be styled appropriately.
117+
</p>
118+
<div class="demo-layout__row">
119+
<div class="demo-container">
120+
<button mdc-button>
121+
<span mdcButtonLabel>Trailing Icon</span>
122+
<mdc-icon>favorite</mdc-icon>
123+
</button>
124+
</div>
125+
<div class="demo-container">
126+
<button mdc-button secondary raised>
127+
<mdc-button-label>Trailing Icon</mdc-button-label>
128+
<mdc-icon>favorite</mdc-icon>
129+
</button>
130+
</div>
131+
<div class="demo-container">
132+
<button mdc-button outlined label="Trailing Icon">
133+
<mdc-icon>favorite</mdc-icon>
134+
</button>
135+
</div>
136+
</div>
137+
<example-viewer [example]="trailingIconExample"></example-viewer>
138+
</div>

packages/button/button-module.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { NgModule } from '@angular/core';
2+
import { CommonModule } from '@angular/common';
23

3-
import { MdcButton } from './button';
4+
import { MdcButton, MdcButtonLabel } from './button';
45

56
@NgModule({
6-
exports: [MdcButton],
7-
declarations: [MdcButton]
7+
imports: [
8+
CommonModule
9+
],
10+
exports: [MdcButton, MdcButtonLabel],
11+
declarations: [MdcButton, MdcButtonLabel]
812
})
913
export class MdcButtonModule { }

packages/button/button.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
ChangeDetectionStrategy,
33
Component,
44
ContentChild,
5+
Directive,
56
ElementRef,
67
Input,
78
OnDestroy,
@@ -12,6 +13,15 @@ import { toBoolean } from '@angular-mdc/web/common';
1213
import { MdcRipple } from '@angular-mdc/web/ripple';
1314
import { MdcIcon } from '@angular-mdc/web/icon';
1415

16+
@Directive({
17+
selector: 'mdc-button-label, [mdcButtonLabel]',
18+
exportAs: 'mdcButtonLabel',
19+
host: {
20+
'class': 'mdc-button__label'
21+
}
22+
})
23+
export class MdcButtonLabel { }
24+
1525
@Component({
1626
moduleId: module.id,
1727
exportAs: 'mdcButton',
@@ -27,7 +37,10 @@ import { MdcIcon } from '@angular-mdc/web/icon';
2737
'[class.mdc-button--outlined]': 'outlined',
2838
'(click)': 'onClick($event)'
2939
},
30-
template: '<ng-content></ng-content>',
40+
template: `
41+
<mdc-button-label *ngIf="label">{{label}}</mdc-button-label>
42+
<ng-content></ng-content>
43+
`,
3144
providers: [MdcRipple],
3245
encapsulation: ViewEncapsulation.None,
3346
changeDetection: ChangeDetectionStrategy.OnPush
@@ -84,6 +97,8 @@ export class MdcButton implements OnInit, OnDestroy {
8497

8598
@ContentChild(MdcIcon) _icon!: MdcIcon;
8699

100+
@Input() label?: string;
101+
87102
constructor(
88103
public elementRef: ElementRef<HTMLElement>,
89104
private _ripple: MdcRipple) { }

test/button/button.test.ts

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Component, DebugElement } from '@angular/core';
22
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
33
import { By } from '@angular/platform-browser';
44

5-
import { MdcButton, MdcIcon, MdcIconModule, MdcButtonModule } from '@angular-mdc/web';
5+
import { MdcButton, MdcButtonLabel, MdcIcon, MdcIconModule, MdcButtonModule } from '@angular-mdc/web';
66

77
describe('MdcButton', () => {
88
let fixture: ComponentFixture<any>;
@@ -13,7 +13,10 @@ describe('MdcButton', () => {
1313
declarations: [
1414
SimpleButton,
1515
HrefButton,
16-
SimpleButtonWithIcon
16+
SimpleButtonWithIcon,
17+
SimpleButtonWithTrailingIcon,
18+
SimpleButtonWithTrailingIconLabelElement,
19+
SimpleButtonWithTrailingIconLabelAttr
1720
]
1821
});
1922
TestBed.compileComponents();
@@ -102,6 +105,11 @@ describe('MdcButton', () => {
102105
fixture.detectChanges();
103106
expect(buttonNativeElement.disabled).toBeTruthy('Expected button to be disabled');
104107
});
108+
109+
it('#should NOT have mdc-button-label by default', () => {
110+
expect(fixture.debugElement.query(By.directive(MdcButtonLabel)))
111+
.toBe(null, 'Expected buttons not to have mdc-button-label by default');
112+
});
105113
});
106114

107115
// Anchor button tests
@@ -173,6 +181,38 @@ describe('MdcButton', () => {
173181
expect(buttonDebugElement.nativeElement.classList.contains('mdc-button__icon')).toBe(true);
174182
});
175183
});
184+
185+
// Trailing icon button tests
186+
describe('mdc-button with trailing icon', () => {
187+
let buttonLabelDebugElement: DebugElement;
188+
189+
it('#should have class mdc-button__label when using MdcButtonLabel attr', () => {
190+
fixture = TestBed.createComponent(SimpleButtonWithTrailingIcon);
191+
fixture.detectChanges();
192+
193+
buttonLabelDebugElement = fixture.debugElement.query(By.directive(MdcButtonLabel));
194+
195+
expect(buttonLabelDebugElement.nativeElement.classList.contains('mdc-button__label')).toBe(true);
196+
});
197+
198+
it('#should have class mdc-button__label when using MdcButtonLabel element', () => {
199+
fixture = TestBed.createComponent(SimpleButtonWithTrailingIconLabelElement);
200+
fixture.detectChanges();
201+
202+
buttonLabelDebugElement = fixture.debugElement.query(By.directive(MdcButtonLabel));
203+
204+
expect(buttonLabelDebugElement.nativeElement.classList.contains('mdc-button__label')).toBe(true);
205+
});
206+
207+
it('#should have class mdc-button__label when using MdcButton label attribute', () => {
208+
fixture = TestBed.createComponent(SimpleButtonWithTrailingIconLabelAttr);
209+
fixture.detectChanges();
210+
211+
buttonLabelDebugElement = fixture.debugElement.query(By.directive(MdcButtonLabel));
212+
213+
expect(buttonLabelDebugElement.nativeElement.classList.contains('mdc-button__label')).toBe(true);
214+
});
215+
});
176216
});
177217

178218
/** Simple component for testing. */
@@ -225,3 +265,32 @@ class HrefButton {
225265
`,
226266
})
227267
class SimpleButtonWithIcon { }
268+
269+
@Component({
270+
template: `
271+
<button mdc-button>
272+
<span mdcButtonLabel>Search</span>
273+
<mdc-icon>search</mdc-icon>
274+
</button>
275+
`,
276+
})
277+
class SimpleButtonWithTrailingIcon { }
278+
279+
@Component({
280+
template: `
281+
<button mdc-button>
282+
<mdc-button-label>Search</mdc-button-label>
283+
<mdc-icon>search</mdc-icon>
284+
</button>
285+
`,
286+
})
287+
class SimpleButtonWithTrailingIconLabelElement { }
288+
289+
@Component({
290+
template: `
291+
<button mdc-button label="Search">
292+
<mdc-icon>search</mdc-icon>
293+
</button>
294+
`,
295+
})
296+
class SimpleButtonWithTrailingIconLabelAttr { }

0 commit comments

Comments
 (0)