diff --git a/src/main/frontend/mixins.cljs b/src/main/frontend/mixins.cljs index 0bababacad..75a0a6183c 100644 --- a/src/main/frontend/mixins.cljs +++ b/src/main/frontend/mixins.cljs @@ -52,15 +52,16 @@ ;; (dissoc state name))}) (defn hide-when-esc-or-outside - [state & {:keys [on-hide node visibilitychange?]}] + [state & {:keys [on-hide node visibilitychange? outside?]}] (try (let [dom-node (rum/dom-node state)] (when-let [dom-node (or node dom-node)] - (listen state js/window "mousedown" - (fn [e] - ;; If the click target is outside of current node - (when-not (dom/contains dom-node (.. e -target)) - (on-hide state e :click)))) + (or (false? outside?) + (listen state js/window "mousedown" + (fn [e] + ;; If the click target is outside of current node + (when-not (dom/contains dom-node (.. e -target)) + (on-hide state e :click))))) (listen state js/window "keydown" (fn [e] (case (.-keyCode e) diff --git a/src/main/frontend/ui.cljs b/src/main/frontend/ui.cljs index c68deb85e7..cb4d10c89d 100644 --- a/src/main/frontend/ui.cljs +++ b/src/main/frontend/ui.cljs @@ -414,7 +414,7 @@ (defonce modal-show? (atom false)) (rum/defc modal-overlay [state] - [:div.fixed.inset-0.transition-opacity + [:div.ui__modal-overlay {:class (case state "entering" "ease-out duration-300 opacity-0" "entered" "ease-out duration-300 opacity-100" @@ -423,15 +423,15 @@ [:div.absolute.inset-0.bg-gray-500.opacity-75]]) (rum/defc modal-panel - [panel-content state close-fn] - [:div.relative.bg-white.rounded-md.px-4.pt-5.pb-4.overflow-hidden.shadow-xl.transform.transition-all.sm:min-w-lg.sm:p-6 - {:class (case state + [panel-content transition-state close-fn] + [:div.ui__modal-panel.transform.transition-all.sm:min-w-lg.sm.p-6 + {:class (case transition-state "entering" "ease-out duration-300 opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" "entered" "ease-out duration-300 opacity-100 translate-y-0 sm:scale-100" "exiting" "ease-in duration-200 opacity-100 translate-y-0 sm:scale-100" "exited" "ease-in duration-200 opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95")} [:div.absolute.top-0.right-0.pt-2.pr-2 - [:button.text-gray-400.hover:text-gray-500.focus:outline-none.focus:text-gray-500.transition.ease-in-out.duration-150 + [:button.ui__modal-close {:aria-label "Close" :type "button" :on-click (fn [] (apply (or (gobj/get close-fn "user-close") close-fn) []))} @@ -446,12 +446,20 @@ (panel-content close-fn)]) (rum/defc modal < rum/reactive + (mixins/event-mixin + (fn [state] + (mixins/hide-when-esc-or-outside + state + :on-hide (fn [] + (-> (.querySelector (rum/dom-node state) "button.ui__modal-close") + (.click))) + :outside? false))) [] (let [modal-panel-content (state/sub :modal/panel-content) show? (boolean modal-panel-content) close-fn #(state/close-modal!) modal-panel-content (or modal-panel-content (fn [close] [:div]))] - [:div.fixed.bottom-0.inset-x-0.px-4.pb-4.sm:inset-0.sm:flex.sm:items-center.sm:justify-center + [:div.ui__modal {:style {:z-index (if show? 10 -1)}} (css-transition {:in show? :timeout 0} diff --git a/src/main/frontend/ui.css b/src/main/frontend/ui.css index 169a85d407..aec1c32b13 100644 --- a/src/main/frontend/ui.css +++ b/src/main/frontend/ui.css @@ -52,6 +52,27 @@ } } +.ui__modal { + @apply fixed bottom-0 inset-x-0 + sm:inset-0 sm:flex sm:items-center sm:justify-center + px-4 pb-4; + + &-overlay { + @apply fixed inset-0 transition-opacity; + } + + &-panel { + @apply relative bg-white rounded-md px-4 pt-5 + pb-4 overflow-hidden shadow-xl; + } + + &-close { + @apply text-gray-400 hover:text-gray-500 + focus:outline-none focus:text-gray-500 + transition ease-in-out duration-150; + } +} + .ui__confirm-modal { .sublabel { display: flex;