From 818ac4d236c330d934814ccd5c659ac413527dea Mon Sep 17 00:00:00 2001 From: Joey Perrott Date: Fri, 16 Feb 2018 07:42:04 -0800 Subject: [PATCH] feat(icon): add input for inline styling of icons --- src/demo-app/icon/icon-demo.html | 4 ++++ src/demo-app/tabs/tabs-demo.scss | 4 ++++ src/lib/icon/icon.scss | 7 +++++++ src/lib/icon/icon.spec.ts | 24 +++++++++++++++++++++--- src/lib/icon/icon.ts | 15 +++++++++++++++ 5 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/demo-app/icon/icon-demo.html b/src/demo-app/icon/icon-demo.html index 6067745806b6..63fd9b905cd3 100644 --- a/src/demo-app/icon/icon-demo.html +++ b/src/demo-app/icon/icon-demo.html @@ -32,4 +32,8 @@ Custom icon font and CSS:

+ +

+ Inline styling favorite icons appear as + the same directions_carsize as text around them.

diff --git a/src/demo-app/tabs/tabs-demo.scss b/src/demo-app/tabs/tabs-demo.scss index fd69322feeb4..806951c75025 100644 --- a/src/demo-app/tabs/tabs-demo.scss +++ b/src/demo-app/tabs/tabs-demo.scss @@ -16,6 +16,10 @@ } } +.mat-tab-label.mat-tab-label.mat-tab-label { + min-width: 0; +} + .demo-tab-group { flex-grow: 1; } diff --git a/src/lib/icon/icon.scss b/src/lib/icon/icon.scss index 21b38398017b..9738966f8956 100644 --- a/src/lib/icon/icon.scss +++ b/src/lib/icon/icon.scss @@ -10,6 +10,13 @@ $mat-icon-size: 24px !default; fill: currentColor; height: $mat-icon-size; width: $mat-icon-size; + + &.mat-icon-inline { + font-size: inherit; + height: inherit; + line-height: inherit; + width: inherit; + } } .mat-form-field:not(.mat-form-field-appearance-legacy) { diff --git a/src/lib/icon/icon.spec.ts b/src/lib/icon/icon.spec.ts index 2c0da31be028..842524abfa16 100644 --- a/src/lib/icon/icon.spec.ts +++ b/src/lib/icon/icon.spec.ts @@ -50,6 +50,7 @@ describe('MatIcon', () => { IconFromSvgName, IconWithAriaHiddenFalse, IconWithBindingAndNgIf, + InlineIcon, ] }); @@ -82,14 +83,26 @@ describe('MatIcon', () => { const fixture = TestBed.createComponent(IconWithLigature); const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon'); expect(iconElement.getAttribute('aria-hidden')) - .toBe('true', 'Expected the mat-icon element has aria-hidden="true" by default'); + .toBe('true', 'Expected the mat-icon element has aria-hidden="true" by default'); }); it('should not override a user-provided aria-hidden attribute', () => { const fixture = TestBed.createComponent(IconWithAriaHiddenFalse); const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon'); expect(iconElement.getAttribute('aria-hidden')) - .toBe('false', 'Expected the mat-icon element has the user-provided aria-hidden value'); + .toBe('false', 'Expected the mat-icon element has the user-provided aria-hidden value'); + }); + + it('should apply inline styling', () => { + const fixture = TestBed.createComponent(InlineIcon); + const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon'); + expect(iconElement.classList.contains('mat-icon-inline')) + .toBeFalsy('Expected the mat-icon element to not include the inline styling class'); + + fixture.debugElement.componentInstance.inline = true; + fixture.detectChanges(); + expect(iconElement.classList.contains('mat-icon-inline')) + .toBeTruthy('Expected the mat-icon element to include the inline styling class'); }); describe('Ligature icons', () => { @@ -500,10 +513,15 @@ class IconFromSvgName { } @Component({template: 'face'}) -class IconWithAriaHiddenFalse { } +class IconWithAriaHiddenFalse {} @Component({template: `{{iconName}}`}) class IconWithBindingAndNgIf { iconName = 'fluffy'; showIcon = true; } + +@Component({template: `{{iconName}}`}) +class InlineIcon { + inline = false; +} diff --git a/src/lib/icon/icon.ts b/src/lib/icon/icon.ts index 215496e61045..0b839eb4a267 100644 --- a/src/lib/icon/icon.ts +++ b/src/lib/icon/icon.ts @@ -19,6 +19,7 @@ import { ViewEncapsulation, } from '@angular/core'; import {CanColor, mixinColor} from '@angular/material/core'; +import {coerceBooleanProperty} from '@angular/cdk/coercion'; import {MatIconRegistry} from './icon-registry'; @@ -67,12 +68,26 @@ export const _MatIconMixinBase = mixinColor(MatIconBase); host: { 'role': 'img', 'class': 'mat-icon', + '[class.mat-icon-inline]': 'inline', }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, }) export class MatIcon extends _MatIconMixinBase implements OnChanges, OnInit, CanColor { + /** + * Whether the icon should be inlined, automatically sizing the icon to match the font size of + * the element the icon is contained in. + */ + @Input() + get inline(): boolean { + return this._inline; + } + set inline(inline: boolean) { + this._inline = coerceBooleanProperty(inline); + } + private _inline: boolean = false; + /** Name of the icon in the SVG icon set. */ @Input() svgIcon: string;