Skip to content

Commit da5febc

Browse files
tdawgykara
authored andcommitted
feat(icon): added color attribute to md-icon for icon theming (#1896)
1 parent e3830b4 commit da5febc

File tree

5 files changed

+78
-11
lines changed

5 files changed

+78
-11
lines changed

src/demo-app/icon/icon-demo.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@
2626
<md-icon>home</md-icon>
2727
</p>
2828

29+
<p>
30+
Using a theme:
31+
<md-icon color="primary">home</md-icon>
32+
<md-icon color="accent">home</md-icon>
33+
<md-icon color="warn">home</md-icon>
34+
</p>
35+
2936
<p>
3037
Custom icon font and CSS:
3138
<md-icon fontSet="fontawesome" fontIcon="fa-birthday-cake"></md-icon>

src/demo-app/icon/icon-demo.scss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
.demo-icon md-icon {
2-
color: purple;
3-
}
4-
51
.demo-icon md-icon.green {
62
color: green;
73
}

src/lib/icon/_icon-theme.scss

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
1-
@import '../core/theming/palette';
21
@import '../core/theming/theming';
32

43

54
// Include this empty mixin for consistency with the other components.
6-
@mixin md-icon-theme($theme) { }
5+
@mixin md-icon-theme($theme) {
6+
$primary: map-get($theme, primary);
7+
$accent: map-get($theme, accent);
8+
$warn: map-get($theme, warn);
9+
$background: map-get($theme, background);
10+
$foreground: map-get($theme, foreground);
11+
12+
md-icon {
13+
&.md-primary {
14+
color: md-color($primary);
15+
}
16+
17+
&.md-accent {
18+
color: md-color($accent);
19+
}
20+
21+
&.md-warn {
22+
color: md-color($warn);
23+
}
24+
}
25+
}

src/lib/icon/icon.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ describe('MdIcon', () => {
4141
TestBed.configureTestingModule({
4242
imports: [MdIconModule.forRoot()],
4343
declarations: [
44+
MdIconColorTestApp,
4445
MdIconLigatureTestApp,
4546
MdIconLigatureWithAriaBindingTestApp,
4647
MdIconCustomFontCssTestApp,
@@ -72,6 +73,17 @@ describe('MdIcon', () => {
7273
});
7374
}));
7475

76+
it('should apply class based on color attribute', () => {
77+
let fixture = TestBed.createComponent(MdIconColorTestApp);
78+
79+
const testComponent = fixture.debugElement.componentInstance;
80+
const mdIconElement = fixture.debugElement.nativeElement.querySelector('md-icon');
81+
testComponent.iconName = 'home';
82+
testComponent.iconColor = 'primary';
83+
fixture.detectChanges();
84+
expect(sortedClassNames(mdIconElement)).toEqual(['material-icons', 'md-primary']);
85+
});
86+
7587
describe('Ligature icons', () => {
7688
it('should add material-icons class by default', () => {
7789
let fixture = TestBed.createComponent(MdIconLigatureTestApp);
@@ -413,6 +425,16 @@ class MdIconLigatureTestApp {
413425
iconName = '';
414426
}
415427

428+
@Component({
429+
selector: 'test-app',
430+
template: `<md-icon [color]="iconColor">{{iconName}}</md-icon>`,
431+
})
432+
class MdIconColorTestApp {
433+
ariaLabel: string = null;
434+
iconName = '';
435+
iconColor = 'primary';
436+
}
437+
416438
@Component({
417439
selector: 'test-app',
418440
template: `<md-icon [aria-label]="ariaLabel" [alt]="altText">{{iconName}}</md-icon>`,

src/lib/icon/icon.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ export class MdIconInvalidNameError extends MdError {
7070
changeDetection: ChangeDetectionStrategy.OnPush,
7171
})
7272
export class MdIcon implements OnChanges, OnInit, AfterViewChecked {
73+
private _color: string;
74+
7375
@Input() svgSrc: string;
7476
@Input() svgIcon: string;
7577
@Input() fontSet: string;
@@ -78,14 +80,35 @@ export class MdIcon implements OnChanges, OnInit, AfterViewChecked {
7880

7981
@Input('aria-label') hostAriaLabel: string = '';
8082

83+
@Input()
84+
get color(): string {
85+
return this._color;
86+
}
87+
88+
set color(value: string) {
89+
this._updateColor(value);
90+
}
91+
8192
private _previousFontSetClass: string;
8293
private _previousFontIconClass: string;
8394

8495
constructor(
85-
private _element: ElementRef,
96+
private _elementRef: ElementRef,
8697
private _renderer: Renderer,
8798
private _mdIconRegistry: MdIconRegistry) { }
8899

100+
_updateColor(newColor: string) {
101+
this._setElementColor(this._color, false);
102+
this._setElementColor(newColor, true);
103+
this._color = newColor;
104+
}
105+
106+
_setElementColor(color: string, isAdd: boolean) {
107+
if (color != null && color != '') {
108+
this._renderer.setElementClass(this._elementRef.nativeElement, `md-${color}`, isAdd);
109+
}
110+
}
111+
89112
/**
90113
* Splits an svgIcon binding value into its icon set and icon name components.
91114
* Returns a 2-element array of [(icon set), (icon name)].
@@ -156,7 +179,7 @@ export class MdIcon implements OnChanges, OnInit, AfterViewChecked {
156179
private _updateAriaLabel() {
157180
const ariaLabel = this._getAriaLabel();
158181
if (ariaLabel) {
159-
this._renderer.setElementAttribute(this._element.nativeElement, 'aria-label', ariaLabel);
182+
this._renderer.setElementAttribute(this._elementRef.nativeElement, 'aria-label', ariaLabel);
160183
}
161184
}
162185

@@ -174,7 +197,7 @@ export class MdIcon implements OnChanges, OnInit, AfterViewChecked {
174197
}
175198
// The "content" of an SVG icon is not a useful label.
176199
if (this._usingFontIcon()) {
177-
const text = this._element.nativeElement.textContent;
200+
const text = this._elementRef.nativeElement.textContent;
178201
if (text) {
179202
return text;
180203
}
@@ -188,7 +211,7 @@ export class MdIcon implements OnChanges, OnInit, AfterViewChecked {
188211
}
189212

190213
private _setSvgElement(svg: SVGElement) {
191-
const layoutElement = this._element.nativeElement;
214+
const layoutElement = this._elementRef.nativeElement;
192215
// Remove existing child nodes and add the new SVG element.
193216
// We would use renderer.detachView(Array.from(layoutElement.childNodes)) here,
194217
// but it fails in IE11: https://github.com/angular/angular/issues/6327
@@ -200,7 +223,7 @@ export class MdIcon implements OnChanges, OnInit, AfterViewChecked {
200223
if (!this._usingFontIcon()) {
201224
return;
202225
}
203-
const elem = this._element.nativeElement;
226+
const elem = this._elementRef.nativeElement;
204227
const fontSetClass = this.fontSet ?
205228
this._mdIconRegistry.classNameForFontAlias(this.fontSet) :
206229
this._mdIconRegistry.getDefaultFontSetClass();

0 commit comments

Comments
 (0)