Skip to content

Commit

Permalink
fix(input-date-picker, input-time-picker, modal, sheet): closes on es…
Browse files Browse the repository at this point in the history
…cape when focusTrap is disabled (#10578)

**Related Issue:** #10522

## Summary
Close on `Escape` works when `focusTrap` is disabled.
  • Loading branch information
Elijbet authored Nov 27, 2024
1 parent 3e48106 commit 5acda5b
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,36 @@ describe("calcite-input-date-picker", () => {
});
});

describe("focusTrap", () => {
it("closes when Escape key is pressed and focusTrapDisabled=true", async () => {
const page = await newE2EPage();
await page.setContent(
html` <calcite-input-date-picker value="2000-11-27" focus-trap-disabled></calcite-input-date-picker>`,
);
await skipAnimations(page);
await page.waitForChanges();

const inputDatePicker = await page.find("calcite-input-date-picker");
let calendar = await page.find(`calcite-input-date-picker >>> .${CSS.calendarWrapper}`);

expect(await calendar.isVisible()).toBe(false);

await inputDatePicker.callMethod("setFocus");
await page.waitForChanges();
await page.keyboard.press("ArrowDown");
await page.waitForChanges();
calendar = await page.find(`calcite-input-date-picker >>> .${CSS.calendarWrapper}`);

expect(await calendar.isVisible()).toBe(true);

await page.keyboard.press("Escape");
await page.waitForChanges();
calendar = await page.find(`calcite-input-date-picker >>> .${CSS.calendarWrapper}`);

expect(await calendar.isVisible()).toBe(false);
});
});

describe("close after selection", () => {
it("should close the date picker after selecting a date", async () => {
const page = await newE2EPage();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ export class InputDatePicker
this.open = true;
this.focusOnOpen = true;
event.preventDefault();
} else if (key === "Escape") {
} else if (this.open && key === "Escape") {
this.open = false;
event.preventDefault();
this.restoreInputFocus(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -987,4 +987,27 @@ describe("calcite-input-time-picker", () => {
expect(await popoverPositionContainer.isVisible()).toBe(false);
});
});

it("closes when Escape key is pressed and focusTrapDisabled=true", async () => {
const page = await newE2EPage();
await page.setContent(html` <calcite-input-time-picker focus-trap-disabled></calcite-input-time-picker>`);
await skipAnimations(page);
await page.waitForChanges();
const inputTimePicker = await page.find("calcite-input-time-picker");
let popover = await page.find("calcite-input-time-picker >>> calcite-popover");

await inputTimePicker.callMethod("setFocus");
await page.waitForChanges();
await page.keyboard.press("ArrowDown");
await page.waitForChanges();
popover = await page.find("calcite-input-time-picker >>> calcite-popover");

expect(await popover.getProperty("open")).toBe(true);

await page.keyboard.press("Escape");
await page.waitForChanges();
popover = await page.find("calcite-input-time-picker >>> calcite-popover");

expect(await popover.getProperty("open")).toBe(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,9 @@ export class InputTimePicker
} else if (key === "ArrowDown") {
this.open = true;
event.preventDefault();
} else if (this.open && this.focusTrapDisabled && key === "Escape") {
this.open = false;
event.preventDefault();
}
}

Expand Down
16 changes: 16 additions & 0 deletions packages/calcite-components/src/components/modal/modal.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,22 @@ describe("calcite-modal", () => {
expect(await modal.isVisible()).toBe(true);
});

it("closes when Escape key is pressed and focusTrapDisabled=true", async () => {
const page = await newE2EPage();
await page.setContent(`<calcite-modal focus-trap-disabled></calcite-modal>`);
await skipAnimations(page);
const modal = await page.find("calcite-modal");

modal.setProperty("open", true);
await page.waitForChanges();
expect(await modal.isVisible()).toBe(true);

await page.keyboard.press("Escape");
await page.waitForChanges();
expect(await modal.isVisible()).toBe(false);
expect(await modal.getProperty("open")).toBe(false);
});

it("closes when Escape key is pressed and modal is open on page load", async () => {
const page = await newE2EPage();
await page.setContent(`<calcite-modal open></calcite-modal>`);
Expand Down
20 changes: 20 additions & 0 deletions packages/calcite-components/src/components/modal/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ export class Modal

// #region Lifecycle

constructor() {
super();
this.listen("keydown", this.keyDownHandler);
}

override connectedCallback(): void {
this.mutationObserver?.observe(this.el, { childList: true, subtree: true });
this.cssVarObserver?.observe(this.el, { attributeFilter: ["style"] });
Expand Down Expand Up @@ -329,6 +334,21 @@ export class Modal

// #region Private Methods

private keyDownHandler = (event: KeyboardEvent): void => {
const { defaultPrevented, key } = event;

if (
!defaultPrevented &&
this.focusTrapDisabled &&
this.open &&
!this.escapeDisabled &&
key === "Escape"
) {
event.preventDefault();
this.open = false;
}
};

private handleFocusTrapDisabled(focusTrapDisabled: boolean): void {
if (!this.open) {
return;
Expand Down
27 changes: 27 additions & 0 deletions packages/calcite-components/src/components/sheet/sheet.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,33 @@ describe("calcite-sheet properties", () => {
expect(await sheet.isVisible()).toBe(true);
});

it("closes when Escape key is pressed and focusTrapDisabled=true", async () => {
const page = await newE2EPage();
await page.setContent(
html`<calcite-sheet open label="hello world" focus-trap-disabled
><calcite-panel heading="Ultrices neque"
><p>Lorem ipsum dolor sit amet.</p>
<calcite-button slot="footer" width="half">tincidunt lobortis</calcite-button>
</calcite-panel></calcite-sheet
>`,
);
const sheet = await page.find("calcite-sheet");
sheet.setProperty("open", true);
await page.waitForChanges();

await page.keyboard.press("Tab");
await page.waitForChanges();

expect(await sheet.isVisible()).toBe(true);
expect(await sheet.getProperty("open")).toBe(true);

await page.keyboard.press("Escape");
await page.waitForChanges();

expect(await sheet.isVisible()).toBe(false);
expect(await sheet.getProperty("open")).toBe(false);
});

it("should close when the scrim is clicked", async () => {
const page = await newE2EPage();
await page.setContent(`<calcite-sheet ></calcite-sheet>`);
Expand Down
20 changes: 20 additions & 0 deletions packages/calcite-components/src/components/sheet/sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ export class Sheet

// #region Lifecycle

constructor() {
super();
this.listen("keydown", this.keyDownHandler);
}

override connectedCallback(): void {
this.mutationObserver?.observe(this.el, { childList: true, subtree: true });
connectFocusTrap(this, {
Expand Down Expand Up @@ -259,6 +264,21 @@ export class Sheet

// #region Private Methods

private keyDownHandler = (event: KeyboardEvent): void => {
const { defaultPrevented, key } = event;

if (
!defaultPrevented &&
!this.escapeDisabled &&
this.focusTrapDisabled &&
this.open &&
key === "Escape"
) {
event.preventDefault();
this.open = false;
}
};

private handleFocusTrapDisabled(focusTrapDisabled: boolean): void {
if (!this.open) {
return;
Expand Down

0 comments on commit 5acda5b

Please sign in to comment.