Skip to content

Commit 95799c1

Browse files
committed
feat(icon): add input for inline styling of icons
1 parent 73bc948 commit 95799c1

File tree

5 files changed

+51
-3
lines changed

5 files changed

+51
-3
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,8 @@
3232
Custom icon font and CSS:
3333
<mat-icon fontSet="fontawesome" fontIcon="fa-birthday-cake"></mat-icon>
3434
</p>
35+
36+
<p>
37+
Inline styling <mat-icon inline="true">favorite</mat-icon> icons appear as
38+
the same <mat-icon inline="true">directions_car</mat-icon>size as text around them.</p>
3539
</div>

src/demo-app/tabs/tabs-demo.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
}
1717
}
1818

19+
.mat-tab-label.mat-tab-label.mat-tab-label {
20+
min-width: 0;
21+
}
22+
1923
.demo-tab-group {
2024
flex-grow: 1;
2125
}

src/lib/icon/icon.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ $mat-icon-size: 24px !default;
1010
fill: currentColor;
1111
height: $mat-icon-size;
1212
width: $mat-icon-size;
13+
14+
&.mat-icon-inline {
15+
font-size: inherit;
16+
height: inherit;
17+
line-height: inherit;
18+
width: inherit;
19+
}
1320
}
1421

1522
.mat-form-field:not(.mat-form-field-appearance-legacy) {

src/lib/icon/icon.spec.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ describe('MatIcon', () => {
5050
IconFromSvgName,
5151
IconWithAriaHiddenFalse,
5252
IconWithBindingAndNgIf,
53+
InlineIcon,
5354
]
5455
});
5556

@@ -82,14 +83,26 @@ describe('MatIcon', () => {
8283
const fixture = TestBed.createComponent(IconWithLigature);
8384
const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon');
8485
expect(iconElement.getAttribute('aria-hidden'))
85-
.toBe('true', 'Expected the mat-icon element has aria-hidden="true" by default');
86+
.toBe('true', 'Expected the mat-icon element has aria-hidden="true" by default');
8687
});
8788

8889
it('should not override a user-provided aria-hidden attribute', () => {
8990
const fixture = TestBed.createComponent(IconWithAriaHiddenFalse);
9091
const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon');
9192
expect(iconElement.getAttribute('aria-hidden'))
92-
.toBe('false', 'Expected the mat-icon element has the user-provided aria-hidden value');
93+
.toBe('false', 'Expected the mat-icon element has the user-provided aria-hidden value');
94+
});
95+
96+
it('should apply inline styling', () => {
97+
const fixture = TestBed.createComponent(InlineIcon);
98+
const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon');
99+
expect(iconElement.classList.contains('mat-icon-inline'))
100+
.toBeFalsy('Expected the mat-icon element to not include the inline styling class');
101+
102+
fixture.debugElement.componentInstance.inline = true;
103+
fixture.detectChanges();
104+
expect(iconElement.classList.contains('mat-icon-inline'))
105+
.toBeTruthy('Expected the mat-icon element to include the inline styling class');
93106
});
94107

95108
describe('Ligature icons', () => {
@@ -500,10 +513,15 @@ class IconFromSvgName {
500513
}
501514

502515
@Component({template: '<mat-icon aria-hidden="false">face</mat-icon>'})
503-
class IconWithAriaHiddenFalse { }
516+
class IconWithAriaHiddenFalse {}
504517

505518
@Component({template: `<mat-icon [svgIcon]="iconName" *ngIf="showIcon">{{iconName}}</mat-icon>`})
506519
class IconWithBindingAndNgIf {
507520
iconName = 'fluffy';
508521
showIcon = true;
509522
}
523+
524+
@Component({template: `<mat-icon [inline]="inline">{{iconName}}</mat-icon>`})
525+
class InlineIcon {
526+
inline = false;
527+
}

src/lib/icon/icon.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
ViewEncapsulation,
2020
} from '@angular/core';
2121
import {CanColor, mixinColor} from '@angular/material/core';
22+
import {coerceBooleanProperty} from '@angular/cdk/coercion';
2223
import {MatIconRegistry} from './icon-registry';
2324

2425

@@ -67,13 +68,27 @@ export const _MatIconMixinBase = mixinColor(MatIconBase);
6768
host: {
6869
'role': 'img',
6970
'class': 'mat-icon',
71+
'[class.mat-icon-inline]': 'inline',
7072
},
7173
encapsulation: ViewEncapsulation.None,
7274
preserveWhitespaces: false,
7375
changeDetection: ChangeDetectionStrategy.OnPush,
7476
})
7577
export class MatIcon extends _MatIconMixinBase implements OnChanges, OnInit, CanColor {
7678

79+
/**
80+
* Whether the icon should be inlined, automatically sizing the icon to match the font size of
81+
* the element the icon is contained in.
82+
*/
83+
@Input()
84+
get inline(): boolean {
85+
return this._inline;
86+
}
87+
set inline(inline: boolean) {
88+
this._inline = coerceBooleanProperty(inline);
89+
}
90+
private _inline: boolean = false;
91+
7792
/** Name of the icon in the SVG icon set. */
7893
@Input() svgIcon: string;
7994

0 commit comments

Comments
 (0)