From a73dcf7898c9da06af31ee003d2fbde3e9a0e715 Mon Sep 17 00:00:00 2001 From: Trevor Burch Date: Tue, 23 Jul 2024 14:37:26 -0400 Subject: [PATCH] Move theme logic to modal to avoid new peer --- .../scroll-shadow.component.fixture.html | 1 + .../scroll-shadow.component.fixture.ts | 1 + .../scroll-shadow.directive.spec.ts | 277 ++++++----------- .../scroll-shadow/scroll-shadow.directive.ts | 54 ++-- .../lib/modules/modal/modal.component.html | 1 + .../lib/modules/modal/modal.component.spec.ts | 286 ++++++++++++------ .../src/lib/modules/modal/modal.component.ts | 18 +- 7 files changed, 333 insertions(+), 305 deletions(-) diff --git a/libs/components/core/src/lib/modules/scroll-shadow/fixtures/scroll-shadow.component.fixture.html b/libs/components/core/src/lib/modules/scroll-shadow/fixtures/scroll-shadow.component.fixture.html index 2801a0c612..0d6d7db432 100644 --- a/libs/components/core/src/lib/modules/scroll-shadow/fixtures/scroll-shadow.component.fixture.html +++ b/libs/components/core/src/lib/modules/scroll-shadow/fixtures/scroll-shadow.component.fixture.html @@ -8,6 +8,7 @@
{ return document.querySelector('.scroll-shadow-test-header'); } + function scrollElement(element: HTMLElement | null, yDistance: number): void { + if (element) { + element.scrollTop = yDistance; + SkyAppTestUtility.fireDomEvent(element, 'scroll'); + fixture.detectChanges(); + } + } + function validateShadow( el: HTMLElement | null, expectedAlpha?: number, @@ -69,191 +68,113 @@ describe('Scroll shadow directive', () => { let fixture: ComponentFixture; let cmp: ScrollShadowFixtureComponent; - describe('no theme service', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ScrollShadowFixtureComponent], - }); - - fixture = TestBed.createComponent(ScrollShadowFixtureComponent); - cmp = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should not show a shadow when the body is not scrollable', async () => { - validateShadow(getScrollFooter()); - validateShadow(getScrollHeader()); + beforeEach(fakeAsync(() => { + TestBed.configureTestingModule({ + imports: [ScrollShadowFixtureComponent], }); - it('should not show a shadow when the body is scrollable', async () => { - cmp.height = 800; - fixture.detectChanges(); - await waitForMutationObserver(); - fixture.detectChanges(); - - validateShadow(getScrollFooter()); - validateShadow(getScrollHeader()); - }); + fixture = TestBed.createComponent(ScrollShadowFixtureComponent); + cmp = fixture.componentInstance; + fixture.detectChanges(); + tick(); + fixture.detectChanges(); + })); + + it('should not show a shadow when the body is not scrollable when disabled', async () => { + cmp.enabled = false; + fixture.detectChanges(); + await waitForMutationObserver(); + fixture.detectChanges(); + + validateShadow(getScrollFooter()); + validateShadow(getScrollHeader()); }); - describe('default theme', () => { - const mockThemeSvc = { - settingsChange: new BehaviorSubject({ - currentSettings: new SkyThemeSettings( - SkyTheme.presets.default, - SkyThemeMode.presets.light, - ), - previousSettings: undefined, - }), - }; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ScrollShadowFixtureComponent], - providers: [ - { - provide: SkyThemeService, - useValue: mockThemeSvc, - }, - ], - }); - - fixture = TestBed.createComponent(ScrollShadowFixtureComponent); - cmp = fixture.componentInstance; - fixture.detectChanges(); - }); + it('should not show a shadow when the body is scrollable when disabled', async () => { + cmp.height = 800; + cmp.enabled = false; + fixture.detectChanges(); + await waitForMutationObserver(); + fixture.detectChanges(); - it('should not show a shadow when the body is not scrollable', async () => { - validateShadow(getScrollFooter()); - validateShadow(getScrollHeader()); - }); - - it('should not show a shadow when the body is scrollable', async () => { - cmp.height = 800; - fixture.detectChanges(); - await waitForMutationObserver(); - fixture.detectChanges(); - - validateShadow(getScrollFooter()); - validateShadow(getScrollHeader()); - }); + validateShadow(getScrollFooter()); + validateShadow(getScrollHeader()); }); - describe('modern theme', () => { - function scrollElement( - element: HTMLElement | null, - yDistance: number, - ): void { - if (element) { - element.scrollTop = yDistance; - SkyAppTestUtility.fireDomEvent(element, 'scroll'); - fixture.detectChanges(); - } - } - - const mockThemeSvc = { - settingsChange: new BehaviorSubject({ - currentSettings: new SkyThemeSettings( - SkyTheme.presets.modern, - SkyThemeMode.presets.light, - ), - previousSettings: undefined, - }), - }; - - beforeEach(fakeAsync(() => { - TestBed.configureTestingModule({ - imports: [ScrollShadowFixtureComponent], - providers: [ - { - provide: SkyThemeService, - useValue: mockThemeSvc, - }, - ], - }); - - fixture = TestBed.createComponent(ScrollShadowFixtureComponent); - cmp = fixture.componentInstance; - fixture.detectChanges(); - tick(); - fixture.detectChanges(); - })); - - it('should not show a shadow when the body is not scrollable', async () => { - await waitForMutationObserver(); - fixture.detectChanges(); - - validateShadow(getScrollFooter()); - validateShadow(getScrollHeader()); - }); - - it('should progressively show a drop shadow as the modal content scrolls', async () => { - const headerEl = getScrollHeader(); - const contentEl = getScrollBody(); - const footerEl = getScrollFooter(); - - if (!contentEl) { - fail('Content element not found'); - return; - } - - cmp.height = 800; - fixture.detectChanges(); - await waitForMutationObserver(); - fixture.detectChanges(); - - scrollElement(contentEl, 0); - validateShadow(headerEl); - validateShadow(footerEl, 0.3); - - scrollElement(contentEl, 15); - validateShadow(headerEl, 0.15); - validateShadow(footerEl, 0.3); + it('should not show a shadow when the body is not scrollable', async () => { + await waitForMutationObserver(); + fixture.detectChanges(); - scrollElement(contentEl, 30); - validateShadow(headerEl, 0.3); - validateShadow(footerEl, 0.3); + validateShadow(getScrollFooter()); + validateShadow(getScrollHeader()); + }); - scrollElement(contentEl, 31); - validateShadow(headerEl, 0.3); - validateShadow(footerEl, 0.3); + it('should progressively show a drop shadow as the modal content scrolls', async () => { + const headerEl = getScrollHeader(); + const contentEl = getScrollBody(); + const footerEl = getScrollFooter(); - scrollElement( - contentEl, - contentEl.scrollHeight - 15 - contentEl.clientHeight, - ); - validateShadow(headerEl, 0.3); - validateShadow(footerEl, 0.15); + if (!contentEl) { + fail('Content element not found'); + return; + } - scrollElement(contentEl, contentEl.scrollHeight - contentEl.clientHeight); - validateShadow(headerEl, 0.3); - validateShadow(footerEl); - }); + cmp.height = 800; + fixture.detectChanges(); + await waitForMutationObserver(); + fixture.detectChanges(); + + scrollElement(contentEl, 0); + validateShadow(headerEl); + validateShadow(footerEl, 0.3); + + scrollElement(contentEl, 15); + validateShadow(headerEl, 0.15); + validateShadow(footerEl, 0.3); + + scrollElement(contentEl, 30); + validateShadow(headerEl, 0.3); + validateShadow(footerEl, 0.3); + + scrollElement(contentEl, 31); + validateShadow(headerEl, 0.3); + validateShadow(footerEl, 0.3); + + scrollElement( + contentEl, + contentEl.scrollHeight - 15 - contentEl.clientHeight, + ); + validateShadow(headerEl, 0.3); + validateShadow(footerEl, 0.15); + + scrollElement(contentEl, contentEl.scrollHeight - contentEl.clientHeight); + validateShadow(headerEl, 0.3); + validateShadow(footerEl); + }); - it('should update the shadow on window resize', async () => { - const headerEl = getScrollHeader(); - const contentEl = getScrollBody(); - const footerEl = getScrollFooter(); + it('should update the shadow on window resize', async () => { + const headerEl = getScrollHeader(); + const contentEl = getScrollBody(); + const footerEl = getScrollFooter(); - if (!contentEl) { - fail('Content element not found'); - return; - } + if (!contentEl) { + fail('Content element not found'); + return; + } - cmp.height = 800; - fixture.detectChanges(); - await waitForMutationObserver(); - fixture.detectChanges(); + cmp.height = 800; + fixture.detectChanges(); + await waitForMutationObserver(); + fixture.detectChanges(); - validateShadow(headerEl); - validateShadow(footerEl, 0.3); + validateShadow(headerEl); + validateShadow(footerEl, 0.3); - spyOnProperty(Element.prototype, 'scrollTop').and.returnValue(15); - SkyAppTestUtility.fireDomEvent(window, 'resize'); - fixture.detectChanges(); + spyOnProperty(Element.prototype, 'scrollTop').and.returnValue(15); + SkyAppTestUtility.fireDomEvent(window, 'resize'); + fixture.detectChanges(); - validateShadow(headerEl, 0.15); - validateShadow(footerEl, 0.3); - }); + validateShadow(headerEl, 0.15); + validateShadow(footerEl, 0.3); }); }); diff --git a/libs/components/core/src/lib/modules/scroll-shadow/scroll-shadow.directive.ts b/libs/components/core/src/lib/modules/scroll-shadow/scroll-shadow.directive.ts index 521d4a948b..51946b830e 100644 --- a/libs/components/core/src/lib/modules/scroll-shadow/scroll-shadow.directive.ts +++ b/libs/components/core/src/lib/modules/scroll-shadow/scroll-shadow.directive.ts @@ -3,16 +3,14 @@ import { ElementRef, EventEmitter, HostListener, + Input, NgZone, OnDestroy, - OnInit, Output, inject, } from '@angular/core'; -import { SkyTheme, SkyThemeService } from '@skyux/theme'; import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; import { SkyMutationObserverService } from '../mutation/mutation-observer-service'; @@ -27,14 +25,32 @@ import { SkyScrollShadowEventArgs } from './scroll-shadow-event-args'; standalone: true, selector: '[skyScrollShadow]', }) -export class SkyScrollShadowDirective implements OnInit, OnDestroy { +export class SkyScrollShadowDirective implements OnDestroy { + @Input() + public set skyScrollShadowEnabled(value: boolean) { + this.#_enabled = value; + + if (value) { + this.#initMutationObserver(); + } else { + this.#emitShadow({ + bottomShadow: 'none', + topShadow: 'none', + }); + + this.#destroyMutationObserver(); + } + } + + public get skyScrollShadowEnabled(): boolean { + return this.#_enabled; + } + @Output() public skyScrollShadow = new EventEmitter(); #currentShadow: SkyScrollShadowEventArgs | undefined; - #currentTheme: SkyTheme | undefined; - #mutationObserver: MutationObserver | undefined; #ngUnsubscribe = new Subject(); @@ -42,7 +58,8 @@ export class SkyScrollShadowDirective implements OnInit, OnDestroy { readonly #elRef = inject(ElementRef); readonly #mutationObserverSvc = inject(SkyMutationObserverService); readonly #ngZone = inject(NgZone); - readonly #themeSvc = inject(SkyThemeService, { optional: true }); + + #_enabled = false; @HostListener('window:resize') public windowResize(): void { @@ -54,27 +71,6 @@ export class SkyScrollShadowDirective implements OnInit, OnDestroy { this.#checkForShadow(); } - public ngOnInit(): void { - if (this.#themeSvc) { - this.#themeSvc.settingsChange - .pipe(takeUntil(this.#ngUnsubscribe)) - .subscribe((themeSettings) => { - this.#currentTheme = themeSettings.currentSettings.theme; - - if (this.#currentTheme === SkyTheme.presets.modern) { - this.#initMutationObserver(); - } else { - this.#emitShadow({ - bottomShadow: 'none', - topShadow: 'none', - }); - - this.#destroyMutationObserver(); - } - }); - } - } - public ngOnDestroy(): void { this.#ngUnsubscribe.next(); this.#ngUnsubscribe.complete(); @@ -112,7 +108,7 @@ export class SkyScrollShadowDirective implements OnInit, OnDestroy { } #checkForShadow(): void { - if (this.#currentTheme === SkyTheme.presets.modern) { + if (this.skyScrollShadowEnabled) { const el: Element = this.#elRef.nativeElement; const topShadow = this.#buildShadowStyle(el.scrollTop); diff --git a/libs/components/modals/src/lib/modules/modal/modal.component.html b/libs/components/modals/src/lib/modules/modal/modal.component.html index e7d9faede1..e20f7f56e8 100644 --- a/libs/components/modals/src/lib/modules/modal/modal.component.html +++ b/libs/components/modals/src/lib/modules/modal/modal.component.html @@ -78,6 +78,7 @@ skyId [attr.aria-labelledby]="headerId.id" (skyScrollShadow)="scrollShadowChange($event)" + [skyScrollShadowEnabled]="scrollShadowEnabled" #modalContentId="skyId" #modalContentWrapper > diff --git a/libs/components/modals/src/lib/modules/modal/modal.component.spec.ts b/libs/components/modals/src/lib/modules/modal/modal.component.spec.ts index e49efadfd3..f9f99e0afe 100644 --- a/libs/components/modals/src/lib/modules/modal/modal.component.spec.ts +++ b/libs/components/modals/src/lib/modules/modal/modal.component.spec.ts @@ -1058,7 +1058,7 @@ describe('Modal component', () => { await expectAsync(getModalElement()).toBeAccessible(); }); - describe('when modern theme', () => { + describe('scroll shadow', () => { function scrollContent(contentEl: HTMLElement, top: number): void { contentEl.scrollTop = top; @@ -1113,129 +1113,221 @@ describe('Modal component', () => { } } - it('should progressively show a drop shadow as the modal content scrolls', fakeAsync(() => { - setModernTheme(); - - const modalInstance1 = openModal(ModalTestComponent); - - const modalHeaderEl = document.querySelector( - '.sky-modal-header', - ) as HTMLElement; - const modalContentEl = document.querySelector( - '.sky-modal-content', - ) as HTMLElement; - const modalFooterEl = document.querySelector( - '.sky-modal-footer', - ) as HTMLElement; - - const fixtureContentEl = document.querySelector( - '.modal-fixture-content', - ) as HTMLElement; - fixtureContentEl.style.height = `${window.innerHeight + 100}px`; - - scrollContent(modalContentEl, 0); - validateShadow(modalHeaderEl); - validateShadow(modalFooterEl, 0.3); - - scrollContent(modalContentEl, 15); - validateShadow(modalHeaderEl, 0.15); - validateShadow(modalFooterEl, 0.3); - - scrollContent(modalContentEl, 30); - validateShadow(modalHeaderEl, 0.3); - validateShadow(modalFooterEl, 0.3); - - scrollContent(modalContentEl, 31); - validateShadow(modalHeaderEl, 0.3); - validateShadow(modalFooterEl, 0.3); - - scrollContent( - modalContentEl, - modalContentEl.scrollHeight - 15 - modalContentEl.clientHeight, - ); - validateShadow(modalHeaderEl, 0.3); - validateShadow(modalFooterEl, 0.15); + describe('when default theme', () => { + it('should not show a drop shadow as the modal content scrolls', fakeAsync(() => { + const modalInstance1 = openModal(ModalTestComponent); + + const modalHeaderEl = document.querySelector( + '.sky-modal-header', + ) as HTMLElement; + const modalContentEl = document.querySelector( + '.sky-modal-content', + ) as HTMLElement; + const modalFooterEl = document.querySelector( + '.sky-modal-footer', + ) as HTMLElement; + + const fixtureContentEl = document.querySelector( + '.modal-fixture-content', + ) as HTMLElement; + fixtureContentEl.style.height = `${window.innerHeight + 100}px`; + + scrollContent(modalContentEl, 0); + validateShadow(modalHeaderEl); + validateShadow(modalFooterEl); + + scrollContent(modalContentEl, 15); + validateShadow(modalHeaderEl); + validateShadow(modalFooterEl); + + scrollContent(modalContentEl, 30); + validateShadow(modalHeaderEl); + validateShadow(modalFooterEl); + + scrollContent(modalContentEl, 31); + validateShadow(modalHeaderEl); + validateShadow(modalFooterEl); + + scrollContent( + modalContentEl, + modalContentEl.scrollHeight - 15 - modalContentEl.clientHeight, + ); + validateShadow(modalHeaderEl); + validateShadow(modalFooterEl); - scrollContent( - modalContentEl, - modalContentEl.scrollHeight - modalContentEl.clientHeight, - ); - validateShadow(modalHeaderEl, 0.3); - validateShadow(modalFooterEl); + scrollContent( + modalContentEl, + modalContentEl.scrollHeight - modalContentEl.clientHeight, + ); + validateShadow(modalHeaderEl); + validateShadow(modalFooterEl); - closeModal(modalInstance1); - })); + closeModal(modalInstance1); + })); - it('should check for shadow when elements are added to the modal content', fakeAsync(() => { - let mutateCallback: MutationCallback | undefined; + it('should not check for shadow when elements are added to the modal content', fakeAsync(() => { + let mutateCallback: MutationCallback | undefined; - const fakeMutationObserver: MutationObserver = { - observe: jasmine.createSpy('observe'), - disconnect: jasmine.createSpy('disconnect'), - takeRecords: jasmine.createSpy('takeRecords'), - }; + const fakeMutationObserver: MutationObserver = { + observe: jasmine.createSpy('observe'), + disconnect: jasmine.createSpy('disconnect'), + takeRecords: jasmine.createSpy('takeRecords'), + }; - spyOn(TestBed.inject(SkyMutationObserverService), 'create').and.callFake( - (cb) => { + spyOn( + TestBed.inject(SkyMutationObserverService), + 'create', + ).and.callFake((cb) => { mutateCallback = cb; return fakeMutationObserver; - }, - ); + }); - setModernTheme(); + const modalInstance1 = openModal(ModalTestComponent); - const modalInstance1 = openModal(ModalTestComponent); + const modalFooterEl = document.querySelector( + '.sky-modal-footer', + ) as HTMLElement; - const modalFooterEl = document.querySelector( - '.sky-modal-footer', - ) as HTMLElement; + const fixtureContentEl = document.querySelector( + '.modal-fixture-content', + ) as HTMLElement; - const fixtureContentEl = document.querySelector( - '.modal-fixture-content', - ) as HTMLElement; + const childEl = document.createElement('div'); + childEl.style.height = `${window.innerHeight + 100}px`; + childEl.style.backgroundColor = 'red'; - const childEl = document.createElement('div'); - childEl.style.height = `${window.innerHeight + 100}px`; - childEl.style.backgroundColor = 'red'; + fixtureContentEl.appendChild(childEl); - fixtureContentEl.appendChild(childEl); + triggerMutation(mutateCallback, fakeMutationObserver); - triggerMutation(mutateCallback, fakeMutationObserver); + tick(); + getApplicationRef().tick(); - tick(); - getApplicationRef().tick(); + validateShadow(modalFooterEl); - validateShadow(modalFooterEl, 0.3); + fixtureContentEl.removeChild(childEl); - fixtureContentEl.removeChild(childEl); + triggerMutation(mutateCallback, fakeMutationObserver); - triggerMutation(mutateCallback, fakeMutationObserver); + tick(); + getApplicationRef().tick(); - tick(); - getApplicationRef().tick(); + validateShadow(modalFooterEl); - validateShadow(modalFooterEl); + closeModal(modalInstance1); + })); + }); - closeModal(modalInstance1); - })); + describe('when modern theme', () => { + it('should progressively show a drop shadow as the modal content scrolls', fakeAsync(() => { + setModernTheme(); + + const modalInstance1 = openModal(ModalTestComponent); + + const modalHeaderEl = document.querySelector( + '.sky-modal-header', + ) as HTMLElement; + const modalContentEl = document.querySelector( + '.sky-modal-content', + ) as HTMLElement; + const modalFooterEl = document.querySelector( + '.sky-modal-footer', + ) as HTMLElement; + + const fixtureContentEl = document.querySelector( + '.modal-fixture-content', + ) as HTMLElement; + fixtureContentEl.style.height = `${window.innerHeight + 100}px`; + + scrollContent(modalContentEl, 0); + validateShadow(modalHeaderEl); + validateShadow(modalFooterEl, 0.3); + + scrollContent(modalContentEl, 15); + validateShadow(modalHeaderEl, 0.15); + validateShadow(modalFooterEl, 0.3); + + scrollContent(modalContentEl, 30); + validateShadow(modalHeaderEl, 0.3); + validateShadow(modalFooterEl, 0.3); + + scrollContent(modalContentEl, 31); + validateShadow(modalHeaderEl, 0.3); + validateShadow(modalFooterEl, 0.3); + + scrollContent( + modalContentEl, + modalContentEl.scrollHeight - 15 - modalContentEl.clientHeight, + ); + validateShadow(modalHeaderEl, 0.3); + validateShadow(modalFooterEl, 0.15); - it('should not create multiple mutation observers', fakeAsync(() => { - const modalInstance1 = openModal(ModalTestComponent); + scrollContent( + modalContentEl, + modalContentEl.scrollHeight - modalContentEl.clientHeight, + ); + validateShadow(modalHeaderEl, 0.3); + validateShadow(modalFooterEl); - const mutationObserverCreateSpy = spyOn( - TestBed.inject(SkyMutationObserverService), - 'create', - ).and.callThrough(); + closeModal(modalInstance1); + })); - setModernTheme(); - setModernTheme(); - setModernTheme(); + it('should check for shadow when elements are added to the modal content', fakeAsync(() => { + let mutateCallback: MutationCallback | undefined; - expect(mutationObserverCreateSpy.calls.count()).toBe(1); + const fakeMutationObserver: MutationObserver = { + observe: jasmine.createSpy('observe'), + disconnect: jasmine.createSpy('disconnect'), + takeRecords: jasmine.createSpy('takeRecords'), + }; - closeModal(modalInstance1); - })); + spyOn( + TestBed.inject(SkyMutationObserverService), + 'create', + ).and.callFake((cb) => { + mutateCallback = cb; + + return fakeMutationObserver; + }); + + setModernTheme(); + + const modalInstance1 = openModal(ModalTestComponent); + + const modalFooterEl = document.querySelector( + '.sky-modal-footer', + ) as HTMLElement; + + const fixtureContentEl = document.querySelector( + '.modal-fixture-content', + ) as HTMLElement; + + const childEl = document.createElement('div'); + childEl.style.height = `${window.innerHeight + 100}px`; + childEl.style.backgroundColor = 'red'; + + fixtureContentEl.appendChild(childEl); + + triggerMutation(mutateCallback, fakeMutationObserver); + + tick(); + getApplicationRef().tick(); + + validateShadow(modalFooterEl, 0.3); + + fixtureContentEl.removeChild(childEl); + + triggerMutation(mutateCallback, fakeMutationObserver); + + tick(); + getApplicationRef().tick(); + + validateShadow(modalFooterEl); + + closeModal(modalInstance1); + })); + }); }); it('should pass accessibility with scrolling content', async () => { diff --git a/libs/components/modals/src/lib/modules/modal/modal.component.ts b/libs/components/modals/src/lib/modules/modal/modal.component.ts index 81140fbacd..51af8d7004 100644 --- a/libs/components/modals/src/lib/modules/modal/modal.component.ts +++ b/libs/components/modals/src/lib/modules/modal/modal.component.ts @@ -26,6 +26,7 @@ import { } from '@skyux/core'; import { SkyHelpInlineModule } from '@skyux/help-inline'; import { SkyIconModule } from '@skyux/icon'; +import { SkyTheme, SkyThemeService } from '@skyux/theme'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -163,13 +164,18 @@ export class SkyModalComponent implements AfterViewInit, OnDestroy, OnInit { public modalZIndex: number | undefined; - public scrollShadow: SkyScrollShadowEventArgs | undefined; + public scrollShadow: SkyScrollShadowEventArgs = { + bottomShadow: 'none', + topShadow: 'none', + }; public size: string; @ViewChild('modalContentWrapper', { read: ElementRef }) public modalContentWrapperElement: ElementRef | undefined; + protected scrollShadowEnabled = false; + #ngUnsubscribe = new Subject(); #_ariaDescribedBy: string | undefined; @@ -197,6 +203,7 @@ export class SkyModalComponent implements AfterViewInit, OnDestroy, OnInit { readonly #config = inject(SkyModalConfiguration, { optional: true }) ?? new SkyModalConfiguration(); + readonly #themeSvc = inject(SkyThemeService, { optional: true }); constructor() { this.ariaDescribedBy = this.#config.ariaDescribedBy; @@ -280,6 +287,15 @@ export class SkyModalComponent implements AfterViewInit, OnDestroy, OnInit { this.#changeDetector.markForCheck(); } }); + + if (this.#themeSvc) { + this.#themeSvc.settingsChange + .pipe(takeUntil(this.#ngUnsubscribe)) + .subscribe((themeSettings) => { + this.scrollShadowEnabled = + themeSettings.currentSettings.theme === SkyTheme.presets.modern; + }); + } } public ngAfterViewInit(): void {