From cc0daef254d70276c2b5e093944ea2630e24def1 Mon Sep 17 00:00:00 2001
From: Cory LaViska <cory@abeautifulsite.net>
Date: Wed, 25 Nov 2020 09:26:01 -0500
Subject: [PATCH] Prevent sl-hide from firing twice; fixes #275

---
 docs/getting-started/changelog.md |  1 +
 src/components/dialog/dialog.tsx  | 12 ++++++++----
 src/components/drawer/drawer.tsx  | 12 ++++++++----
 3 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/docs/getting-started/changelog.md b/docs/getting-started/changelog.md
index c0572d58..aa089437 100644
--- a/docs/getting-started/changelog.md
+++ b/docs/getting-started/changelog.md
@@ -19,6 +19,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
 - Added experimental `sl-theme` utility and updated theming documentation
 - Fixed a bug where `sl-menu-item` wouldn't render properly in the dark theme
 - Fixed a bug where `sl-select` would show an autocomplete menu
+- Fixed a bug where `sl-dialog` and `sl-drawer` would emit the `sl-hide` event twice [#275](https://github.com/shoelace-style/shoelace/issues/275)
 - Improved placeholder contrast in dark theme
 - Updated to Boostrap Icons 1.1.0
 - Updated to Stencil 2.3.0
diff --git a/src/components/dialog/dialog.tsx b/src/components/dialog/dialog.tsx
index 2332bca8..de5e925d 100644
--- a/src/components/dialog/dialog.tsx
+++ b/src/components/dialog/dialog.tsx
@@ -33,6 +33,8 @@ export class Dialog {
   dialog: HTMLElement;
   modal: Modal;
   panel: HTMLElement;
+  willShow = false;
+  willHide = false;
 
   @Element() host: HTMLSlDialogElement;
 
@@ -100,8 +102,7 @@ export class Dialog {
   /** Shows the dialog */
   @Method()
   async show() {
-    // Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
-    if (this.isVisible) {
+    if (this.willShow) {
       return;
     }
 
@@ -111,6 +112,7 @@ export class Dialog {
       return;
     }
 
+    this.willShow = true;
     this.isVisible = true;
     this.open = true;
     this.modal.activate();
@@ -121,8 +123,7 @@ export class Dialog {
   /** Hides the dialog */
   @Method()
   async hide() {
-    // Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
-    if (!this.isVisible) {
+    if (this.willHide) {
       return;
     }
 
@@ -132,6 +133,7 @@ export class Dialog {
       return;
     }
 
+    this.willHide = true;
     this.open = false;
     this.modal.deactivate();
 
@@ -166,6 +168,8 @@ export class Dialog {
     // Ensure we only emit one event when the target element is no longer visible
     if (event.propertyName === 'opacity' && target.classList.contains('dialog__panel')) {
       this.isVisible = this.open;
+      this.willShow = false;
+      this.willHide = false;
       this.open ? this.slAfterShow.emit() : this.slAfterHide.emit();
 
       if (this.open) {
diff --git a/src/components/drawer/drawer.tsx b/src/components/drawer/drawer.tsx
index 2d465c2d..4a530950 100644
--- a/src/components/drawer/drawer.tsx
+++ b/src/components/drawer/drawer.tsx
@@ -32,6 +32,8 @@ export class Drawer {
   drawer: HTMLElement;
   modal: Modal;
   panel: HTMLElement;
+  willShow = false;
+  willHide = false;
 
   @Element() host: HTMLSlDrawerElement;
 
@@ -108,8 +110,7 @@ export class Drawer {
   /** Shows the drawer */
   @Method()
   async show() {
-    // Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
-    if (this.isVisible) {
+    if (this.willShow) {
       return;
     }
 
@@ -119,6 +120,7 @@ export class Drawer {
       return;
     }
 
+    this.willShow = true;
     this.isVisible = true;
     this.open = true;
 
@@ -132,8 +134,7 @@ export class Drawer {
   /** Hides the drawer */
   @Method()
   async hide() {
-    // Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
-    if (!this.isVisible) {
+    if (this.willHide) {
       return;
     }
 
@@ -143,6 +144,7 @@ export class Drawer {
       return;
     }
 
+    this.willHide = true;
     this.open = false;
     this.modal.deactivate();
 
@@ -177,6 +179,8 @@ export class Drawer {
     // Ensure we only emit one event when the target element is no longer visible
     if (event.propertyName === 'transform' && target.classList.contains('drawer__panel')) {
       this.isVisible = this.open;
+      this.willShow = false;
+      this.willHide = false;
       this.open ? this.slAfterShow.emit() : this.slAfterHide.emit();
 
       if (this.open) {