Skip to content
10 changes: 4 additions & 6 deletions packages/calcite-components/src/components/dialog/dialog.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,6 @@ describe("calcite-dialog", () => {

const messageOverrides = { close: "shut the front door" };

await page.$eval("calcite-dialog", (el: Dialog["el"]) => (el.beforeClose = (window as TestWindow).beforeClose));
dialog.setProperty("closeDisabled", true);
dialog.setProperty("loading", true);
dialog.setProperty("menuOpen", true);
Expand All @@ -304,7 +303,6 @@ describe("calcite-dialog", () => {
expect(await panel.getProperty("icon")).toBe("x");
expect(await panel.getProperty("iconFlipRtl")).toBe(true);
expect((await panel.getProperty("messageOverrides")).close).toBe(messageOverrides.close);
expect(await panel.getProperty("beforeClose")).toBeDefined();
});

it("outsideCloseDisabled", async () => {
Expand Down Expand Up @@ -470,7 +468,7 @@ describe("calcite-dialog", () => {
const closeButton = await page.find(`calcite-dialog >>> calcite-panel >>> #${PanelIDS.close}`);
await closeButton.click();
await page.waitForChanges();
expect(mockCallBack).toHaveBeenCalledTimes(2);
expect(mockCallBack).toHaveBeenCalledTimes(1);
expect(await page.find(`calcite-dialog >>> .${CSS.containerOpen}`)).toBeNull();
});

Expand Down Expand Up @@ -499,7 +497,7 @@ describe("calcite-dialog", () => {
await page.waitForChanges();
await closeEventSpy;

expect(mockCallBack).toHaveBeenCalledTimes(2);
expect(mockCallBack).toHaveBeenCalledTimes(1);
expect(await page.find(`calcite-dialog >>> .${CSS.containerOpen}`)).toBeNull();
});

Expand All @@ -522,7 +520,7 @@ describe("calcite-dialog", () => {
dialog.removeAttribute("open");
await page.waitForChanges();

expect(mockCallBack).toHaveBeenCalledTimes(2);
expect(mockCallBack).toHaveBeenCalledTimes(1);
expect(await page.find(`calcite-dialog >>> .${CSS.containerOpen}`)).toBeNull();
});

Expand All @@ -541,7 +539,7 @@ describe("calcite-dialog", () => {
dialog.setProperty("open", false);
await page.waitForChanges();

expect(mockCallBack).toHaveBeenCalledTimes(2);
expect(mockCallBack).toHaveBeenCalledTimes(1);
});

it("should remain open with rejected 'beforeClose' promise'", async () => {
Expand Down
17 changes: 16 additions & 1 deletion packages/calcite-components/src/components/dialog/dialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,22 @@ calcite-panel {
}

.panel {
@apply rounded;
@apply invisible
rounded
opacity-0;

transition:
visibility 0ms linear var(--calcite-internal-animation-timing-slow),
opacity var(--calcite-internal-animation-timing-slow) $easing-function;
}

.container--open .panel {
@apply visible
opacity-100;

transition:
visibility 0ms linear,
opacity var(--calcite-internal-animation-timing-slow) $easing-function;
}

.container--open {
Expand Down
55 changes: 17 additions & 38 deletions packages/calcite-components/src/components/dialog/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ export class Dialog extends LitElement implements OpenCloseComponent {

usePreventDocumentScroll = usePreventDocumentScroll()(this);

private ignoreOpenChange = false;

private interaction: Interactable;

private mutationObserver: MutationObserver = createObserver("mutation", () =>
Expand Down Expand Up @@ -202,11 +200,10 @@ export class Dialog extends LitElement implements OpenCloseComponent {
get open(): boolean {
return this._open;
}
set open(open: boolean) {
const oldOpen = this._open;
if (open !== oldOpen) {
this._open = open;
this.toggleDialog(open);
set open(value: boolean) {
const oldValue = this._open;
if (value !== oldValue) {
this.setOpenState(value);
}
}

Expand Down Expand Up @@ -386,16 +383,22 @@ export class Dialog extends LitElement implements OpenCloseComponent {
this.calciteDialogClose.emit();
}

private toggleDialog(value: boolean): void {
if (this.ignoreOpenChange) {
return;
private async setOpenState(value: boolean): Promise<void> {
if (this.beforeClose && !value) {
try {
await this.beforeClose?.();
} catch {
return;
}
}

this._open = value;

if (value) {
this.openDialog();
} else {
this.closeDialog();
await this.componentOnReady();
}

this.opened = value;
}

private handleOpenedChange(value: boolean): void {
Expand Down Expand Up @@ -713,6 +716,7 @@ export class Dialog extends LitElement implements OpenCloseComponent {
return;
}

event.preventDefault();
event.stopPropagation();
this.open = false;
}
Expand All @@ -723,11 +727,6 @@ export class Dialog extends LitElement implements OpenCloseComponent {
}
}

private async openDialog(): Promise<void> {
await this.componentOnReady();
this.opened = true;
}

private handleOutsideClose(): void {
if (this.outsideCloseDisabled) {
return;
Expand All @@ -736,24 +735,6 @@ export class Dialog extends LitElement implements OpenCloseComponent {
this.open = false;
}

private async closeDialog(): Promise<void> {
if (this.beforeClose) {
try {
await this.beforeClose();
} catch {
// close prevented
requestAnimationFrame(() => {
this.ignoreOpenChange = true;
this.open = true;
this.ignoreOpenChange = false;
});
return;
}
}

this.opened = false;
}

private handleMutationObserver(): void {
this.focusTrap.updateContainerElements();
}
Expand Down Expand Up @@ -795,10 +776,8 @@ export class Dialog extends LitElement implements OpenCloseComponent {
<slot name={SLOTS.customContent}>
<slot name={SLOTS.content}>
<calcite-panel
beforeClose={this.beforeClose}
class={CSS.panel}
closable={!this.closeDisabled}
closed={!opened}
description={description}
heading={heading}
headingLevel={this.headingLevel}
Expand Down
43 changes: 43 additions & 0 deletions packages/calcite-components/src/components/panel/panel.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ type TestWindow = GlobalTestProps<{
beforeClose: () => Promise<void>;
}>;

type TestPanelWindow = GlobalTestProps<{
lastEventCancelable: boolean;
lastEventDefaultPrevented: boolean;
calledTimes: number;
}>;

const panelTemplate = (scrollable = false) =>
html`<div style="height: 200px; display: flex">
<calcite-panel>
Expand Down Expand Up @@ -360,6 +366,43 @@ describe("calcite-panel", () => {
expect(calcitePanelClose).toHaveReceivedEventTimes(1);
});

it("close event can be cancelled", async () => {
const page = await newProgrammaticE2EPage();
await page.evaluate(() => {
(window as TestPanelWindow).calledTimes = 0;

const panel = document.createElement("calcite-panel");
panel.heading = "Hello World";
panel.closable = true;
panel.innerText = "Hello World";

panel.addEventListener("calcitePanelClose", (event) => {
event.preventDefault();
// needed to work around event spy limitation - details are captured before event is canceled
(window as TestPanelWindow).lastEventCancelable = event.cancelable;
Comment thread
driskull marked this conversation as resolved.
(window as TestPanelWindow).lastEventDefaultPrevented = event.defaultPrevented;
(window as TestPanelWindow).calledTimes++;
});

document.body.append(panel);
});
await page.waitForChanges();

const panel = await page.find("calcite-panel");
const closeButton = await page.find(`calcite-panel >>> #${IDS.close}`);
await closeButton.click();
await page.waitForChanges();

const calledTimes = await page.evaluate(() => (window as TestPanelWindow).calledTimes);
const lastEventCancelable = await page.evaluate(() => (window as TestPanelWindow).lastEventCancelable);
const lastEventDefaultPrevented = await page.evaluate(() => (window as TestPanelWindow).lastEventDefaultPrevented);

expect(calledTimes).toBe(1);
expect(lastEventCancelable).toBe(true);
expect(lastEventDefaultPrevented).toBe(true);
expect(await panel.getProperty("closed")).toBe(false);
});

it("toggle event should fire when collapsed", async () => {
const page = await newE2EPage();
await page.setContent("<calcite-panel collapsible>Hello World!</calcite-panel>");
Expand Down
Loading
Loading