Fix & optimize shadows foundation (#16553)
Rewrite the shadows foundation API: - Fix (implementation & usages): theme changes were not causing shadows to be reevaluated. - Optimization: define all possible shadow values at compile time. Good to reduce cycles on garbage collection since recreating the shadow map all the time is unnecessary and also to save cycles on computing colors since calls to colors/alpha are not memoized. - API redesign: unify access to Design System shadows in a single function. None of the actual shadow values changed. Fixes https://github.com/status-im/status-mobile/issues/16526 API rationale ============= The quo2.foundations.shadows namespace reflects what's in the Design System > Foundations > Shadows https://www.figma.com/file/v98g9ZiaSHYUdKWrbFg9eM/Foundations?type=design&node-id=624-965&mode=design&t=CvIotdjbHKHcHjpd-0). Figma users see these shadows in other components as "Shadow/Normal/Light/03". Notice the shadow's weight is shown as a number (not the semantic name in Figma, e.g. "intense", "strong"): So to make things as easy as possible, I opted for exposing a single public function named "get", which receives arguments in order of frequency of usage and which expects shadow weights as numbers so that devs don't need to mentally translate 1 to "soft", or 3 to "intense".
This commit is contained in:
parent
6170686e34
commit
6c28e9349f
|
@ -62,4 +62,4 @@
|
||||||
(and pressed? (= type :discover))
|
(and pressed? (= type :discover))
|
||||||
(colors/theme-colors colors/white :transparent theme))}
|
(colors/theme-colors colors/white :transparent theme))}
|
||||||
(when (and (= type :discover) (not pressed?))
|
(when (and (= type :discover) (not pressed?))
|
||||||
(:shadow-3 shadows/normal-scale))))
|
(shadows/get 3))))
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
:background-color :transparent})
|
:background-color :transparent})
|
||||||
|
|
||||||
(defn content-container
|
(defn content-container
|
||||||
[override-theme]
|
[theme]
|
||||||
(merge
|
(merge
|
||||||
(:shadow-1 shadows/normal-scale)
|
(shadows/get 1 theme)
|
||||||
{:background-color (colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70 override-theme)
|
{:background-color (colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70 theme)
|
||||||
:flex-direction :row
|
:flex-direction :row
|
||||||
:padding-vertical 8
|
:padding-vertical 8
|
||||||
:padding-horizontal 12}))
|
:padding-horizontal 12}))
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
:background-color :transparent})
|
:background-color :transparent})
|
||||||
|
|
||||||
(defn content-container
|
(defn content-container
|
||||||
[override-theme]
|
[theme]
|
||||||
(merge
|
(merge
|
||||||
(:shadow-1 shadows/normal-scale)
|
(shadows/get 1 theme)
|
||||||
{:background-color (colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70 override-theme)
|
{:background-color (colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70 theme)
|
||||||
:flex-direction :row
|
:flex-direction :row
|
||||||
:justify-content :space-between
|
:justify-content :space-between
|
||||||
:padding-vertical 8
|
:padding-vertical 8
|
||||||
|
|
|
@ -1,66 +1,77 @@
|
||||||
(ns quo2.foundations.shadows
|
(ns quo2.foundations.shadows
|
||||||
|
(:refer-clojure :exclude [get])
|
||||||
(:require [quo2.foundations.colors :as colors]
|
(:require [quo2.foundations.colors :as colors]
|
||||||
[quo2.theme :as theme]))
|
[quo2.theme :as quo.theme]))
|
||||||
|
|
||||||
(defn- get-inverted
|
(def ^:private shadows
|
||||||
[inverted? number]
|
(let [dark-normal {1 {:shadow-color (colors/alpha colors/neutral-100 0.5)
|
||||||
(if inverted? (* -1 number) number))
|
:shadow-offset {:width 0 :height 4}
|
||||||
|
:elevation 3
|
||||||
|
:shadow-opacity 1
|
||||||
|
:shadow-radius 20}
|
||||||
|
2 {:shadow-color (colors/alpha colors/neutral-100 0.64)
|
||||||
|
:shadow-offset {:width 0 :height 4}
|
||||||
|
:elevation 4
|
||||||
|
:shadow-opacity 1
|
||||||
|
:shadow-radius 20}
|
||||||
|
3 {:shadow-color (colors/alpha colors/neutral-100 0.64)
|
||||||
|
:shadow-offset {:width 0 :height 12}
|
||||||
|
:elevation 8
|
||||||
|
:shadow-opacity 1
|
||||||
|
:shadow-radius 20}
|
||||||
|
4 {:shadow-color (colors/alpha colors/neutral-100 0.72)
|
||||||
|
:shadow-offset {:width 0 :height 16}
|
||||||
|
:shadow-opacity 1
|
||||||
|
:shadow-radius 20
|
||||||
|
:elevation 15}}
|
||||||
|
dark-normal-inverted (-> dark-normal
|
||||||
|
(update-in [:soft :shadow-offset :height] -)
|
||||||
|
(update-in [:medium :shadow-offset :height] -)
|
||||||
|
(update-in [:intense :shadow-offset :height] -)
|
||||||
|
(update-in [:strong :shadow-offset :height] -))
|
||||||
|
light-normal {1 {:shadow-color (colors/alpha colors/neutral-100 0.04)
|
||||||
|
:shadow-offset {:width 0 :height 4}
|
||||||
|
:elevation 1
|
||||||
|
:shadow-opacity 1
|
||||||
|
:shadow-radius 16}
|
||||||
|
2 {:shadow-color (colors/alpha colors/neutral-100 0.08)
|
||||||
|
:shadow-offset {:width 0 :height 4}
|
||||||
|
:elevation 2
|
||||||
|
:shadow-opacity 1
|
||||||
|
:shadow-radius 16}
|
||||||
|
3 {:shadow-color (colors/alpha colors/neutral-100 0.12)
|
||||||
|
:shadow-offset {:width 0 :height 12}
|
||||||
|
:elevation 5
|
||||||
|
:shadow-opacity 1
|
||||||
|
:shadow-radius 16}
|
||||||
|
4 {:shadow-color (colors/alpha colors/neutral-100 0.16)
|
||||||
|
:shadow-offset {:width 0 :height 16}
|
||||||
|
:shadow-opacity 1
|
||||||
|
:shadow-radius 16
|
||||||
|
:elevation 13}}
|
||||||
|
light-normal-inverted (-> light-normal
|
||||||
|
(update-in [:soft :shadow-offset :height] -)
|
||||||
|
(update-in [:medium :shadow-offset :height] -)
|
||||||
|
(update-in [:intense :shadow-offset :height] -)
|
||||||
|
(update-in [:strong :shadow-offset :height] -))]
|
||||||
|
{:dark {:normal dark-normal :inverted dark-normal-inverted}
|
||||||
|
:light {:normal light-normal :inverted light-normal-inverted}}))
|
||||||
|
|
||||||
(defn- get-scales
|
(defn get
|
||||||
[inverted?]
|
"Get the appropriate shadow map for a given shadow `weight`, `theme`, and `scale-type`.
|
||||||
(if (theme/dark?)
|
|
||||||
{:shadow-1 {:shadow-color (colors/alpha colors/neutral-100 0.5)
|
|
||||||
:shadow-offset {:width 0
|
|
||||||
:height (get-inverted inverted? 4)}
|
|
||||||
:elevation 3
|
|
||||||
:shadow-opacity 1
|
|
||||||
:shadow-radius 20}
|
|
||||||
:shadow-2 {:shadow-color (colors/alpha colors/neutral-100 0.64)
|
|
||||||
:shadow-offset {:width 0
|
|
||||||
:height (get-inverted inverted? 4)}
|
|
||||||
:elevation 4
|
|
||||||
:shadow-opacity 1
|
|
||||||
:shadow-radius 20}
|
|
||||||
:shadow-3 {:shadow-color (colors/alpha colors/neutral-100 0.64)
|
|
||||||
:shadow-offset {:width 0
|
|
||||||
:height (get-inverted inverted? 12)}
|
|
||||||
:elevation 8
|
|
||||||
:shadow-opacity 1
|
|
||||||
:shadow-radius 20}
|
|
||||||
:shadow-4 {:shadow-color (colors/alpha colors/neutral-100 0.72)
|
|
||||||
:shadow-offset {:width 0
|
|
||||||
:height (get-inverted inverted? 16)}
|
|
||||||
:shadow-opacity 1
|
|
||||||
:shadow-radius 20
|
|
||||||
:elevation 15}}
|
|
||||||
{:shadow-1 {:shadow-color (colors/alpha colors/neutral-100 0.04)
|
|
||||||
:shadow-offset {:width 0
|
|
||||||
:height (get-inverted inverted? 4)}
|
|
||||||
:elevation 1
|
|
||||||
:shadow-opacity 1
|
|
||||||
:shadow-radius 16}
|
|
||||||
:shadow-2 {:shadow-color (colors/alpha colors/neutral-100 0.08)
|
|
||||||
:shadow-offset {:width 0
|
|
||||||
:height (get-inverted inverted? 4)}
|
|
||||||
:elevation 2
|
|
||||||
:shadow-opacity 1
|
|
||||||
:shadow-radius 16}
|
|
||||||
:shadow-3 {:shadow-color (colors/alpha colors/neutral-100 0.12)
|
|
||||||
:shadow-offset {:width 0
|
|
||||||
:height (get-inverted inverted? 12)}
|
|
||||||
:elevation 5
|
|
||||||
:shadow-opacity 1
|
|
||||||
:shadow-radius 16}
|
|
||||||
:shadow-4 {:shadow-color (colors/alpha colors/neutral-100 0.16)
|
|
||||||
:shadow-offset {:width 0
|
|
||||||
:height (get-inverted inverted? 16)}
|
|
||||||
:shadow-opacity 1
|
|
||||||
:shadow-radius 16
|
|
||||||
:elevation 13}}))
|
|
||||||
|
|
||||||
(def normal-scale (get-scales false))
|
Return nil if no shadow is found.
|
||||||
|
|
||||||
(def inverted-scale (get-scales true))
|
`weight` - int (required) from 1 to 4.
|
||||||
|
`theme` - :light/:dark (optional).
|
||||||
|
`scale-type` - :normal/:inverted (optional).
|
||||||
|
"
|
||||||
|
([weight]
|
||||||
|
(get weight (quo.theme/get-theme)))
|
||||||
|
([weight theme]
|
||||||
|
(get weight theme :normal))
|
||||||
|
([weight theme scale-type]
|
||||||
|
(get-in shadows [theme scale-type weight])))
|
||||||
|
|
||||||
(def inner-shadow
|
(def inner-shadow
|
||||||
{:shadow-color (colors/alpha colors/neutral-100 0.08)
|
{:shadow-color (colors/alpha colors/neutral-100 0.08)
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
[last-item?]
|
[last-item?]
|
||||||
;; This part needs to be improved, inverted shadow is not supported in android
|
;; This part needs to be improved, inverted shadow is not supported in android
|
||||||
;; https://reactnative.dev/docs/shadow-props#shadowoffset-ios
|
;; https://reactnative.dev/docs/shadow-props#shadowoffset-ios
|
||||||
;; (merge
|
;;
|
||||||
;; (:shadow-1 (shadows/get-scales true :dark))
|
;; (merge (shadows/get 1 :dark :inverted) ...)
|
||||||
|
;;
|
||||||
{:padding-horizontal 20
|
{:padding-horizontal 20
|
||||||
:margin-bottom (when-not last-item? -24)})
|
:margin-bottom (when-not last-item? -24)})
|
||||||
|
|
||||||
|
|
|
@ -1,65 +1,65 @@
|
||||||
(ns status-im2.contexts.quo-preview.foundations.shadows
|
(ns status-im2.contexts.quo-preview.foundations.shadows
|
||||||
(:require
|
(:require [quo2.core :as quo]
|
||||||
[quo2.foundations.shadows :as shadows]
|
[quo2.foundations.colors :as colors]
|
||||||
[quo2.foundations.colors :as colors]
|
[quo2.foundations.shadows :as shadows]
|
||||||
[quo2.core :as quo]
|
[quo2.theme :as quo.theme]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im2.contexts.quo-preview.preview :as preview]))
|
[status-im2.contexts.quo-preview.preview :as preview]))
|
||||||
|
|
||||||
(defn demo-box
|
(defn demo-box
|
||||||
[shadow-on? name shadow-style]
|
[shadow? description shadow-style]
|
||||||
[rn/view
|
[rn/view
|
||||||
{:margin-left :auto
|
{:style {:margin-left :auto
|
||||||
:margin-right :auto
|
:margin-right :auto
|
||||||
:margin-top 8
|
:margin-top 8
|
||||||
:margin-bottom 8
|
:margin-bottom 8
|
||||||
:align-items :center}
|
:align-items :center}}
|
||||||
[quo/text {} name]
|
[quo/text {} description]
|
||||||
[rn/view
|
[rn/view
|
||||||
{:style (merge {:width 60
|
{:style (merge {:width 60
|
||||||
:height 60
|
:height 60
|
||||||
:border-radius 16
|
:border-radius 16
|
||||||
:background-color (colors/theme-colors colors/white colors/neutral-90)}
|
:background-color (colors/theme-colors colors/white colors/neutral-90)}
|
||||||
(when shadow-on? shadow-style))}]])
|
(when shadow? shadow-style))}]])
|
||||||
|
|
||||||
(def descriptor
|
(def descriptor
|
||||||
[{:label "Shadow on?"
|
[{:label "Shadows enabled?"
|
||||||
:key :shadow-on?
|
:key :shadow?
|
||||||
:type :boolean}])
|
:type :boolean}])
|
||||||
|
|
||||||
(defn cool-preview
|
(defn cool-preview
|
||||||
[]
|
[]
|
||||||
(let [state (reagent/atom {:shadow-on? true})]
|
(let [state (reagent/atom {:shadow? true})
|
||||||
|
shadow? (reagent/cursor state [:shadow?])]
|
||||||
(fn []
|
(fn []
|
||||||
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
|
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
|
||||||
[rn/view {:padding-bottom 150}
|
[rn/view {:style {:padding-bottom 150}}
|
||||||
[preview/customizer state descriptor]
|
[preview/customizer state descriptor]
|
||||||
[:<>
|
[quo/text
|
||||||
[quo/text
|
{:style {:margin-left :auto
|
||||||
{:style {:margin-left :auto
|
:margin-right :auto
|
||||||
:margin-right :auto
|
:align-items :center}}
|
||||||
:align-items :center}}
|
"Normal Scales"]
|
||||||
"Normal Scales"]
|
[demo-box @shadow? "Shadow 1" (shadows/get 1)]
|
||||||
[demo-box (:shadow-on? @state) "shadow 1" (:shadow-1 shadows/normal-scale)]
|
[demo-box @shadow? "Shadow 2" (shadows/get 2)]
|
||||||
[demo-box (:shadow-on? @state) "shadow 2" (:shadow-2 shadows/normal-scale)]
|
[demo-box @shadow? "Shadow 3" (shadows/get 3)]
|
||||||
[demo-box (:shadow-on? @state) "shadow 3" (:shadow-3 shadows/normal-scale)]
|
[demo-box @shadow? "Shadow 4" (shadows/get 4)]
|
||||||
[demo-box (:shadow-on? @state) "shadow 4" (:shadow-4 shadows/normal-scale)]
|
[quo/text
|
||||||
[quo/text
|
{:style {:margin-left :auto
|
||||||
{:style {:margin-left :auto
|
:margin-right :auto
|
||||||
:margin-right :auto
|
:align-items :center}}
|
||||||
:align-items :center}}
|
"Inverted Scales"]
|
||||||
"Inverted Scales"]
|
[demo-box @shadow? "Shadow 1" (shadows/get 1 (quo.theme/get-theme) :inverted)]
|
||||||
[demo-box (:shadow-on? @state) "shadow 1" (:shadow-1 shadows/inverted-scale)]
|
[demo-box @shadow? "Shadow 2" (shadows/get 2 (quo.theme/get-theme) :inverted)]
|
||||||
[demo-box (:shadow-on? @state) "shadow 2" (:shadow-2 shadows/inverted-scale)]
|
[demo-box @shadow? "Shadow 3" (shadows/get 3 (quo.theme/get-theme) :inverted)]
|
||||||
[demo-box (:shadow-on? @state) "shadow 3" (:shadow-3 shadows/inverted-scale)]
|
[demo-box @shadow? "Shadow 4" (shadows/get 4 (quo.theme/get-theme) :inverted)]
|
||||||
[demo-box (:shadow-on? @state) "shadow 4" (:shadow-4 shadows/inverted-scale)]
|
[quo/text
|
||||||
[quo/text
|
{:style {:margin-left :auto
|
||||||
{:style {:margin-left :auto
|
:margin-right :auto
|
||||||
:margin-right :auto
|
:align-items :center}}
|
||||||
:align-items :center}}
|
"Inverted Scales"]
|
||||||
"Inverted Scales"]
|
[demo-box @shadow? "Inner Shadow" shadows/inner-shadow]]])))
|
||||||
[demo-box (:shadow-on? @state) "Inner Shadow" shadows/inner-shadow]]]])))
|
|
||||||
|
|
||||||
(defn preview-shadows
|
(defn preview-shadows
|
||||||
[]
|
[]
|
||||||
|
|
Loading…
Reference in New Issue