From 76cd19d126aee6de753c42a3f37f19d382ff052a Mon Sep 17 00:00:00 2001 From: Emma Segal-Grossman Date: Tue, 14 May 2024 15:21:10 -0400 Subject: [PATCH] [Bug] Collection detail: only update dialog state on close event if close event originates from dialog (#1793) Closes https://github.com/webrecorder/browsertrix/issues/1553 ## Changes Adds a check on `sl-hide` events to ensure that only the events originating from the elements we want to listen to are acted on --- frontend/src/components/ui/dialog.ts | 28 ++++++++++++++++++++- frontend/src/pages/org/collection-detail.ts | 4 +-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/ui/dialog.ts b/frontend/src/components/ui/dialog.ts index 17972851..d5b98efb 100644 --- a/frontend/src/components/ui/dialog.ts +++ b/frontend/src/components/ui/dialog.ts @@ -1,7 +1,11 @@ import SlDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.js"; import dialogStyles from "@shoelace-style/shoelace/dist/components/dialog/dialog.styles.js"; import { css } from "lit"; -import { customElement, queryAssignedElements } from "lit/decorators.js"; +import { + customElement, + property, + queryAssignedElements, +} from "lit/decorators.js"; /** * with custom CSS @@ -59,6 +63,28 @@ export class Dialog extends SlDialog { @queryAssignedElements({ selector: "form", flatten: true }) readonly formElems!: HTMLFormElement[]; + @property({ type: Boolean }) + reEmitInnerSlHideEvents = false; + + // Because both `sl-tooltip` and `sl-dialog` elements use "sl-hide", anything + // that listens for "sl-hide" events receives them from tooltips inside the + // dialog as well as from the dialog itself, which can lead to mousing out of + // a tooltip causing the dialog to close (if it's used as a fully-controlled + // component). This prevents that by catching any "sl-hide" events, and + // optionally re-emitting them as "sl-inner-hide" events + protected createRenderRoot() { + const root = super.createRenderRoot(); + root.addEventListener("sl-hide", (event: Event) => { + if (!(event.target instanceof Dialog)) { + event.stopPropagation(); + if (this.reEmitInnerSlHideEvents) { + this.dispatchEvent(new CustomEvent("sl-inner-hide", { ...event })); + } + } + }); + return root; + } + /** * Submit form using external buttons to bypass * incorrect `getRootNode` in Chrome. diff --git a/frontend/src/pages/org/collection-detail.ts b/frontend/src/pages/org/collection-detail.ts index 1bb4e52a..21222d29 100644 --- a/frontend/src/pages/org/collection-detail.ts +++ b/frontend/src/pages/org/collection-detail.ts @@ -176,8 +176,8 @@ export class CollectionDetail extends LiteElement {
${this.renderDescription()}
(this.openDialogName = undefined)} > ${msg(