From b3da46ac029b2b9be47b50aabb199b1ba82f9de6 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Tue, 3 Mar 2026 11:50:30 +0100 Subject: [PATCH] feat(dialog): close dialog on backdrop click MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add click handlers to the dialog component for all three targets that close the dialog when clicking the backdrop area (outside the dialog box). Uses event.target === event.currentTarget to distinguish backdrop clicks from content clicks. - :clj — inline onclick attribute - :cljs — Replicant :on {:click handler} - :squint — :on-click handler - CSS: cursor: pointer on ::backdrop for affordance --- src/ui/dialog.cljc | 16 +++++++++++++--- src/ui/dialog.css | 1 + test/ui/dialog_test.clj | 7 ++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/ui/dialog.cljc b/src/ui/dialog.cljc index c5a3da6..9c97aab 100644 --- a/src/ui/dialog.cljc +++ b/src/ui/dialog.cljc @@ -14,6 +14,9 @@ (defn dialog "Render a dialog element. + Clicking the backdrop (the area outside the dialog box) will close the + dialog automatically when opened via .showModal(). + Props: :open - boolean, whether the dialog is open :id - dialog id for targeting @@ -23,7 +26,10 @@ #?(:squint (let [classes (cond-> (dialog-classes {}) class (str " " class)) - base-attrs (merge {:class classes} + base-attrs (merge {:class classes + :on-click (fn [e] + (when (identical? (.-target e) (.-currentTarget e)) + (.close (.-currentTarget e))))} (when id {:id id}) (when open {:open true}) attrs)] @@ -32,7 +38,10 @@ :cljs (let [cls (dialog-class-list {}) classes (cond-> cls class (conj class)) - base-attrs (merge {:class classes} + base-attrs (merge {:class classes + :on {:click (fn [e] + (when (identical? (.-target e) (.-currentTarget e)) + (.close (.-currentTarget e))))}} (when id {:id id}) (when open {:open true}) attrs)] @@ -41,7 +50,8 @@ :clj (let [classes (cond-> (dialog-classes {}) class (str " " class)) - base-attrs (merge {:class classes} + base-attrs (merge {:class classes + :onclick "if(event.target===this)this.close()"} (when id {:id id}) (when open {:open true}) attrs)] diff --git a/src/ui/dialog.css b/src/ui/dialog.css index 2cdac68..451264f 100644 --- a/src/ui/dialog.css +++ b/src/ui/dialog.css @@ -21,6 +21,7 @@ .dialog::backdrop { background: rgba(0, 0, 0, 0.5); + cursor: pointer; } .dialog-header { diff --git a/test/ui/dialog_test.clj b/test/ui/dialog_test.clj index 116bd7a..30eeaed 100644 --- a/test/ui/dialog_test.clj +++ b/test/ui/dialog_test.clj @@ -15,7 +15,12 @@ (testing "open dialog has open attr" (let [result (dialog/dialog {:open true} "Content")] - (is (true? (get-in result [1 :open])))))) + (is (true? (get-in result [1 :open]))))) + + (testing "dialog has backdrop close handler" + (let [result (dialog/dialog {} "Content")] + (is (string? (get-in result [1 :onclick]))) + (is (clojure.string/includes? (get-in result [1 :onclick]) "close"))))) (deftest dialog-sections-test (testing "dialog-header renders header"