From c98d217dfef4ba79f4272cec3df201d153321181 Mon Sep 17 00:00:00 2001 From: Austin Date: Tue, 13 Feb 2018 09:55:21 -0600 Subject: [PATCH] feat(badge): add badge component (#7483) --- .github/CODEOWNERS | 2 + src/demo-app/badge/badge-demo.html | 90 ++++++++++ src/demo-app/badge/badge-demo.scss | 3 + src/demo-app/badge/badge-demo.ts | 20 +++ src/demo-app/demo-app/demo-app.ts | 1 + src/demo-app/demo-app/demo-module.ts | 2 + src/demo-app/demo-app/routes.ts | 2 + src/demo-app/demo-material-module.ts | 2 + src/demo-app/system-config.ts | 1 + src/lib/badge/_badge-theme.scss | 167 +++++++++++++++++++ src/lib/badge/badge-module.ts | 27 +++ src/lib/badge/badge.md | 53 ++++++ src/lib/badge/badge.spec.ts | 132 +++++++++++++++ src/lib/badge/badge.ts | 167 +++++++++++++++++++ src/lib/badge/index.ts | 9 + src/lib/badge/public-api.ts | 10 ++ src/lib/badge/tsconfig-build.json | 14 ++ src/lib/core/theming/_all-theme.scss | 2 + src/lib/core/typography/_all-typography.scss | 1 + src/lib/public-api.ts | 1 + test/karma-test-shim.js | 1 + 21 files changed, 707 insertions(+) create mode 100644 src/demo-app/badge/badge-demo.html create mode 100644 src/demo-app/badge/badge-demo.scss create mode 100644 src/demo-app/badge/badge-demo.ts create mode 100644 src/lib/badge/_badge-theme.scss create mode 100644 src/lib/badge/badge-module.ts create mode 100644 src/lib/badge/badge.md create mode 100644 src/lib/badge/badge.spec.ts create mode 100644 src/lib/badge/badge.ts create mode 100644 src/lib/badge/index.ts create mode 100644 src/lib/badge/public-api.ts create mode 100644 src/lib/badge/tsconfig-build.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a26cc2170a51..e526353343ec 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -32,6 +32,7 @@ /src/lib/tabs/** @andrewseguin /src/lib/toolbar/** @devversion /src/lib/tooltip/** @andrewseguin +/src/lib/badge/** @amcdnl # Angular Material core /src/lib/core/* @jelbourn @@ -129,6 +130,7 @@ /src/demo-app/toolbar/** @devversion /src/demo-app/tooltip/** @andrewseguin /src/demo-app/typography/** @crisbeto +/src/demo-app/badge/** @amcdnl # E2E app /e2e/* @jelbourn diff --git a/src/demo-app/badge/badge-demo.html b/src/demo-app/badge/badge-demo.html new file mode 100644 index 000000000000..eeb119c4f249 --- /dev/null +++ b/src/demo-app/badge/badge-demo.html @@ -0,0 +1,90 @@ +
+ +
+

Text

+ + Hello + + + + Hello + + + + Hello + + + + Hello + + + + Hello + + + + Aria + + + + Hidden + + + + +
+ +
+

Buttons

+ + + + + + + + + +
+ +
+

Icons

+ + home + + + + home + + + + home + + + + home + +
+ +
+

Size

+ + home + + + home + + +
+ +
\ No newline at end of file diff --git a/src/demo-app/badge/badge-demo.scss b/src/demo-app/badge/badge-demo.scss new file mode 100644 index 000000000000..bea7811f28cd --- /dev/null +++ b/src/demo-app/badge/badge-demo.scss @@ -0,0 +1,3 @@ +.badge-examples { + margin-bottom: 25px; +} diff --git a/src/demo-app/badge/badge-demo.ts b/src/demo-app/badge/badge-demo.ts new file mode 100644 index 000000000000..120cfca9bd82 --- /dev/null +++ b/src/demo-app/badge/badge-demo.ts @@ -0,0 +1,20 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Component} from '@angular/core'; + +@Component({ + moduleId: module.id, + selector: 'badge-demo', + templateUrl: 'badge-demo.html', + styleUrls: ['badge-demo.css'], +}) +export class BadgeDemo { + visible = true; + badgeContent = '0'; +} diff --git a/src/demo-app/demo-app/demo-app.ts b/src/demo-app/demo-app/demo-app.ts index 26e5a0f0e4b8..3eb21c9ec0ce 100644 --- a/src/demo-app/demo-app/demo-app.ts +++ b/src/demo-app/demo-app/demo-app.ts @@ -51,6 +51,7 @@ export class DemoApp { dark = false; navItems = [ {name: 'Autocomplete', route: '/autocomplete'}, + {name: 'Badge', route: '/badge'}, {name: 'Bottom sheet', route: '/bottom-sheet'}, {name: 'Button Toggle', route: '/button-toggle'}, {name: 'Button', route: '/button'}, diff --git a/src/demo-app/demo-app/demo-module.ts b/src/demo-app/demo-app/demo-module.ts index 1adf751c966c..e43ba75b3204 100644 --- a/src/demo-app/demo-app/demo-module.ts +++ b/src/demo-app/demo-app/demo-module.ts @@ -61,6 +61,7 @@ import {TypographyDemo} from '../typography/typography-demo'; import {DemoApp, Home} from './demo-app'; import {DEMO_APP_ROUTES} from './routes'; import {TableDemoModule} from '../table/table-demo-module'; +import {BadgeDemo} from 'badge/badge-demo'; @NgModule({ imports: [ @@ -78,6 +79,7 @@ import {TableDemoModule} from '../table/table-demo-module'; BaselineDemo, ButtonDemo, ButtonToggleDemo, + BadgeDemo, CardDemo, CheckboxDemo, ChipsDemo, diff --git a/src/demo-app/demo-app/routes.ts b/src/demo-app/demo-app/routes.ts index 865634f7eeb4..f818c06e4506 100644 --- a/src/demo-app/demo-app/routes.ts +++ b/src/demo-app/demo-app/routes.ts @@ -51,11 +51,13 @@ import {TypographyDemo} from '../typography/typography-demo'; import {DemoApp, Home} from './demo-app'; import {TableDemoPage} from '../table/table-demo-page'; import {TABLE_DEMO_ROUTES} from '../table/routes'; +import {BadgeDemo} from 'badge/badge-demo'; export const DEMO_APP_ROUTES: Routes = [ {path: '', component: DemoApp, children: [ {path: '', component: Home}, {path: 'autocomplete', component: AutocompleteDemo}, + {path: 'badge', component: BadgeDemo}, {path: 'bottom-sheet', component: BottomSheetDemo}, {path: 'baseline', component: BaselineDemo}, {path: 'button', component: ButtonDemo}, diff --git a/src/demo-app/demo-material-module.ts b/src/demo-app/demo-material-module.ts index eec0b7e6cc21..cec18c8cb6a1 100644 --- a/src/demo-app/demo-material-module.ts +++ b/src/demo-app/demo-material-module.ts @@ -17,6 +17,7 @@ import {CdkTableModule} from '@angular/cdk/table'; import {NgModule} from '@angular/core'; import { MatAutocompleteModule, + MatBadgeModule, MatBottomSheetModule, MatButtonModule, MatButtonToggleModule, @@ -58,6 +59,7 @@ import { @NgModule({ exports: [ MatAutocompleteModule, + MatBadgeModule, MatBottomSheetModule, MatButtonModule, MatButtonToggleModule, diff --git a/src/demo-app/system-config.ts b/src/demo-app/system-config.ts index 4f45b0820945..51dfa2a6c8ec 100644 --- a/src/demo-app/system-config.ts +++ b/src/demo-app/system-config.ts @@ -91,6 +91,7 @@ System.config({ '@angular/material/tabs': 'dist/packages/material/tabs/index.js', '@angular/material/toolbar': 'dist/packages/material/toolbar/index.js', '@angular/material/tooltip': 'dist/packages/material/tooltip/index.js', + '@angular/material/badge': 'dist/packages/material/badge/index.js', }, packages: { // Thirdparty barrels. diff --git a/src/lib/badge/_badge-theme.scss b/src/lib/badge/_badge-theme.scss new file mode 100644 index 000000000000..9ea47f1cc12c --- /dev/null +++ b/src/lib/badge/_badge-theme.scss @@ -0,0 +1,167 @@ +// This contains all of the styles for the badge +// rather than just the color/theme because of +// no style sheet support for directives. +@import '../core/theming/palette'; +@import '../core/theming/theming'; +@import '../core/typography/typography-utils'; + +$mat-badge-font-size: 12px; +$mat-badge-font-weight: 600; +$mat-badge-default-size: 22px !default; +$mat-badge-small-size: $mat-badge-default-size - 6; +$mat-badge-large-size: $mat-badge-default-size + 6; + +// Mixin for building offset given different sizes +@mixin _mat-badge-size($size) { + .mat-badge-content { + width: $size; + height: $size; + line-height: $size; + } + + &.mat-badge-above { + .mat-badge-content { + top: -$size / 2; + } + } + + &.mat-badge-below { + .mat-badge-content { + bottom: -$size / 2; + } + } + + &.mat-badge-before { + margin-left: $size; + + &[dir='rtl'] { + margin-left: 0; + margin-right: $size; + } + + .mat-badge-content { + left: -$size; + } + } + + &.mat-badge-after { + margin-right: $size; + + &[dir='rtl'] { + margin-right: 0; + margin-left: $size; + } + + .mat-badge-content { + right: -$size; + } + } + + &.mat-badge-overlap { + &.mat-badge-before { + margin-left: $size / 2; + + &[dir='rtl'] { + margin-left: 0; + margin-right: $size / 2; + } + + .mat-badge-content { + left: -$size / 2; + } + } + + &.mat-badge-after { + margin-right: $size / 2; + + &[dir='rtl'] { + margin-right: 0; + margin-left: $size; + } + + .mat-badge-content { + right: -$size / 2; + } + } + } +} + +@mixin mat-badge-theme($theme) { + $accent: map-get($theme, accent); + $warn: map-get($theme, warn); + $primary: map-get($theme, primary); + + .mat-badge-content { + color: mat-color($primary, default-contrast); + background: mat-color($primary); + } + + &.mat-badge-accent { + .mat-badge-content { + background: mat-color($accent); + color: mat-color($accent, default-contrast); + } + } + + &.mat-badge-warn { + .mat-badge-content { + color: mat-color($warn, default-contrast); + background: mat-color($warn); + } + } +} + +@mixin mat-badge-typography($config) { + .mat-badge-content { + font-weight: $mat-badge-font-weight; + font-size: $mat-badge-font-size; + font-family: mat-font-family($config); + } + + .mat-badge-small .mat-badge-content { + font-size: $mat-badge-font-size / 2; + } + + .mat-badge-large .mat-badge-content { + font-size: $mat-badge-font-size * 2; + } +} + +.mat-badge { + position: relative; +} + +.mat-badge-hidden { + .mat-badge-content { + display: none; + } +} + +.mat-badge-content { + position: absolute; + text-align: center; + display: inline-block; + border-radius: 50%; + transition: all 0.2 ease-in-out; + transform: scale(0.6); + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + pointer-events: none; +} + +// The active class is added after the element is added +// so it can animate scale to default +.mat-badge-content.mat-badge-active { + transform: scale(1); +} + +.mat-badge-small { + @include _mat-badge-size($mat-badge-small-size); +} +.mat-badge-medium { + @include _mat-badge-size($mat-badge-default-size); +} +.mat-badge-large { + @include _mat-badge-size($mat-badge-large-size); +} diff --git a/src/lib/badge/badge-module.ts b/src/lib/badge/badge-module.ts new file mode 100644 index 000000000000..d324e2d8441a --- /dev/null +++ b/src/lib/badge/badge-module.ts @@ -0,0 +1,27 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {NgModule} from '@angular/core'; +import {MatCommonModule} from '@angular/material/core'; +import {A11yModule} from '@angular/cdk/a11y'; +import {MatBadge} from './badge'; + + +@NgModule({ + imports: [ + MatCommonModule, + A11yModule, + ], + exports: [ + MatBadge, + ], + declarations: [ + MatBadge, + ], +}) +export class MatBadgeModule {} diff --git a/src/lib/badge/badge.md b/src/lib/badge/badge.md new file mode 100644 index 000000000000..9a2e2a5b01c6 --- /dev/null +++ b/src/lib/badge/badge.md @@ -0,0 +1,53 @@ +Badges are small status descriptors for UI elements. A badge consists of a small circle, +typically containing a number or other short set of characters, that appears in proximity to another object. + +### Badge position +By default, the badge will be placed `above after`. The direction can be changed by defining +the attribute `matBadgePosition` follow by `above|below` and `before|after`. + +```html +home +``` + +The overlap of the badge in relation to its inner contents can also be defined +using the `matBadgeOverlap` tag. Typically, you want the badge to overlap an icon and not +a text phrase. By default it will overlap. + +```html +

+ Email +

+``` + +### Badge sizing +The badge has 3 sizes: `small`, `medium` and `large`. By default, the badge is set to `medium`. +You can change the size by adding `matBadgeSize` to the host element. + +```html +

+ Email +

+``` + +### Badge visibility +The badge visibility can be toggled programmatically by defining `matBadgeHidden`. + +```html +

+ Email +

+``` + +### Theming +Badges can be colored in terms of the current theme using the `matBadgeColor` property to set the +background color to `primary`, `accent`, or `warn`. + +```html + + home + +``` + +### Accessibility +Badges should be given a meaningful description via `matBadgeDescription`. This description will be +applied, via `aria-describedby` to the element decorated by `matBadge`. \ No newline at end of file diff --git a/src/lib/badge/badge.spec.ts b/src/lib/badge/badge.spec.ts new file mode 100644 index 000000000000..8ad7572804af --- /dev/null +++ b/src/lib/badge/badge.spec.ts @@ -0,0 +1,132 @@ +import {ComponentFixture, TestBed, async} from '@angular/core/testing'; +import {Component, DebugElement} from '@angular/core'; +import {By} from '@angular/platform-browser'; +import {MatBadge, MatBadgeModule} from './index'; +import {ThemePalette} from '@angular/material/core'; + +describe('MatBadge', () => { + let fixture: ComponentFixture; + let testComponent: BadgeWithTextContent; + let badgeNativeElement; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [MatBadgeModule], + declarations: [BadgeWithTextContent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(BadgeWithTextContent); + testComponent = fixture.debugElement.componentInstance; + fixture.detectChanges(); + }); + + describe('MatBadge Text', () => { + let badgeDebugElement: DebugElement; + + beforeEach(() => { + badgeDebugElement = fixture.debugElement.query(By.directive(MatBadge)); + badgeNativeElement = badgeDebugElement.nativeElement; + fixture.detectChanges(); + }); + + it('should update the badge based on attribute', () => { + let badgeContentDebugElement = badgeNativeElement.querySelector('.mat-badge-content'); + + expect(badgeContentDebugElement.textContent).toContain('1'); + + testComponent.badgeContent = '22'; + fixture.detectChanges(); + + badgeContentDebugElement = badgeNativeElement.querySelector('.mat-badge-content'); + expect(badgeContentDebugElement.textContent).toContain('22'); + }); + + it('should apply class based on color attribute', () => { + testComponent.badgeColor = 'primary'; + fixture.detectChanges(); + expect(badgeNativeElement.classList.contains('mat-badge-primary')).toBe(true); + + testComponent.badgeColor = 'accent'; + fixture.detectChanges(); + expect(badgeNativeElement.classList.contains('mat-badge-accent')).toBe(true); + + testComponent.badgeColor = 'warn'; + fixture.detectChanges(); + expect(badgeNativeElement.classList.contains('mat-badge-warn')).toBe(true); + + testComponent.badgeColor = undefined; + fixture.detectChanges(); + + expect(badgeNativeElement.classList).not.toContain('mat-badge-accent'); + }); + + it('should update the badge position on direction change', () => { + expect(badgeNativeElement.classList.contains('mat-badge-above')).toBe(true); + expect(badgeNativeElement.classList.contains('mat-badge-after')).toBe(true); + + testComponent.badgeDirection = 'below before'; + fixture.detectChanges(); + + expect(badgeNativeElement.classList.contains('mat-badge-below')).toBe(true); + expect(badgeNativeElement.classList.contains('mat-badge-before')).toBe(true); + }); + + it('should change visibility to hidden', () => { + expect(badgeNativeElement.classList.contains('mat-badge-hidden')).toBe(false); + + testComponent.badgeHidden = true; + fixture.detectChanges(); + + expect(badgeNativeElement.classList.contains('mat-badge-hidden')).toBe(true); + }); + + it('should change badge sizes', () => { + expect(badgeNativeElement.classList.contains('mat-badge-medium')).toBe(true); + + testComponent.badgeSize = 'small'; + fixture.detectChanges(); + + expect(badgeNativeElement.classList.contains('mat-badge-small')).toBe(true); + + testComponent.badgeSize = 'large'; + fixture.detectChanges(); + + expect(badgeNativeElement.classList.contains('mat-badge-large')).toBe(true); + }); + + it('should change badge overlap', () => { + expect(badgeNativeElement.classList.contains('mat-badge-overlap')).toBe(false); + + testComponent.badgeOverlap = true; + fixture.detectChanges(); + + expect(badgeNativeElement.classList.contains('mat-badge-overlap')).toBe(true); + }); + }); + +}); + +/** Test component that contains a MatBadge. */ +@Component({ + selector: 'test-app', + template: ` + + home + + ` +}) +class BadgeWithTextContent { + badgeColor: ThemePalette; + badgeContent = '1'; + badgeDirection = 'above after'; + badgeHidden = false; + badgeSize = 'medium'; + badgeOverlap = false; +} diff --git a/src/lib/badge/badge.ts b/src/lib/badge/badge.ts new file mode 100644 index 000000000000..9b44702e8bc8 --- /dev/null +++ b/src/lib/badge/badge.ts @@ -0,0 +1,167 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Directive, Input, ElementRef, Inject, Optional, NgZone} from '@angular/core'; +import {coerceBooleanProperty} from '@angular/cdk/coercion'; +import {ThemePalette} from '@angular/material/core'; +import {AriaDescriber} from '@angular/cdk/a11y'; +import {DOCUMENT} from '@angular/common'; + +let nextId = 0; + +export type MatBadgePosition = 'above after' | 'above before' | 'below before' | 'below after'; +export type MatBadgeSize = 'small' | 'medium' | 'large'; + +/** Directive to display a text badge. */ +@Directive({ + selector: '[matBadge]', + host: { + 'class': 'mat-badge', + '[class.mat-badge-overlap]': '_overlap', + '[class.mat-badge-above]': 'isAbove()', + '[class.mat-badge-below]': '!isAbove()', + '[class.mat-badge-before]': '!isAfter()', + '[class.mat-badge-after]': 'isAfter()', + '[class.mat-badge-small]': 'size === "small"', + '[class.mat-badge-medium]': 'size === "medium"', + '[class.mat-badge-large]': 'size === "large"', + '[class.mat-badge-hidden]': 'hidden', + }, +}) +export class MatBadge { + + /** The color of the badge. Can be `primary`, `accent`, or `warn`. */ + @Input('matBadgeColor') + get color(): ThemePalette { return this._color; } + set color(value: ThemePalette) { + this._setColor(value); + this._color = value; + } + private _color: ThemePalette = 'primary'; + + /** Whether the badge should overlap its contents or not */ + @Input('matBadgeOverlap') + get overlap(): boolean { return this._overlap; } + set overlap(val: boolean) { + this._overlap = coerceBooleanProperty(val); + } + private _overlap: boolean = true; + + /** + * Position the badge should reside. + * Accepts any combination of 'above'|'below' and 'before'|'after' + */ + @Input('matBadgePosition') position: MatBadgePosition = 'above after'; + + /** The content for the badge */ + @Input('matBadge') + get content(): string { return this._content; } + set content(val: string) { + this._content = val; + this._updateTextContent(); + } + private _content: string; + + /** Message used to describe the decorated element via aria-describedby */ + @Input('matBadgeDescription') + get description(): string { return this._description; } + set description(val: string) { + if (this._description) { + this._updateHostAriaDescription(val, this._description); + } + this._description = val; + } + private _description: string; + + /** Size of the badge. Can be 'small', 'medium', or 'large'. */ + @Input('matBadgeSize') size: MatBadgeSize = 'medium'; + + /** Whether the badge is hidden. */ + @Input('matBadgeHidden') + get hidden(): boolean { return this._hidden; } + set hidden(val: boolean) { + this._hidden = coerceBooleanProperty(val); + } + private _hidden: boolean; + + /** Unique id for the badge */ + _id: number = nextId++; + + private _badgeElement: HTMLElement; + + constructor( + @Optional() @Inject(DOCUMENT) private _document: any, + private _ngZone: NgZone, + private _elementRef: ElementRef, + private _ariaDescriber: AriaDescriber) {} + + /** Whether the badge is above the host or not */ + isAbove(): boolean { + return this.position.indexOf('below') === -1; + } + + /** Whether the badge is after the host or not */ + isAfter(): boolean { + return this.position.indexOf('before') === -1; + } + + /** Injects a span element into the DOM with the content. */ + private _updateTextContent(): HTMLSpanElement { + if (!this._badgeElement) { + this._badgeElement = this._createBadgeElement(); + } else { + this._badgeElement.textContent = this.content; + } + return this._badgeElement; + } + + /** Creates the badge element */ + private _createBadgeElement(): HTMLElement { + const badgeElement = this._document.createElement('span'); + badgeElement.setAttribute('id', `mat-badge-content-${this._id}`); + badgeElement.classList.add('mat-badge-content'); + badgeElement.textContent = this.content; + + if (this.description) { + badgeElement.setAttribute('aria-label', this.description); + } + + this._elementRef.nativeElement.appendChild(badgeElement); + + // animate in after insertion + this._ngZone.runOutsideAngular(() => requestAnimationFrame(() => { + // ensure content available + if (badgeElement) { + badgeElement.classList.add('mat-badge-active'); + } + })); + + return badgeElement; + } + + /** Sets the aria-label property on the element */ + private _updateHostAriaDescription(val: string, prevVal: string): void { + // ensure content available before setting label + const content = this._updateTextContent(); + this._ariaDescriber.removeDescription(content, prevVal); + this._ariaDescriber.describe(content, val); + } + + /** Adds css theme class given the color to the component host */ + private _setColor(colorPalette: ThemePalette) { + if (colorPalette !== this._color) { + if (this._color) { + this._elementRef.nativeElement.classList.remove(`mat-badge-${this._color}`); + } + if (colorPalette) { + this._elementRef.nativeElement.classList.add(`mat-badge-${colorPalette}`); + } + } + } + +} diff --git a/src/lib/badge/index.ts b/src/lib/badge/index.ts new file mode 100644 index 000000000000..676ca90f1ffa --- /dev/null +++ b/src/lib/badge/index.ts @@ -0,0 +1,9 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +export * from './public-api'; diff --git a/src/lib/badge/public-api.ts b/src/lib/badge/public-api.ts new file mode 100644 index 000000000000..91b69772f78c --- /dev/null +++ b/src/lib/badge/public-api.ts @@ -0,0 +1,10 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +export * from './badge-module'; +export * from './badge'; diff --git a/src/lib/badge/tsconfig-build.json b/src/lib/badge/tsconfig-build.json new file mode 100644 index 000000000000..9e813e4e6317 --- /dev/null +++ b/src/lib/badge/tsconfig-build.json @@ -0,0 +1,14 @@ +{ + "extends": "../tsconfig-build", + "files": [ + "public-api.ts", + "../typings.d.ts" + ], + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "strictMetadataEmit": true, + "flatModuleOutFile": "index.js", + "flatModuleId": "@angular/material/badge", + "skipTemplateCodegen": true + } +} diff --git a/src/lib/core/theming/_all-theme.scss b/src/lib/core/theming/_all-theme.scss index 744aa5f6a4f1..50e142dbfca2 100644 --- a/src/lib/core/theming/_all-theme.scss +++ b/src/lib/core/theming/_all-theme.scss @@ -1,6 +1,7 @@ // Import all the theming functionality. @import '../core'; @import '../../autocomplete/autocomplete-theme'; +@import '../../badge/badge-theme'; @import '../../bottom-sheet/bottom-sheet-theme'; @import '../../button/button-theme'; @import '../../button-toggle/button-toggle-theme'; @@ -37,6 +38,7 @@ @mixin angular-material-theme($theme) { @include mat-core-theme($theme); @include mat-autocomplete-theme($theme); + @include mat-badge-theme($theme); @include mat-bottom-sheet-theme($theme); @include mat-button-theme($theme); @include mat-button-toggle-theme($theme); diff --git a/src/lib/core/typography/_all-typography.scss b/src/lib/core/typography/_all-typography.scss index fafa324df737..2f3acd58ba07 100644 --- a/src/lib/core/typography/_all-typography.scss +++ b/src/lib/core/typography/_all-typography.scss @@ -39,6 +39,7 @@ $config: mat-typography-config(); } + @include mat-badge-typography($config); @include mat-base-typography($config); @include mat-autocomplete-typography($config); @include mat-bottom-sheet-typography($config); diff --git a/src/lib/public-api.ts b/src/lib/public-api.ts index 42ab730a5b31..33001993d55c 100644 --- a/src/lib/public-api.ts +++ b/src/lib/public-api.ts @@ -8,6 +8,7 @@ export * from './version'; export * from '@angular/material/autocomplete'; +export * from '@angular/material/badge'; export * from '@angular/material/bottom-sheet'; export * from '@angular/material/button'; export * from '@angular/material/button-toggle'; diff --git a/test/karma-test-shim.js b/test/karma-test-shim.js index b3528b9b3e44..ae949d35a9f8 100644 --- a/test/karma-test-shim.js +++ b/test/karma-test-shim.js @@ -71,6 +71,7 @@ System.config({ '@angular/cdk/testing': 'dist/packages/cdk/testing/index.js', '@angular/material/autocomplete': 'dist/packages/material/autocomplete/index.js', + '@angular/material/badge': 'dist/packages/material/badge/index.js', '@angular/material/bottom-sheet': 'dist/packages/material/bottom-sheet/index.js', '@angular/material/button': 'dist/packages/material/button/index.js', '@angular/material/button-toggle': 'dist/packages/material/button-toggle/index.js',