diff --git a/src/app/shared/components/modal-host/modal-host.component.spec.ts b/src/app/shared/components/modal-host/modal-host.component.spec.ts
index fd5af67..4946a52 100644
--- a/src/app/shared/components/modal-host/modal-host.component.spec.ts
+++ b/src/app/shared/components/modal-host/modal-host.component.spec.ts
@@ -3,25 +3,10 @@ import { Component, inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { TestBed, getTestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
-import {
- BrowserTestingModule,
- platformBrowserTesting
-} from '@angular/platform-browser/testing';
-import {
- afterEach,
- beforeAll,
- beforeEach,
- describe,
- expect,
- it,
- vi
-} from 'vitest';
+import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
+import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
-import {
- MODAL_DATA,
- ModalRef,
- ModalService
-} from '../../../core/services/modal.service';
+import { MODAL_DATA, ModalRef, ModalService } from '../../../core/services/modal.service';
import { ModalHostComponent } from './modal-host.component';
@Component({
@@ -31,7 +16,7 @@ import { ModalHostComponent } from './modal-host.component';
{{ data?.title }}
- `
+ `,
})
class ModalContentTestComponent {
readonly data = inject<{ title: string } | null>(MODAL_DATA);
@@ -48,10 +33,7 @@ describe('ModalHostComponent', () => {
beforeAll(() => {
try {
- getTestBed().initTestEnvironment(
- BrowserTestingModule,
- platformBrowserTesting()
- );
+ getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting());
} catch {
// Test environment may already be initialized by another setup entrypoint.
}
@@ -59,7 +41,7 @@ describe('ModalHostComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
- imports: [ModalHostComponent]
+ imports: [ModalHostComponent],
}).compileComponents();
service = TestBed.inject(ModalService);
@@ -68,6 +50,7 @@ describe('ModalHostComponent', () => {
afterEach(() => {
doc.body.style.overflow = '';
+ doc.body.style.paddingRight = '';
TestBed.resetTestingModule();
});
@@ -84,7 +67,7 @@ describe('ModalHostComponent', () => {
service.open(ModalContentTestComponent, {
title: 'Editar producto',
- data: { title: 'Contenido del modal' }
+ data: { title: 'Contenido del modal' },
});
fixture.detectChanges();
@@ -99,27 +82,30 @@ describe('ModalHostComponent', () => {
it('closes with a result from the child component', () => {
const fixture = TestBed.createComponent(ModalHostComponent);
const ref = service.open(ModalContentTestComponent, {
- data: { title: 'Cerrar' }
+ data: { title: 'Cerrar' },
});
const closedSpy = vi.fn();
ref.afterClosed$.subscribe(closedSpy);
fixture.detectChanges();
- const closeButton = fixture.nativeElement.querySelector('.modal-test-close') as HTMLButtonElement;
+ const closeButton = fixture.nativeElement.querySelector(
+ '.modal-test-close',
+ ) as HTMLButtonElement;
closeButton.click();
fixture.detectChanges();
expect(closedSpy).toHaveBeenCalledWith('accepted');
expect(service.activeModal()).toBeNull();
expect(doc.body.style.overflow).toBe('');
+ expect(doc.body.style.paddingRight).toBe('');
});
it('closes on backdrop click when enabled', () => {
const fixture = TestBed.createComponent(ModalHostComponent);
const ref = service.open(ModalContentTestComponent, {
data: { title: 'Backdrop' },
- closeOnBackdrop: true
+ closeOnBackdrop: true,
});
fixture.detectChanges();
@@ -136,7 +122,7 @@ describe('ModalHostComponent', () => {
const fixture = TestBed.createComponent(ModalHostComponent);
const ref = service.open(ModalContentTestComponent, {
data: { title: 'Persistente' },
- closeOnBackdrop: false
+ closeOnBackdrop: false,
});
fixture.detectChanges();
@@ -152,7 +138,7 @@ describe('ModalHostComponent', () => {
const fixture = TestBed.createComponent(ModalHostComponent);
const ref = service.open(ModalContentTestComponent, {
data: { title: 'Escape' },
- closeOnEscape: true
+ closeOnEscape: true,
});
fixture.detectChanges();
@@ -167,7 +153,7 @@ describe('ModalHostComponent', () => {
const fixture = TestBed.createComponent(ModalHostComponent);
const ref = service.open(ModalContentTestComponent, {
data: { title: 'No Escape' },
- closeOnEscape: false
+ closeOnEscape: false,
});
fixture.detectChanges();
@@ -181,12 +167,13 @@ describe('ModalHostComponent', () => {
const fixture = TestBed.createComponent(ModalHostComponent);
const ref = service.open(ModalContentTestComponent, {
title: 'Con cierre',
- data: { title: 'Boton' }
+ data: { title: 'Boton' },
});
fixture.detectChanges();
- const closeButton = fixture.debugElement.query(By.css('.btn-close')).nativeElement as HTMLButtonElement;
+ const closeButton = fixture.debugElement.query(By.css('.btn-close'))
+ .nativeElement as HTMLButtonElement;
closeButton.click();
fixture.detectChanges();
diff --git a/src/app/shared/components/modal-host/modal-host.component.ts b/src/app/shared/components/modal-host/modal-host.component.ts
index 7bc840e..a85e7e9 100644
--- a/src/app/shared/components/modal-host/modal-host.component.ts
+++ b/src/app/shared/components/modal-host/modal-host.component.ts
@@ -7,21 +7,17 @@ import {
computed,
effect,
inject,
- viewChild
+ viewChild,
} from '@angular/core';
-import {
- MODAL_DATA,
- ModalRef,
- ModalService
-} from '../../../core/services/modal.service';
+import { MODAL_DATA, ModalRef, ModalService } from '../../../core/services/modal.service';
import { ModalShellComponent } from '../modal-shell/modal-shell.component';
@Component({
selector: 'app-modal-host',
imports: [NgComponentOutlet, ModalShellComponent],
templateUrl: './modal-host.component.html',
- changeDetection: ChangeDetectionStrategy.OnPush
+ changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ModalHostComponent {
private readonly modalService = inject(ModalService);
@@ -42,9 +38,9 @@ export class ModalHostComponent {
return Injector.create({
providers: [
{ provide: ModalRef, useValue: modal.ref },
- { provide: MODAL_DATA, useValue: modal.config.data ?? null }
+ { provide: MODAL_DATA, useValue: modal.config.data ?? null },
],
- parent: this.injector
+ parent: this.injector,
});
});
@@ -58,6 +54,18 @@ export class ModalHostComponent {
const body = this.document.body;
const previousOverflow = body.style.overflow;
+ const previousPaddingRight = body.style.paddingRight;
+ const view = this.document.defaultView;
+ const scrollbarWidth = view
+ ? Math.max(0, view.innerWidth - this.document.documentElement.clientWidth)
+ : 0;
+
+ if (scrollbarWidth > 0 && view) {
+ const currentPaddingRight =
+ Number.parseFloat(view.getComputedStyle(body).paddingRight) || 0;
+ body.style.paddingRight = `${currentPaddingRight + scrollbarWidth}px`;
+ }
+
body.style.overflow = 'hidden';
const onKeyDown = (event: KeyboardEvent) => {
@@ -75,6 +83,7 @@ export class ModalHostComponent {
onCleanup(() => {
this.document.removeEventListener('keydown', onKeyDown);
body.style.overflow = previousOverflow;
+ body.style.paddingRight = previousPaddingRight;
});
});
}
diff --git a/src/app/shared/components/modal-shell/modal-shell.component.scss b/src/app/shared/components/modal-shell/modal-shell.component.scss
index d5f80b8..d016d61 100644
--- a/src/app/shared/components/modal-shell/modal-shell.component.scss
+++ b/src/app/shared/components/modal-shell/modal-shell.component.scss
@@ -10,8 +10,7 @@
align-items: center;
justify-content: center;
padding: 1rem;
- background: rgba(16, 18, 22, 0.48);
- backdrop-filter: blur(2px);
+ background: rgba(16, 18, 22, 0.56);
}
.modal-shell__dialog {