diff --git a/apps/integration-e2e/src/e2e/vertical-tabset-back-to-top.cy.ts b/apps/integration-e2e/src/e2e/vertical-tabset-back-to-top.cy.ts index 5220a655b1..f38f10f535 100644 --- a/apps/integration-e2e/src/e2e/vertical-tabset-back-to-top.cy.ts +++ b/apps/integration-e2e/src/e2e/vertical-tabset-back-to-top.cy.ts @@ -17,22 +17,63 @@ describe('vertical-tabset-back-to-top', () => { if (device === 'iphone-6') { cy.get('.sky-vertical-tabset-content button') .should('be.visible') - .should('contain', 'Tab list') - .click(); + .should('contain', 'Tab list'); + cy.get('.sky-vertical-tabset-content button').click(); } cy.get('#sky-vertical-tab-1') .should('be.visible') - .should('contain', 'Group 1 Tab 1') - .click(); + .should('contain', 'Group 1 Tab 1'); + cy.get('#sky-vertical-tab-1').click(); cy.get( 'div[aria-labelledby="sky-vertical-tab-1"] > div:first-child', ) .should('be.visible') - .should('contain', 'Group 1 Tab 1 content') - .scrollTo('bottom'); + .should('contain', 'Group 1 Tab 1 content'); + cy.get( + 'div[aria-labelledby="sky-vertical-tab-1"] > div:first-child', + ).scrollTo('bottom'); + cy.get('sky-back-to-top button') + .should('be.visible') + .should('contain', 'Back to top'); + }); + + it('verify back-to-top with summary action', () => { + /* spell-checker:disable */ + if (device === 'iphone-6') { + cy.get('.sky-vertical-tabset-content button') + .should('be.visible') + .should('contain', 'Tab list'); + cy.get('.sky-vertical-tabset-content button').click(); + } + cy.get('#sky-vertical-tab-1') + .should('be.visible') + .should('contain', 'Group 1 Tab 1'); + cy.get('#sky-vertical-tab-1').click(); + cy.get( + 'div[aria-labelledby="sky-vertical-tab-1"] > div:first-child', + ) + .should('be.visible') + .should('contain', 'Group 1 Tab 1 content'); + cy.get('button[aria-label="Toggle summary"]') + .should('exist') + .should('be.visible'); + cy.get('button[aria-label="Toggle summary"]') + .first() + .scrollIntoView(); + cy.get('button[aria-label="Toggle summary"]') + .first() + .click('topLeft'); + cy.get('sky-summary-action-bar button').should('be.visible'); + cy.get( + 'div[aria-labelledby="sky-vertical-tab-1"] > div:first-child', + ).scrollTo('bottom'); cy.get('sky-back-to-top button') .should('be.visible') .should('contain', 'Back to top'); + cy.window().skyVisualTest( + `vertical-tabset-back-to-top-summary-action-${device}-${theme}`, + { capture: 'viewport' }, + ); }); }); }, diff --git a/apps/integration/src/app/integrations/modal-viewkept-toolbars/modal-viewkept-toolbars-modal.component.html b/apps/integration/src/app/integrations/modal-viewkept-toolbars/modal-viewkept-toolbars-modal.component.html index 3a57ad1bb0..44179890f9 100644 --- a/apps/integration/src/app/integrations/modal-viewkept-toolbars/modal-viewkept-toolbars-modal.component.html +++ b/apps/integration/src/app/integrations/modal-viewkept-toolbars/modal-viewkept-toolbars-modal.component.html @@ -3,6 +3,7 @@ 'viewkeeper inside a modal' | skyAppResources }}
@@ -75,13 +76,14 @@ } - + + + + Close + + + diff --git a/apps/integration/src/app/integrations/modal-viewkept-toolbars/modal-viewkept-toolbars-modal.component.ts b/apps/integration/src/app/integrations/modal-viewkept-toolbars/modal-viewkept-toolbars-modal.component.ts index 132ca5ac8a..2cb1cddaaf 100644 --- a/apps/integration/src/app/integrations/modal-viewkept-toolbars/modal-viewkept-toolbars-modal.component.ts +++ b/apps/integration/src/app/integrations/modal-viewkept-toolbars/modal-viewkept-toolbars-modal.component.ts @@ -1,9 +1,10 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { SkySummaryActionBarModule } from '@skyux/action-bars'; import { SkyViewkeeperModule } from '@skyux/core'; import { SkyCheckboxModule } from '@skyux/forms'; import { SkyI18nModule } from '@skyux/i18n'; import { SkyIconModule } from '@skyux/icon'; -import { SkyToolbarModule } from '@skyux/layout'; +import { SkyBackToTopModule, SkyToolbarModule } from '@skyux/layout'; import { SkySearchModule } from '@skyux/lookup'; import { SkyModalInstance, SkyModalModule } from '@skyux/modals'; import { SkyThemeModule } from '@skyux/theme'; @@ -15,6 +16,8 @@ import { SkyThemeModule } from '@skyux/theme'; styleUrls: ['./modal-viewkept-toolbars-modal.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, imports: [ + SkySummaryActionBarModule, + SkyBackToTopModule, SkyCheckboxModule, SkyIconModule, SkyI18nModule, diff --git a/apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.component.html b/apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.component.html index 30070c681a..2b041283c6 100644 --- a/apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.component.html +++ b/apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.component.html @@ -14,56 +14,72 @@

Vertical tabset

Group 1 Tab 1 content

Stuff

- Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean - commodo ligula eget dolor. Aenean massa. Cum sociis natoque - penatibus et magnis dis parturient montes, nascetur ridiculus mus. - Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. - Nulla consequat massa quis enim. Donec pede justo, fringilla vel, - aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, - imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede - mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum - semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, - porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem - ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra - nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. - Etiam ultricies Lorem ipsum dolor sit amet, consectetuer adipiscing - elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis - natoque penatibus et magnis dis parturient montes, nascetur - ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, - pretium quis, sem. Nulla consequat massa quis enim. Donec pede - justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim - justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam - dictum felis eu pede mollis pretium. Integer tincidunt. Cras - dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend - tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend - ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, - tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque - rutrum. Aenean imperdiet. Etiam ultricies Lorem ipsum dolor sit - amet, consectetuer adipiscing elit. Aenean commodo ligula eget - dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis - parturient montes, nascetur ridiculus mus. Donec quam felis, - ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat - massa quis enim. Donec pede justo, fringilla vel, aliquet nec, - vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, - venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. - Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. - Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, - consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, - viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus - varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean - commodo ligula eget dolor. Aenean massa. Cum sociis natoque - penatibus et magnis dis parturient montes, nascetur ridiculus mus. - Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. - Nulla consequat massa quis enim. Donec pede justo, fringilla vel, - aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, - imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede - mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum - semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, - porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem - ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra - nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. - Etiam ultricies +

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean @@ -270,3 +286,13 @@

Vertical tabset

+ +@if (showSummary()) { + + + + Primary Action + + + +} diff --git a/apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.component.ts b/apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.component.ts index ce840c1920..62be15f969 100644 --- a/apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.component.ts +++ b/apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, model } from '@angular/core'; @Component({ selector: 'app-vertical-tabset-back-to-top', @@ -41,4 +41,6 @@ export class VerticalTabsetBackToTopComponent { content: 'Tab 3 content', }, ]; + + protected readonly showSummary = model(false); } diff --git a/apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.module.ts b/apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.module.ts index 3c86ca30c6..6f0ef6a272 100644 --- a/apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.module.ts +++ b/apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.module.ts @@ -1,4 +1,5 @@ import { NgModule } from '@angular/core'; +import { SkySummaryActionBarModule } from '@skyux/action-bars'; import { SkyBackToTopModule } from '@skyux/layout'; import { SkyVerticalTabsetModule } from '@skyux/tabs'; @@ -9,6 +10,7 @@ import { VerticalTabsetBackToTopComponent } from './vertical-tabset-back-to-top. declarations: [VerticalTabsetBackToTopComponent], imports: [ SkyBackToTopModule, + SkySummaryActionBarModule, SkyVerticalTabsetModule, VerticalTabsetBackToTopRoutingModule, ], diff --git a/apps/playground/src/app/components/action-bars/summary-action-bar/summary-action-bar.component.html b/apps/playground/src/app/components/action-bars/summary-action-bar/summary-action-bar.component.html index 22832bdbbf..e84abad2bb 100644 --- a/apps/playground/src/app/components/action-bars/summary-action-bar/summary-action-bar.component.html +++ b/apps/playground/src/app/components/action-bars/summary-action-bar/summary-action-bar.component.html @@ -1,83 +1,145 @@ - - - - - - - Primary action - - - Foo - - Secondary action - - - Secondary action 2 - - - - Cancel - - - @if (showSummary) { - - - $123.00 - Field 1 - - - $456.00 - Field 2 - - - 18 - Field 3 - - - $123.00 - Field 1 - - - $456.00 - Field 2 - - - 18 - Field 3 - - - $123.00 - Field 1 - - - $456.00 - Field 2 - - - 18 - Field 3 - - +
+ + + + + @for (n of [1, 2, 3, 4, 5]; track n) { +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer + pellentesque tincidunt interdum. Ut sodales elementum enim id fermentum. + Nulla quis lacinia turpis, in laoreet augue. Integer euismod sagittis + nibh, ut blandit erat sagittis sed. Nullam a arcu sed ligula eleifend + lobortis at non nulla. Morbi eleifend dui sed gravida suscipit. Cras quis + luctus sapien, at auctor ante. Nulla vestibulum malesuada pulvinar. Nulla + facilisi. Curabitur eu felis et ante interdum malesuada. Nunc enim massa, + malesuada at faucibus a, placerat nec orci. In imperdiet vitae nisl ac + consequat. Praesent sed elit velit. Pellentesque sit amet congue lacus. + Sed placerat neque felis, ut facilisis nunc blandit eu. Cras posuere diam + vitae condimentum tincidunt. +

+

+ Donec tellus sapien, malesuada a nulla id, elementum rutrum sapien. + Aliquam erat volutpat. Cras fermentum felis urna, in condimentum ante + venenatis nec. Pellentesque pharetra semper massa quis venenatis. Quisque + in rhoncus ex, at pretium felis. Aliquam ante leo, ullamcorper interdum + feugiat quis, ultrices a nisl. Ut sit amet tempus massa, vel viverra + sapien. Morbi aliquam gravida nisl, lacinia placerat urna congue non. + Vivamus a orci quis turpis venenatis hendrerit nec non magna. Ut in odio + mi. +

+

+ Nulla congue lacinia lectus ut luctus. Quisque eget orci metus. Duis a + tristique arcu, a aliquet dui. Pellentesque euismod nisi congue elementum + tempus. Quisque mi lacus, eleifend ac dictum vitae, aliquam pellentesque + quam. Quisque ultricies metus mauris, sit amet dapibus tellus interdum in. + Donec id eleifend enim. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras a metus + eros. Proin sed lacus aliquam, cursus metus vitae, sagittis elit. Nullam + consectetur, justo eu pharetra molestie, libero arcu mollis dolor, eu + molestie urna ex eu ex. In dapibus mollis interdum. Curabitur tempor + consectetur ipsum. Curabitur convallis gravida rutrum. Nunc cursus, diam a + porttitor tempus, lectus diam dignissim tellus, nec accumsan orci nulla in + sem. Nunc volutpat tortor ac facilisis interdum. Praesent nulla enim, + imperdiet id orci sit amet, consectetur convallis odio. In bibendum dolor + a posuere pharetra. Sed convallis diam turpis, varius ultricies est + fermentum ut. Morbi tincidunt velit eu dolor congue, sed dapibus lectus + dictum. Ut finibus sagittis urna ut rhoncus. Pellentesque ornare, nunc et + dignissim varius, justo ipsum vehicula augue, nec fringilla erat velit in + tellus. +

+

+ Aenean rhoncus pretium felis convallis semper. Nunc aliquet mollis ligula, + id fringilla orci gravida eu. Nunc sed turpis vel nibh semper euismod at + non mauris. Donec lobortis ligula est, vitae aliquet mauris consectetur + ac. Aliquam ac eros accumsan, tempus dolor a, rutrum orci. Suspendisse eu + purus dui. Donec cursus non urna at consequat. Donec pharetra tincidunt + dapibus. Duis eu ligula mattis ex dictum tristique. Nam et mollis est, sit + amet tempus elit. Pellentesque sed maximus est, nec venenatis massa. + Phasellus eleifend tellus quis mi fringilla tristique. Quisque dignissim + ullamcorper augue, eget maximus arcu rutrum non. +

} - + + + + + Primary action + + + Foo + + Secondary action + + + Secondary action 2 + + + + Cancel + + + @if (showSummary) { + + + $123.00 + Field 1 + + + $456.00 + Field 2 + + + 18 + Field 3 + + + $123.00 + Field 1 + + + $456.00 + Field 2 + + + 18 + Field 3 + + + $123.00 + Field 1 + + + $456.00 + Field 2 + + + 18 + Field 3 + + + } + +
diff --git a/apps/playground/src/app/components/action-bars/summary-action-bar/summary-action-bar.component.ts b/apps/playground/src/app/components/action-bars/summary-action-bar/summary-action-bar.component.ts index b8faffab83..8d683f3f49 100644 --- a/apps/playground/src/app/components/action-bars/summary-action-bar/summary-action-bar.component.ts +++ b/apps/playground/src/app/components/action-bars/summary-action-bar/summary-action-bar.component.ts @@ -1,4 +1,5 @@ import { Component, OnDestroy } from '@angular/core'; +import { SkyKeyInfoLayoutType } from '@skyux/indicators'; import { SkyModalService } from '@skyux/modals'; import { Subject } from 'rxjs'; @@ -11,7 +12,7 @@ import { SummaryActionBarModalComponent } from './summary-action-bar-modal.compo styleUrls: ['./summary-action-bar.component.scss'], }) export class SummaryActionBarComponent implements OnDestroy { - public layout = 'vertical'; + public layout: SkyKeyInfoLayoutType = 'vertical'; public showSummary = true; diff --git a/apps/playground/src/app/components/action-bars/summary-action-bar/summary-action-bar.module.ts b/apps/playground/src/app/components/action-bars/summary-action-bar/summary-action-bar.module.ts index ec329a14f1..a54526b509 100644 --- a/apps/playground/src/app/components/action-bars/summary-action-bar/summary-action-bar.module.ts +++ b/apps/playground/src/app/components/action-bars/summary-action-bar/summary-action-bar.module.ts @@ -1,12 +1,19 @@ import { NgModule } from '@angular/core'; import { SkySummaryActionBarModule } from '@skyux/action-bars'; +import { SkyKeyInfoModule } from '@skyux/indicators'; +import { SkyBackToTopModule } from '@skyux/layout'; import { SummaryActionBarRoutingModule } from './summary-action-bar-routing.module'; import { SummaryActionBarComponent } from './summary-action-bar.component'; @NgModule({ declarations: [SummaryActionBarComponent], - imports: [SkySummaryActionBarModule, SummaryActionBarRoutingModule], + imports: [ + SkySummaryActionBarModule, + SkyBackToTopModule, + SummaryActionBarRoutingModule, + SkyKeyInfoModule, + ], }) export class SummaryActionBarModule { public static routes = SummaryActionBarRoutingModule.routes; diff --git a/libs/components/action-bars/src/lib/modules/summary-action-bar/summary-action-bar-adapter.service.ts b/libs/components/action-bars/src/lib/modules/summary-action-bar/summary-action-bar-adapter.service.ts index 09bbd21bae..40572d3ee3 100644 --- a/libs/components/action-bars/src/lib/modules/summary-action-bar/summary-action-bar-adapter.service.ts +++ b/libs/components/action-bars/src/lib/modules/summary-action-bar/summary-action-bar-adapter.service.ts @@ -36,7 +36,7 @@ export class SkySummaryActionBarAdapterService { this.#renderer.setStyle( body, 'margin-bottom', - actionBarEl.offsetHeight + 'px', + `calc(${actionBarEl.offsetHeight}px + var(--sky-dock-height, 0))`, ); } } diff --git a/libs/components/action-bars/src/lib/modules/summary-action-bar/summary-action-bar.component.scss b/libs/components/action-bars/src/lib/modules/summary-action-bar/summary-action-bar.component.scss index de4e2ea4a3..439b910fd2 100644 --- a/libs/components/action-bars/src/lib/modules/summary-action-bar/summary-action-bar.component.scss +++ b/libs/components/action-bars/src/lib/modules/summary-action-bar/summary-action-bar.component.scss @@ -9,7 +9,10 @@ width: 100%; margin-top: $sky-margin-double; position: fixed; - bottom: 0; + bottom: var(--sky-dock-height, 0); + transition-property: bottom; + transition-duration: 60ms; + transition-timing-function: ease-out; left: var(--sky-summary-action-bar-left, 0); z-index: 999; background-color: $sky-color-white; diff --git a/libs/components/action-bars/src/lib/modules/summary-action-bar/summary-action-bar.component.spec.ts b/libs/components/action-bars/src/lib/modules/summary-action-bar/summary-action-bar.component.spec.ts index baf467fe45..82fcd78891 100644 --- a/libs/components/action-bars/src/lib/modules/summary-action-bar/summary-action-bar.component.spec.ts +++ b/libs/components/action-bars/src/lib/modules/summary-action-bar/summary-action-bar.component.spec.ts @@ -126,17 +126,23 @@ describe('Summary Action Bar component', () => { it('should set a margin on the body if the action bar is not in a modal footer', () => { fixture.detectChanges(); const actionBarHeight = getActionBarHeight(debugElement); - expect(document.body.style.marginBottom).toBe(actionBarHeight + 'px'); + expect(document.body.style.marginBottom).toBe( + `calc(${actionBarHeight}px + var(--sky-dock-height, 0))`, + ); }); it('should set a new margin when the summary area changes collapsed state', fakeAsync(() => { mediaQueryController.setBreakpoint('xs'); fixture.detectChanges(); let actionBarHeight = getActionBarHeight(debugElement); - expect(document.body.style.marginBottom).toBe(actionBarHeight + 'px'); + expect(document.body.style.marginBottom).toBe( + `calc(${actionBarHeight}px + var(--sky-dock-height, 0))`, + ); clickCollapseButton(debugElement); actionBarHeight = getActionBarHeight(debugElement); - expect(document.body.style.marginBottom).toBe(actionBarHeight + 'px'); + expect(document.body.style.marginBottom).toBe( + `calc(${actionBarHeight}px + var(--sky-dock-height, 0))`, + ); })); it('should set a new margin on the body if the window is resized', () => { @@ -436,7 +442,9 @@ describe('Summary Action Bar component', () => { cmp.showSecondaryActionBar = true; fixture.detectChanges(); const actionBarHeight = getActionBarHeight(debugElement); - expect(document.body.style.marginBottom).toBe(actionBarHeight + 'px'); + expect(document.body.style.marginBottom).toBe( + `calc(${actionBarHeight}px + var(--sky-dock-height, 0))`, + ); }); it('should set isSummaryCollapsible to true when on a xs screen on a replaced action bar', () => { @@ -590,7 +598,7 @@ describe('Summary Action Bar component', () => { void fixture.whenStable().then(() => { const actionBarHeight = getActionBarHeight(debugElement); expect(document.body.style.marginBottom).toBe( - actionBarHeight + 'px', + `calc(${actionBarHeight}px + var(--sky-dock-height, 0))`, ); done(); }); @@ -622,7 +630,7 @@ describe('Summary Action Bar component', () => { void fixture.whenStable().then(() => { const actionBarHeight = getActionBarHeight(debugElement); expect(document.body.style.marginBottom).toBe( - actionBarHeight + 'px', + `calc(${actionBarHeight}px + var(--sky-dock-height, 0))`, ); done(); }); @@ -648,7 +656,7 @@ describe('Summary Action Bar component', () => { void fixture.whenStable().then(() => { const actionBarHeight = getActionBarHeight(debugElement); expect(document.body.style.marginBottom).toBe( - actionBarHeight + 'px', + `calc(${actionBarHeight}px + var(--sky-dock-height, 0))`, ); done(); }); diff --git a/libs/components/core/src/lib/modules/dock/dock-dom-adapter.service.ts b/libs/components/core/src/lib/modules/dock/dock-dom-adapter.service.ts index 0b844747b1..adb2311dd5 100644 --- a/libs/components/core/src/lib/modules/dock/dock-dom-adapter.service.ts +++ b/libs/components/core/src/lib/modules/dock/dock-dom-adapter.service.ts @@ -88,7 +88,7 @@ export class SkyDockDomAdapterService implements OnDestroy { // Create a style element to avoid overwriting any existing inline body styles. const styleElement = this.#renderer.createElement('style'); const textNode = this.#renderer.createText( - `body { margin-bottom: ${dockHeight}px; }`, + `body { margin-bottom: ${dockHeight}px; --sky-dock-height: ${dockHeight}px; }`, ); // Apply a `data-` attribute to make unit testing easier. diff --git a/libs/components/core/src/lib/modules/dock/dock.component.spec.ts b/libs/components/core/src/lib/modules/dock/dock.component.spec.ts index 359dd287f0..c3b5878fc0 100644 --- a/libs/components/core/src/lib/modules/dock/dock.component.spec.ts +++ b/libs/components/core/src/lib/modules/dock/dock.component.spec.ts @@ -238,7 +238,7 @@ describe('Dock component', () => { const styleElement = getStyleElement(); expect(styleElement.textContent).toContain( - `body { margin-bottom: 60px; }`, + `body { margin-bottom: 60px; --sky-dock-height: 60px; }`, ); })); @@ -260,7 +260,7 @@ describe('Dock component', () => { const styleElement = getStyleElement(); expect(styleElement.textContent).toContain( - `body { margin-bottom: 60px; }`, + `body { margin-bottom: 60px; --sky-dock-height: 60px; }`, ); })); diff --git a/libs/components/core/src/lib/modules/dock/dock.service.ts b/libs/components/core/src/lib/modules/dock/dock.service.ts index 10d5cf0e8b..b4fc658e28 100644 --- a/libs/components/core/src/lib/modules/dock/dock.service.ts +++ b/libs/components/core/src/lib/modules/dock/dock.service.ts @@ -1,4 +1,6 @@ -import { ComponentRef, Injectable, Type } from '@angular/core'; +import { ComponentRef, Injectable, Type, inject } from '@angular/core'; + +import { Subscription } from 'rxjs'; import { SkyDynamicComponentLocation } from '../dynamic-component/dynamic-component-location'; import { SkyDynamicComponentOptions } from '../dynamic-component/dynamic-component-options'; @@ -28,14 +30,11 @@ export class SkyDockService { return SkyDockService._items; } - #dynamicComponentSvc: SkyDynamicComponentService; + readonly #dynamicComponentSvc = inject(SkyDynamicComponentService); + #subscription: Subscription | undefined; #options: SkyDockOptions | undefined; - constructor(dynamicComponentSvc: SkyDynamicComponentService) { - this.#dynamicComponentSvc = dynamicComponentSvc; - } - /** * Docks a component to the bottom of the page. * @param component The component to dock. @@ -45,6 +44,7 @@ export class SkyDockService { component: Type, config?: SkyDockInsertComponentConfig, ): SkyDockItem { + this.#subscription ??= new Subscription(); const dockRef = (SkyDockService.dockRef = SkyDockService.dockRef || this.#createDock()); @@ -54,13 +54,15 @@ export class SkyDockService { itemRef.stackOrder, ); - item.destroyed.subscribe(() => { - dockRef.instance.removeItem(itemRef); - SkyDockService._items.splice(SkyDockService._items.indexOf(item), 1); - if (SkyDockService._items.length === 0) { - this.#destroyDock(); - } - }); + this.#subscription?.add( + item.destroyed.subscribe(() => { + dockRef.instance.removeItem(itemRef); + SkyDockService._items.splice(SkyDockService._items.indexOf(item), 1); + if (SkyDockService._items.length === 0) { + this.#destroyDock(); + } + }), + ); SkyDockService._items.push(item); SkyDockService._items.sort(sortByStackOrder); @@ -113,6 +115,8 @@ export class SkyDockService { } #destroyDock(): void { + this.#subscription?.unsubscribe(); + this.#subscription = undefined; this.#dynamicComponentSvc.removeComponent(SkyDockService.dockRef); SkyDockService.dockRef = undefined; } diff --git a/libs/components/modals/src/lib/modules/modal/modal.component.scss b/libs/components/modals/src/lib/modules/modal/modal.component.scss index f956e915bc..fdc52ab0b0 100644 --- a/libs/components/modals/src/lib/modules/modal/modal.component.scss +++ b/libs/components/modals/src/lib/modules/modal/modal.component.scss @@ -141,6 +141,7 @@ .sky-modal-content > ::ng-deep sky-dock { bottom: -$sky-padding-plus-half; margin-left: -$sky-margin-plus-half; + margin-right: -$sky-margin-plus-half; margin-bottom: -$sky-margin-plus-half; padding-top: $sky-padding-plus-half; width: calc(100% + 30px); @@ -169,6 +170,7 @@ .sky-modal-content > ::ng-deep sky-dock { bottom: 0; margin-left: initial; + margin-right: initial; margin-bottom: initial; padding-top: initial; width: 100%; diff --git a/libs/components/split-view/src/lib/modules/split-view/split-view.component.spec.ts b/libs/components/split-view/src/lib/modules/split-view/split-view.component.spec.ts index f8d5bce8fa..be6d098a55 100644 --- a/libs/components/split-view/src/lib/modules/split-view/split-view.component.spec.ts +++ b/libs/components/split-view/src/lib/modules/split-view/split-view.component.spec.ts @@ -395,7 +395,7 @@ describe('Split view component', () => { expect(rendererSpy).toHaveBeenCalledWith( splitViewElement, 'max-height', - 'calc(100vh - 100px - ' + actionBar.offsetHeight + 'px)', + `calc(100vh - 100px - calc(${actionBar.offsetHeight}px + var(--sky-dock-height, 0)))`, ); }, 10); })); @@ -772,7 +772,7 @@ describe('Split view component', () => { expect(rendererSpy).toHaveBeenCalledWith( splitViewElement, 'max-height', - 'calc(100vh - 0px - ' + actionBar.offsetHeight + 'px)', + `calc(100vh - 0px - calc(${actionBar.offsetHeight}px + var(--sky-dock-height, 0)))`, ); rendererSpy.calls.reset(); @@ -799,7 +799,7 @@ describe('Split view component', () => { expect(rendererSpy).toHaveBeenCalledWith( splitViewElement, 'max-height', - 'calc(100vh - 100px - ' + actionBar.offsetHeight + 'px)', + `calc(100vh - 100px - calc(${actionBar.offsetHeight}px + var(--sky-dock-height, 0)))`, ); }, 10); });