From 594b7d312cb444409cf61c577270dadec80aa966 Mon Sep 17 00:00:00 2001 From: xelaint Date: Tue, 23 Jul 2024 16:18:57 -0600 Subject: [PATCH] feat(design): create daffStatusMixin to a directive --- .../src/button/button.component.spec.ts | 16 ++++---- .../button/src/button/button.component.ts | 13 ++++--- .../notification-status.component.html | 4 +- .../notification/src/notification-theme.scss | 2 +- .../notification.component.spec.ts | 18 ++------- .../notification/notification.component.ts | 38 ++++++------------- libs/design/src/core/statusable/public_api.ts | 1 + .../core/statusable/statusable.directive.ts | 35 +++++++++++++++++ 8 files changed, 70 insertions(+), 57 deletions(-) create mode 100644 libs/design/src/core/statusable/statusable.directive.ts diff --git a/libs/design/button/src/button/button.component.spec.ts b/libs/design/button/src/button/button.component.spec.ts index cc87515a1e..c87779bff9 100644 --- a/libs/design/button/src/button/button.component.spec.ts +++ b/libs/design/button/src/button/button.component.spec.ts @@ -207,17 +207,15 @@ describe('@daffodil/design/button | DaffButtonComponent', () => { }); }); - describe('using the status property of a button', () => { - it('should not set a default status', () => { - expect(component.status).toBeFalsy(); - }); + it('should take status as an input', () => { + wrapper.status = 'warn'; + fixture.detectChanges(); - it('should add the class of the defined status to the host element', () => { - wrapper.status = 'warn'; - fixture.detectChanges(); + expect(de.nativeElement.classList.contains('daff-warn')).toEqual(true); + }); - expect(de.nativeElement.classList.contains('daff-warn')).toEqual(true); - }); + it('should not set a default status', () => { + expect(component.status).toBeFalsy(); }); describe('using the tabindex property of a button', () => { diff --git a/libs/design/button/src/button/button.component.ts b/libs/design/button/src/button/button.component.ts index 719dad96a3..54bacf8eba 100644 --- a/libs/design/button/src/button/button.component.ts +++ b/libs/design/button/src/button/button.component.ts @@ -17,9 +17,8 @@ import { DaffSuffixable, daffPrefixableMixin, daffSuffixableMixin, - DaffStatusable, - daffStatusMixin, DaffArticleEncapsulatedDirective, + DaffStatusableDirective, } from '@daffodil/design'; import { DaffButtonSizableDirective } from './button-sizable.directive'; @@ -43,7 +42,7 @@ class DaffButtonBase{ constructor(public _elementRef: ElementRef, public _renderer: Renderer2) {} } -const _daffButtonBase = daffPrefixableMixin(daffSuffixableMixin(daffColorMixin(daffStatusMixin((DaffButtonBase))))); +const _daffButtonBase = daffPrefixableMixin(daffSuffixableMixin(daffColorMixin((DaffButtonBase)))); export type DaffButtonType = 'daff-button' | 'daff-stroked-button' | 'daff-raised-button' | 'daff-flat-button' | 'daff-icon-button' | 'daff-underline-button' | undefined; @@ -78,20 +77,24 @@ enum DaffButtonTypeEnum { styleUrls: ['./button.component.scss'], //todo(damienwebdev): remove once decorators hit stage 3 - https://github.com/microsoft/TypeScript/issues/7342 // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['color', 'status'], + inputs: ['color'], hostDirectives: [ { directive: DaffArticleEncapsulatedDirective }, { directive: DaffButtonSizableDirective, inputs: ['size'], }, + { + directive: DaffStatusableDirective, + inputs: ['status'], + }, ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, }) export class DaffButtonComponent extends _daffButtonBase - implements OnInit, DaffPrefixable, DaffSuffixable, DaffColorable, DaffStatusable { + implements OnInit, DaffPrefixable, DaffSuffixable, DaffColorable { private buttonType: DaffButtonType; diff --git a/libs/design/notification/examples/src/notification-status/notification-status.component.html b/libs/design/notification/examples/src/notification-status/notification-status.component.html index 9e2621d55c..649aa74140 100644 --- a/libs/design/notification/examples/src/notification-status/notification-status.component.html +++ b/libs/design/notification/examples/src/notification-status/notification-status.component.html @@ -1,7 +1,7 @@ - +
Title
This is the subtitle with information
@@ -9,5 +9,5 @@ \ No newline at end of file diff --git a/libs/design/notification/src/notification-theme.scss b/libs/design/notification/src/notification-theme.scss index 96a04a4dd3..8e3b379286 100644 --- a/libs/design/notification/src/notification-theme.scss +++ b/libs/design/notification/src/notification-theme.scss @@ -37,7 +37,7 @@ } } - &.daff-error { + &.daff-danger { background: theming.daff-color(theming.$daff-red, 10); border: 1px solid theming.daff-color(theming.$daff-red, 20); color: theming.daff-text-contrast(theming.daff-color(theming.$daff-red, 10)); diff --git a/libs/design/notification/src/notification/notification.component.spec.ts b/libs/design/notification/src/notification/notification.component.spec.ts index 6fb0528700..0c8a4dd726 100644 --- a/libs/design/notification/src/notification/notification.component.spec.ts +++ b/libs/design/notification/src/notification/notification.component.spec.ts @@ -1,9 +1,6 @@ import { Component, - ContentChild, DebugElement, - Input, - ViewChild, } from '@angular/core'; import { waitForAsync, @@ -18,7 +15,6 @@ import { DaffNotificationComponent, DaffNotificationOrientation, } from './notification.component'; -import { DaffNotificationActionsDirective } from '../notification-actions/notification-actions.directive'; @Component ({ template: ` @@ -133,17 +129,11 @@ describe('@daffodil/design/notification | DaffNotificationComponent', () => { }); }); - describe('using the status property of a notification', () => { - it('should not set a default status', () => { - expect(component.status).toBeFalsy(); - }); - - it('should add the class of the defined status to the host element', () => { - wrapper.status = 'warn'; - fixture.detectChanges(); + it('should take status as an input', () => { + wrapper.status = 'warn'; + fixture.detectChanges(); - expect(de.nativeElement.classList.contains('daff-warn')).toEqual(true); - }); + expect(de.nativeElement.classList.contains('daff-warn')).toEqual(true); }); describe('setting the orientation of a notification', () => { diff --git a/libs/design/notification/src/notification/notification.component.ts b/libs/design/notification/src/notification/notification.component.ts index 2e196240f3..dc5c925d18 100644 --- a/libs/design/notification/src/notification/notification.component.ts +++ b/libs/design/notification/src/notification/notification.component.ts @@ -17,21 +17,13 @@ import { DaffPrefixable, DaffPrefixDirective, DaffStatusable, + DaffStatusableDirective, DaffStatusEnum, daffStatusMixin, } from '@daffodil/design'; import { DaffNotificationActionsDirective } from '../notification-actions/notification-actions.directive'; -/** - * An _elementRef is needed for the core mixins - */ -class DaffNotificationBase { - constructor(public _elementRef: ElementRef, public _renderer: Renderer2) {} -} - -const _daffNotificationBase = daffStatusMixin(DaffNotificationBase); - export type DaffNotificationOrientation = 'horizontal' | 'vertical'; enum DaffNotificationOrientationEnum { @@ -47,18 +39,17 @@ enum DaffNotificationOrientationEnum { selector: 'daff-notification', templateUrl: './notification.component.html', styleUrls: ['./notification.component.scss'], - // todo(damienwebdev): remove once decorators hit stage 3 - https://github.com/microsoft/TypeScript/issues/7342 - // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['status'], - hostDirectives: [{ - directive: DaffArticleEncapsulatedDirective, - }], + hostDirectives: [ + { directive: DaffArticleEncapsulatedDirective }, + { + directive: DaffStatusableDirective, + inputs: ['status'], + }, + ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class DaffNotificationComponent - extends _daffNotificationBase - implements DaffPrefixable, DaffStatusable { +export class DaffNotificationComponent implements DaffPrefixable { faTimes = faTimes; @ContentChild(DaffPrefixDirective) _prefix: DaffPrefixDirective; @@ -74,7 +65,7 @@ export class DaffNotificationComponent * Sets role to status on all other instances. */ @HostBinding('attr.role') get role() { - return this.status === DaffStatusEnum.Warn || this.status === DaffStatusEnum.Danger ? 'alert' : 'status'; + return this.statusDirective.status === DaffStatusEnum.Warn || this.statusDirective.status === DaffStatusEnum.Danger ? 'alert' : 'status'; }; @HostBinding('class.vertical') get verticalOrientation() { @@ -88,6 +79,8 @@ export class DaffNotificationComponent /** Whether or not a notification is closable */ @Input() @HostBinding('class.dismissible') dismissible = false; + constructor(private statusDirective: DaffStatusableDirective) {} + private _orientation: DaffNotificationOrientation = DaffNotificationOrientationEnum.Vertical; @Input() @@ -103,13 +96,6 @@ export class DaffNotificationComponent } }; - constructor( - private elementRef: ElementRef, - private renderer: Renderer2, - ) { - super(elementRef, renderer); - } - /** * Output event triggered when the close icon is clicked. */ diff --git a/libs/design/src/core/statusable/public_api.ts b/libs/design/src/core/statusable/public_api.ts index edce10f826..fbf939e940 100644 --- a/libs/design/src/core/statusable/public_api.ts +++ b/libs/design/src/core/statusable/public_api.ts @@ -4,3 +4,4 @@ export { DaffStatusEnum, } from './statusable'; export { daffStatusMixin } from './statusable-mixin'; +export { DaffStatusableDirective } from './statusable.directive'; diff --git a/libs/design/src/core/statusable/statusable.directive.ts b/libs/design/src/core/statusable/statusable.directive.ts new file mode 100644 index 0000000000..f12400b383 --- /dev/null +++ b/libs/design/src/core/statusable/statusable.directive.ts @@ -0,0 +1,35 @@ +import { + Directive, + HostBinding, + Input, +} from '@angular/core'; + +import { + DaffStatus, + DaffStatusEnum, + DaffStatusable, +} from './statusable'; + +@Directive({ + selector: '[daffStatusable]', + standalone: true, +}) + +export class DaffStatusableDirective implements DaffStatusable { + /** + * @docs-private + */ + @HostBinding('class') get class() { + return { + 'daff-warn': this.status === DaffStatusEnum.Warn, + 'daff-danger': this.status === DaffStatusEnum.Danger, + 'daff-success': this.status === DaffStatusEnum.Success, + }; + } + + /** + * Sets the status on a component. + */ + @Input() status: DaffStatus; +} +