Skip to content

Instantly share code, notes, and snippets.

@Ivana-
Created August 29, 2022 15:25
Show Gist options
  • Save Ivana-/5f3f01fe50d3887808001cf8c95d989f to your computer and use it in GitHub Desktop.
Save Ivana-/5f3f01fe50d3887808001cf8c95d989f to your computer and use it in GitHub Desktop.
Toast cljs
;; toast ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- create-element-from-hiccup [hiccup-data]
(let [tmp (.createElement js/document "div")
content (rds/render-to-static-markup hiccup-data)]
(aset tmp "innerHTML" content)
(.-firstChild tmp)))
(defn- get-create-toast-container []
(let [container-id "ivana_toast_container"]
(or (.getElementById js/document container-id)
(let [container (create-element-from-hiccup
[:div {:id container-id
:style {:position :fixed
:top 0
:right 0
:left 0
:bottom 0
:margin :auto
:width "40%"
;; :min-height "40%"
:height :fit-content
:z-index 10 ;; 1
:pointer-events :none
:display :flex
:flex-direction :column ;; :column-reverse
:justify-content :center
;; :border "3px solid red"
}}])]
(.appendChild (.-body js/document) container)
container))))
(defn- toast-animate-show [elem]
(doto (.-style elem)
(aset "opacity" 1)
(aset "height" "4rem")))
(defn- toast-animate-hide [elem]
(doto (.-style elem)
(aset "opacity" 0)
(aset "height" 0)))
(defn toast [{:keys [content timeout status]}]
(let [container (get-create-toast-container)
transition-time-ms (js/Math.floor (/ timeout 4))
transition-time-ms (min 500 transition-time-ms)
toast-elem (create-element-from-hiccup
[:div {:style {:margin-bottom "4px"
:padding-left "20px"
:padding-right "20px"
:border-radius "10px"
:background-color (get {:info "#b3ffb3"
:error "#f6cdcd"}
(or status :info))
:overflow :hidden
:display :flex
:flex-direction :column
:justify-content :center
;; values to transform
:opacity 0
:height 0
:-webkit-transition (str "all " transition-time-ms "ms ease-in")
;; :transition "opacity .5s" ;; linear"
}}
content])]
;; allow 5 toasts max at one time
(when (< 5 (or (.-childElementCount container) 0))
(when-let [first-elem (.-firstChild container)]
;; (.remove first-elem) not remove immediatelly, but after toast-animate-hide
(toast-animate-hide first-elem)
(js/setTimeout #(.remove toast-elem) transition-time-ms)))
(.appendChild container toast-elem)
;; (.prepend container toast-elem) ;; for top-to-bottom scroll
;; https://stackoverflow.com/questions/24148403/trigger-css-transition-on-appended-element
(.getBoundingClientRect toast-elem)
(toast-animate-show toast-elem)
(js/setTimeout #(toast-animate-hide toast-elem) (- timeout transition-time-ms)) ;; transition back right before element deleting
(js/setTimeout #(.remove toast-elem) timeout)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment