feat(dialog): close dialog on backdrop click
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
This commit is contained in:
@@ -14,6 +14,9 @@
|
|||||||
(defn dialog
|
(defn dialog
|
||||||
"Render a dialog element.
|
"Render a dialog element.
|
||||||
|
|
||||||
|
Clicking the backdrop (the area outside the dialog box) will close the
|
||||||
|
dialog automatically when opened via .showModal().
|
||||||
|
|
||||||
Props:
|
Props:
|
||||||
:open - boolean, whether the dialog is open
|
:open - boolean, whether the dialog is open
|
||||||
:id - dialog id for targeting
|
:id - dialog id for targeting
|
||||||
@@ -23,7 +26,10 @@
|
|||||||
#?(:squint
|
#?(:squint
|
||||||
(let [classes (cond-> (dialog-classes {})
|
(let [classes (cond-> (dialog-classes {})
|
||||||
class (str " " class))
|
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 id {:id id})
|
||||||
(when open {:open true})
|
(when open {:open true})
|
||||||
attrs)]
|
attrs)]
|
||||||
@@ -32,7 +38,10 @@
|
|||||||
:cljs
|
:cljs
|
||||||
(let [cls (dialog-class-list {})
|
(let [cls (dialog-class-list {})
|
||||||
classes (cond-> cls class (conj class))
|
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 id {:id id})
|
||||||
(when open {:open true})
|
(when open {:open true})
|
||||||
attrs)]
|
attrs)]
|
||||||
@@ -41,7 +50,8 @@
|
|||||||
:clj
|
:clj
|
||||||
(let [classes (cond-> (dialog-classes {})
|
(let [classes (cond-> (dialog-classes {})
|
||||||
class (str " " class))
|
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 id {:id id})
|
||||||
(when open {:open true})
|
(when open {:open true})
|
||||||
attrs)]
|
attrs)]
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
.dialog::backdrop {
|
.dialog::backdrop {
|
||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-header {
|
.dialog-header {
|
||||||
|
|||||||
@@ -15,7 +15,12 @@
|
|||||||
|
|
||||||
(testing "open dialog has open attr"
|
(testing "open dialog has open attr"
|
||||||
(let [result (dialog/dialog {:open true} "Content")]
|
(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
|
(deftest dialog-sections-test
|
||||||
(testing "dialog-header renders header"
|
(testing "dialog-header renders header"
|
||||||
|
|||||||
Reference in New Issue
Block a user