From bfc1286fe7c53470eb84f572915a46ce48e88fb8 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 2 Oct 2018 19:37:29 +0200 Subject: [PATCH] feat(badge): allow badge to be disabled (#13196) Adds the `matBadgeDisabled` input that allows for a badge to be styled as if it was disabled. This allows it to blend in when it's attached to an element that is also disabled. Fixes #13191. --- src/demo-app/badge/badge-demo.html | 8 ++++++++ src/lib/badge/_badge-theme.scss | 16 ++++++++++++++++ src/lib/badge/badge.spec.ts | 15 ++++++++++++++- src/lib/badge/badge.ts | 17 ++++++++++++++--- 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/demo-app/badge/badge-demo.html b/src/demo-app/badge/badge-demo.html index ce92ee1253d..3dd1f9406c2 100644 --- a/src/demo-app/badge/badge-demo.html +++ b/src/demo-app/badge/badge-demo.html @@ -48,6 +48,14 @@ home + + + + diff --git a/src/lib/badge/_badge-theme.scss b/src/lib/badge/_badge-theme.scss index c7a441c9e18..79d992495ad 100644 --- a/src/lib/badge/_badge-theme.scss +++ b/src/lib/badge/_badge-theme.scss @@ -96,6 +96,8 @@ $mat-badge-large-size: $mat-badge-default-size + 6; $accent: map-get($theme, accent); $warn: map-get($theme, warn); $primary: map-get($theme, primary); + $background: map-get($theme, background); + $foreground: map-get($theme, foreground); .mat-badge-content { color: mat-color($primary, default-contrast); @@ -126,6 +128,20 @@ $mat-badge-large-size: $mat-badge-default-size + 6; } } + .mat-badge-disabled { + .mat-badge-content { + // The disabled color usually has some kind of opacity, but because the badge is overlayed + // on top of something else, it won't look good if it's opaque. We convert it into a solid + // color by taking the opacity from the rgba value and using the value to determine the + // percentage of the background to put into foreground when mixing the colors together. + $app-background: mat-color($background, 'background'); + $badge-color: mat-color($foreground, disabled-button); + $badge-opacity: opacity($badge-color); + background: mix($app-background, rgba($badge-color, 1), (1 - $badge-opacity) * 100%); + color: mat-color($foreground, disabled-text); + } + } + .mat-badge-content { position: absolute; text-align: center; diff --git a/src/lib/badge/badge.spec.ts b/src/lib/badge/badge.spec.ts index ff1ea263ab7..2152085d489 100644 --- a/src/lib/badge/badge.spec.ts +++ b/src/lib/badge/badge.spec.ts @@ -154,6 +154,17 @@ describe('MatBadge', () => { expect(encapsulationAttr).toBeTruthy(); }); + it('should toggle a class depending on the badge disabled state', () => { + const element: HTMLElement = badgeDebugElement.nativeElement; + + expect(element.classList).not.toContain('mat-badge-disabled'); + + testComponent.badgeDisabled = true; + fixture.detectChanges(); + + expect(element.classList).toContain('mat-badge-disabled'); + }); + }); /** Test component that contains a MatBadge. */ @@ -168,7 +179,8 @@ describe('MatBadge', () => { [matBadgeHidden]="badgeHidden" [matBadgeSize]="badgeSize" [matBadgeOverlap]="badgeOverlap" - [matBadgeDescription]="badgeDescription"> + [matBadgeDescription]="badgeDescription" + [matBadgeDisabled]="badgeDisabled"> home ` @@ -181,4 +193,5 @@ class BadgeTestApp { badgeSize = 'medium'; badgeOverlap = false; badgeDescription: string; + badgeDisabled = false; } diff --git a/src/lib/badge/badge.ts b/src/lib/badge/badge.ts index 3d761e27b19..439eae86075 100644 --- a/src/lib/badge/badge.ts +++ b/src/lib/badge/badge.ts @@ -19,17 +19,25 @@ import { Optional, Renderer2, } from '@angular/core'; -import {ThemePalette} from '@angular/material/core'; +import {ThemePalette, mixinDisabled, CanDisableCtor, CanDisable} from '@angular/material/core'; let nextId = 0; +// Boilerplate for applying mixins to MatBadge. +/** @docs-private */ +export class MatBadgeBase {} + +export const _MatBadgeMixinBase: + CanDisableCtor & typeof MatBadgeBase = mixinDisabled(MatBadgeBase); + 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]', + inputs: ['disabled: matBadgeDisabled'], host: { 'class': 'mat-badge', '[class.mat-badge-overlap]': 'overlap', @@ -41,9 +49,10 @@ export type MatBadgeSize = 'small' | 'medium' | 'large'; '[class.mat-badge-medium]': 'size === "medium"', '[class.mat-badge-large]': 'size === "large"', '[class.mat-badge-hidden]': 'hidden || !_hasContent', + '[class.mat-badge-disabled]': 'disabled', }, }) -export class MatBadge implements OnDestroy { +export class MatBadge extends _MatBadgeMixinBase implements OnDestroy, CanDisable { /** Whether the badge has any content. */ _hasContent = false; @@ -113,7 +122,9 @@ export class MatBadge implements OnDestroy { private _elementRef: ElementRef, private _ariaDescriber: AriaDescriber, /** @breaking-change 8.0.0 Make _renderer a required param and remove _document. */ - private _renderer?: Renderer2) {} + private _renderer?: Renderer2) { + super(); + } /** Whether the badge is above the host or not */ isAbove(): boolean {