Skip to content

Commit

Permalink
fix(alert): pause auto-close alert when link focused (#9503)
Browse files Browse the repository at this point in the history
**Related Issue:** #5960 

## Summary
Paused auto close when the focus is in the link or close buton or when the mouse is hovered over the alert dialog.
  • Loading branch information
josercarcamo committed Jun 5, 2024
1 parent 4faa160 commit fa9a829
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 4 deletions.
14 changes: 14 additions & 0 deletions packages/calcite-components/src/components/alert/alert.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,20 @@ describe("calcite-alert", () => {
await page.waitForTimeout(DURATIONS.medium + animationDurationInMs);
await page.waitForSelector("#alert", { visible: false });
});

it("pauses on focus and resumes on blur", async () => {
await button.click();
expect(await alert.isVisible()).toBe(true);
expect(await alert.getProperty("autoCloseDuration")).toEqual("medium");
expect(playState).toEqual("running");
buttonClose = await page.find(`#alert >>> .${CSS.close}`);
buttonClose.focus();
await page.waitForTimeout(DURATIONS.medium);
expect(await alert.isVisible()).toBe(true);
await button.focus();
await page.waitForTimeout(DURATIONS.medium + animationDurationInMs);
await page.waitForSelector("#alert", { visible: false });
});
});

describe("translation support", () => {
Expand Down
7 changes: 6 additions & 1 deletion packages/calcite-components/src/components/alert/alert.scss
Original file line number Diff line number Diff line change
Expand Up @@ -293,11 +293,16 @@ $alertDurations:
:host([auto-close-duration="#{$name}"]) .dismiss-progress:after {
animation: dismissProgress $duration ease-out;
}
:host(:hover[auto-close-duration="#{$name}"]) .dismiss-progress:after {
:host(:hover[auto-close-duration="#{$name}"]) .dismiss-progress:after,
:host(:focus[auto-close-duration="#{$name}"]) .dismiss-progress:after {
animation-play-state: paused;
}
}

.container.focused .dismiss-progress:after {
animation-play-state: paused;
}

@keyframes dismissProgress {
0% {
@apply w-0 opacity-75;
Expand Down
43 changes: 40 additions & 3 deletions packages/calcite-components/src/components/alert/alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export class Alert implements OpenCloseComponent, LoadableComponent, T9nComponen
}),
);
window.clearTimeout(this.autoCloseTimeoutId);
this.autoCloseTimeoutId = null;
window.clearTimeout(this.queueTimeout);
disconnectLocalized(this);
disconnectMessages(this);
Expand All @@ -226,13 +227,18 @@ export class Alert implements OpenCloseComponent, LoadableComponent, T9nComponen
[CSS.containerQueued]: queued,
[`${CSS.container}--${placement}`]: true,
[CSS.containerSlottedInShell]: this.slottedInShell,
[CSS.focused]: this.keyBoardFocus,
}}
onPointerEnter={this.autoClose && this.autoCloseTimeoutId ? this.handleMouseOver : null}
onPointerLeave={this.autoClose && this.autoCloseTimeoutId ? this.handleMouseLeave : null}
onPointerLeave={this.autoClose ? this.handleMouseLeave : null}
ref={this.setTransitionEl}
>
{effectiveIcon && this.renderIcon(effectiveIcon)}
<div class={CSS.textContainer}>
<div
class={CSS.textContainer}
onFocusin={this.autoClose && this.autoCloseTimeoutId ? this.handleKeyBoardFocus : null}
onFocusout={this.autoClose ? this.handleKeyBoardBlur : null}
>
<slot name={SLOTS.title} />
<slot name={SLOTS.message} />
<slot name={SLOTS.link} />
Expand All @@ -246,13 +252,27 @@ export class Alert implements OpenCloseComponent, LoadableComponent, T9nComponen
);
}

private handleKeyBoardFocus = (): void => {
this.keyBoardFocus = true;
this.handleFocus();
};

private handleKeyBoardBlur = (): void => {
this.keyBoardFocus = false;
if (!this.mouseFocus) {
this.handleBlur();
}
};

private renderCloseButton(): VNode {
return (
<button
aria-label={this.messages.close}
class={CSS.close}
key="close"
onClick={this.closeAlert}
onFocusin={this.autoClose ? this.handleKeyBoardFocus : null}
onFocusout={this.autoClose ? this.handleKeyBoardBlur : null}
ref={(el) => (this.closeButton = el)}
type="button"
>
Expand Down Expand Up @@ -429,6 +449,8 @@ export class Alert implements OpenCloseComponent, LoadableComponent, T9nComponen
/** is the alert queued */
@State() queued = false;

@State() keyBoardFocus = false;

private autoCloseTimeoutId: number = null;

private closeButton: HTMLButtonElement;
Expand All @@ -447,6 +469,8 @@ export class Alert implements OpenCloseComponent, LoadableComponent, T9nComponen

transitionEl: HTMLDivElement;

mouseFocus: boolean;

//--------------------------------------------------------------------------
//
// Private Methods
Expand Down Expand Up @@ -510,12 +534,25 @@ export class Alert implements OpenCloseComponent, LoadableComponent, T9nComponen
};

private handleMouseOver = (): void => {
this.mouseFocus = true;
this.handleFocus();
};

private handleMouseLeave = (): void => {
this.mouseFocus = false;
if (!this.keyBoardFocus) {
this.handleBlur();
}
};

private handleFocus = (): void => {
window.clearTimeout(this.autoCloseTimeoutId);
this.autoCloseTimeoutId = null;
this.totalOpenTime = Date.now() - this.initialOpenTime;
this.lastMouseOverBegin = Date.now();
};

private handleMouseLeave = (): void => {
private handleBlur = (): void => {
const hoverDuration = Date.now() - this.lastMouseOverBegin;
const timeRemaining =
DURATIONS[this.autoCloseDuration] - this.totalOpenTime + this.totalHoverTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ export const CSS = {
queueCount: "queue-count",
queueCountActive: "queue-count--active",
textContainer: "text-container",
focused: "focused",
};

0 comments on commit fa9a829

Please sign in to comment.