From 72a0df6332a6aaa8b6bab8ce07a4dc23775b3a21 Mon Sep 17 00:00:00 2001 From: andrey Date: Thu, 10 Mar 2022 11:11:00 +0100 Subject: [PATCH] text component --- .env.jenkins | 1 + src/quo/theme.cljs | 12 +- src/quo2/components/button.cljs | 141 ++++++++++++++ src/quo2/components/text.cljs | 34 ++++ src/quo2/foundations/colors.cljs | 176 ++++++++++++++++++ src/quo2/foundations/typography.cljs | 31 +++ src/quo2/screens/button.cljs | 78 ++++++++ src/quo2/screens/main.cljs | 55 ++++++ src/quo2/screens/text.cljs | 51 +++++ .../ui/screens/profile/user/views.cljs | 7 + src/status_im/ui/screens/screens.cljs | 14 +- 11 files changed, 593 insertions(+), 7 deletions(-) create mode 100644 src/quo2/components/button.cljs create mode 100644 src/quo2/components/text.cljs create mode 100644 src/quo2/foundations/colors.cljs create mode 100644 src/quo2/foundations/typography.cljs create mode 100644 src/quo2/screens/button.cljs create mode 100644 src/quo2/screens/main.cljs create mode 100644 src/quo2/screens/text.cljs diff --git a/.env.jenkins b/.env.jenkins index dddcaa49d6..20ef28303c 100644 --- a/.env.jenkins +++ b/.env.jenkins @@ -36,3 +36,4 @@ COMMUNITIES_MANAGEMENT_ENABLED=1 METRICS_ENABLED=0 DELETE_MESSAGE_ENABLED=1 TWO_MINUTES_SYNCING=1 +ENABLE_QUO_PREVIEW=1 diff --git a/src/quo/theme.cljs b/src/quo/theme.cljs index 79d3b512c5..5fba1edaac 100644 --- a/src/quo/theme.cljs +++ b/src/quo/theme.cljs @@ -1,8 +1,14 @@ (ns quo.theme (:require [quo.design-system.colors :as colors])) -(defn set-theme [theme] - (reset! colors/theme (case theme +(def theme (atom nil)) + +(defn get-theme [] + @theme) + +(defn set-theme [value] + (reset! theme value) + (reset! colors/theme (case value :dark colors/dark-theme colors/light-theme)) - (colors/set-legacy-theme-type theme)) + (colors/set-legacy-theme-type value)) diff --git a/src/quo2/components/button.cljs b/src/quo2/components/button.cljs new file mode 100644 index 0000000000..7f26135524 --- /dev/null +++ b/src/quo2/components/button.cljs @@ -0,0 +1,141 @@ +(ns quo2.components.button + (:require [quo.react-native :as rn] + [status-im.ui.components.icons.icons :as icons] + [quo2.foundations.colors :as colors] + [quo2.components.text :as text] + [quo.theme :as theme] + [reagent.core :as reagent])) + +(def themes {:light {:primary {:icon-color colors/white + :label {:style {:color colors/white}} + :background-color {:default colors/primary-50 + :pressed colors/primary-70 + :disabled colors/primary-50}} + :secondary {:icon-color colors/primary-50 + :label {:style {:color colors/primary-50}} + :background-color {:default colors/primary-50-opa-20 + :pressed colors/primary-50-opa-40 + :disabled colors/primary-50-opa-20}} + :grey {:icon-color colors/neutral-50 + :label {:style {:color colors/black}} + :background-color {:default colors/neutral-40 + :pressed colors/neutral-30 + :disabled colors/neutral-20}} + :outline {:icon-color colors/neutral-50 + :label {:style {:color colors/black}} + :border-color {:default colors/neutral-30 + :pressed colors/neutral-40}} + :ghost {:icon-color colors/neutral-50 + :label {:style {:color colors/black}} + :background-color {:pr:pressedess colors/neutral-10}} + :danger {:icon-color colors/white + :label {:style {:color colors/white}} + :background-color {:default colors/danger-50 + :pressed colors/danger-60 + :disabled colors/danger-50}}} + :dark {:primary {:icon-color colors/white + :label {:style {:color colors/white}} + :background-color {:default colors/primary-60 + :pressed colors/primary-40 + :disabled colors/primary-60}} + :secondary {:icon-color colors/primary-50 + :label {:style {:color colors/primary-50}} + :background-color {:default colors/primary-50-opa-20 + :pressed colors/primary-50-opa-30 + :disabled colors/primary-50-opa-20}} + :grey {:icon-color colors/neutral-40 + :label {:style {:color colors/white}} + :background-color {:default colors/neutral-80 + :pressed colors/neutral-60 + :disabled colors/neutral-80}} + :outline {:icon-color colors/neutral-40 + :label {:style {:color colors/white}} + :border-color {:default colors/neutral-70 + :pressed colors/neutral-60}} + :ghost {:icon-color colors/neutral-40 + :label {:style {:color colors/white}} + :background-color {:pressed colors/neutral-80}} + :danger {:icon-color colors/white + :label {:style {:color colors/white}} + :background-color {:default colors/danger-50 + :pressed colors/danger-40 + :disabled colors/danger-50}}}}) + +(defn style-container [type size disabled background-color border-color icon] + (println size disabled background-color) + (merge {:height size + :align-items :center + :justify-content :center + :flex-direction :row + :border-radius (if (and icon (#{:primary :secondary :danger} type)) + 24 + (case size + 40 12 + 32 10 + 24 8)) + :background-color background-color + :padding-horizontal (if icon 0 (case size 40 16 32 12 24 8))} + (when icon + {:width size}) + (when border-color + {:border-color border-color + :border-width 1}) + (when disabled + {:opacity 0.3}))) + +(defn button + "with label + [button opts \"label\"] + opts + {:type :primary/:secondary/:grey/:outline/:ghost/:danger + :size 40/32/24 + :icon true/false + :before :icon-keyword + :after :icon-keyword} + + only icon + [button {:icon true} :main-icons/close-circle]" + [_ _] + (let [pressed (reagent/atom false)] + (fn [{:keys [on-press disabled type size before after + on-long-press accessibility-label icon] + :or {type :primary + size 40}} + children] + (let [{:keys [icon-color background-color label border-color]} + (get-in themes [(theme/get-theme) type]) + state (cond disabled :disabled @pressed :pressed :else :default)] + [rn/touchable-without-feedback (merge {:disabled disabled + :accessibility-label accessibility-label} + (when on-press + {:on-press (fn [] + (on-press))}) + (when on-long-press + {:on-long-press (fn [] + (on-long-press))}) + {:on-press-in (fn [] + (reset! pressed true))} + {:on-press-out (fn [] + (reset! pressed nil))}) + + [rn/view {:style (style-container type size disabled (get background-color state) (get border-color state) icon)} + (when before + [rn/view + [icons/icon before {:color icon-color}]]) + [rn/view + (cond + icon + [icons/icon children {:color icon-color}] + + (string? children) + [text/text (merge {:size (when (= size 24) :paragraph-2) + :weight :medium + :number-of-lines 1} + label) + children] + + (vector? children) + children)] + (when after + [rn/view + [icons/icon after {:color icon-color}]])]])))) \ No newline at end of file diff --git a/src/quo2/components/text.cljs b/src/quo2/components/text.cljs new file mode 100644 index 0000000000..60fbc440a6 --- /dev/null +++ b/src/quo2/components/text.cljs @@ -0,0 +1,34 @@ +(ns quo2.components.text + (:require [quo.react-native :as rn] + [reagent.core :as reagent] + [quo.theme :as theme] + [quo2.foundations.colors :as colors] + [quo2.foundations.typography :as typography])) + +(defn text-style [{:keys [size align weight style]}] + (merge (case (or weight :regular) + :regular typography/font-regular + :medium typography/font-medium + :semi-bold typography/font-semi-bold + :bold typography/font-bold + :monospace typography/monospace + :inherit nil) + (case (or size :paragraph-1) + :label typography/label + :paragraph-2 typography/paragraph-2 + :paragraph-1 typography/paragraph-1 + :heading-2 typography/heading-2 + :heading-1 typography/heading-1 + :inherit nil) + {:text-align (or align :auto)} + (if (:color style) + style + (assoc style :color (if (= (theme/get-theme) :dark) colors/white colors/black))))) + +(defn text [] + (let [this (reagent/current-component) + props (reagent/props this) + style (text-style props)] + (println "style " style) + (into [rn/text {:style style}] + (reagent/children this)))) \ No newline at end of file diff --git a/src/quo2/foundations/colors.cljs b/src/quo2/foundations/colors.cljs new file mode 100644 index 0000000000..e18060d7f6 --- /dev/null +++ b/src/quo2/foundations/colors.cljs @@ -0,0 +1,176 @@ +(ns quo2.foundations.colors + (:require [clojure.string :as string])) + +(defn alpha [value opacity] + (if (string/starts-with? value "#") + (let [hex (string/replace value #"#" "") + r (js/parseInt (subs hex 0 2) 16) + g (js/parseInt (subs hex 2 4) 16) + b (js/parseInt (subs hex 4 6) 16)] + (str "rgba(" r "," g "," b "," opacity ")")) + (let [rgb (string/split value #",")] + (str (string/join "," (butlast rgb)) "," opacity ")")))) + +;;;;Neutral + +;;Solid +(def neutral-5 "#F5F6F8") +(def neutral-10 "#F0F2F5") +(def neutral-20 "#ECEEF1") +(def neutral-30 "#E7EAEE") +(def neutral-40 "#A1ABBD") +(def neutral-50 "#647084") +(def neutral-60 "#303D55") +(def neutral-70 "#192438") +(def neutral-80 "#131D2F") +(def neutral-90 "#0D1625") +(def neutral-95 "#09101C") + +;;50 with transparency +(def neutral-50-opa-5 (alpha neutral-50 0.05)) +(def neutral-50-opa-10 (alpha neutral-50 0.1)) +(def neutral-50-opa-20 (alpha neutral-50 0.2)) +(def neutral-50-opa-30 (alpha neutral-50 0.3)) +(def neutral-50-opa-40 (alpha neutral-50 0.4)) + +;;80 with transparency +(def neutral-80-opa-60 (alpha neutral-80 0.6)) +(def neutral-80-opa-70 (alpha neutral-80 0.7)) +(def neutral-80-opa-80 (alpha neutral-80 0.8)) +(def neutral-80-opa-90 (alpha neutral-80 0.9)) +(def neutral-80-opa-95 (alpha neutral-80 0.95)) + +;;95 with transparency +(def neutral-95-opa-60 (alpha neutral-95 0.6)) +(def neutral-95-opa-70 (alpha neutral-95 0.7)) +(def neutral-95-opa-80 (alpha neutral-95 0.8)) +(def neutral-95-opa-90 (alpha neutral-95 0.9)) +(def neutral-95-opa-95 (alpha neutral-95 0.95)) + +;;;;Black +(def black "#000000") +(def black-opa-5 (alpha black 0.05)) +(def black-opa-10 (alpha black 0.1)) +(def black-opa-20 (alpha black 0.2)) +(def black-opa-30 (alpha black 0.3)) +(def black-opa-40 (alpha black 0.4)) +(def black-opa-50 (alpha black 0.5)) +(def black-opa-60 (alpha black 0.6)) +(def black-opa-70 (alpha black 0.7)) +(def black-opa-80 (alpha black 0.8)) +(def black-opa-90 (alpha black 0.9)) +(def black-opa-95 (alpha black 0.95)) + +;;;;White +(def white "#ffffff") +(def white-opa-5 (alpha white 0.05)) +(def white-opa-10 (alpha white 0.1)) +(def white-opa-20 (alpha white 0.2)) +(def white-opa-30 (alpha white 0.3)) +(def white-opa-40 (alpha white 0.4)) +(def white-opa-50 (alpha white 0.5)) +(def white-opa-60 (alpha white 0.6)) +(def white-opa-70 (alpha white 0.7)) +(def white-opa-80 (alpha white 0.8)) +(def white-opa-90 (alpha white 0.9)) +(def white-opa-95 (alpha white 0.95)) + +;;;;Primary + +;;Solid +(def primary-10 "#F8F9FE") +(def primary-20 "#D9DFF9") +(def primary-30 "#ACB9F1") +(def primary-40 "#7F93E9") +(def primary-50 "#4360DF") +(def primary-60 "#3851BB") +(def primary-70 "#2E4198") +(def primary-80 "#233274") +(def primary-90 "#182350") + +;;50 with transparency +(def primary-50-opa-5 (alpha primary-50 0.05)) +(def primary-50-opa-10 (alpha primary-50 0.1)) +(def primary-50-opa-20 (alpha primary-50 0.2)) +(def primary-50-opa-30 (alpha primary-50 0.3)) +(def primary-50-opa-40 (alpha primary-50 0.4)) + +;;;;Success + +;;Solid +(def success-10 "#F6FBFB") +(def success-20 "#D4EDEB") +(def success-30 "#9FD8D3") +(def success-40 "#6BC2BA") +(def success-50 "#26A69A") +(def success-60 "#208B81") +(def success-70 "#1A7169") +(def success-80 "#145650") +(def success-90 "#08211F") + +;;50 with transparency +(def success-50-opa-5 (alpha success-50 0.05)) +(def success-50-opa-10 (alpha success-50 0.1)) +(def success-50-opa-20 (alpha success-50 0.2)) +(def success-50-opa-30 (alpha success-50 0.3)) +(def success-50-opa-40 (alpha success-50 0.4)) + +;;;;Warning + +;;Solid +(def warning-10 "#FFFBF9") +(def warning-20 "#FEE9DF") +(def warning-30 "#FDCEBA") +(def warning-40 "#FCB394") +(def warning-50 "#FB8F61") +(def warning-60 "#D37851") +(def warning-70 "#AB6142") +(def warning-80 "#824A32") +(def warning-90 "#5A3323") + +;;50 with transparency +(def warning-50-opa-5 (alpha warning-50 0.05)) +(def warning-50-opa-10 (alpha warning-50 0.1)) +(def warning-50-opa-20 (alpha warning-50 0.2)) +(def warning-50-opa-30 (alpha warning-50 0.3)) +(def warning-50-opa-40 (alpha warning-50 0.4)) + +;;;;Danger + +;;Solid +(def danger-10 "#FEF9F9") +(def danger-20 "#FADFDE") +(def danger-30 "#F4B9B7") +(def danger-40 "#EE9290") +(def danger-50 "#E65F5C") +(def danger-60 "#C1504D") +(def danger-70 "#9C413F") +(def danger-80 "#783130") +(def danger-90 "#532221") + +;;50 with transparency +(def danger-50-opa-5 (alpha danger-50 0.05)) +(def danger-50-opa-10 (alpha danger-50 0.1)) +(def danger-50-opa-20 (alpha danger-50 0.2)) +(def danger-50-opa-30 (alpha danger-50 0.3)) +(def danger-50-opa-40 (alpha danger-50 0.4)) + +;;;;Info + +;;Solid +(def info-10 "#F6FCFD") +(def info-20 "#D2EEF4") +(def info-30 "#9DD9E6") +(def info-40 "#67C4D8") +(def info-50 "#20A8C6") +(def info-60 "#1B8DA6") +(def info-70 "#167287") +(def info-80 "#115767") +(def info-90 "#0C3C47") + +;;50 with transparency +(def info-50-opa-5 (alpha info-50 0.05)) +(def info-50-opa-10 (alpha info-50 0.1)) +(def info-50-opa-20 (alpha info-50 0.2)) +(def info-50-opa-30 (alpha info-50 0.3)) +(def info-50-opa-40 (alpha info-50 0.4)) \ No newline at end of file diff --git a/src/quo2/foundations/typography.cljs b/src/quo2/foundations/typography.cljs new file mode 100644 index 0000000000..54021c5f33 --- /dev/null +++ b/src/quo2/foundations/typography.cljs @@ -0,0 +1,31 @@ +(ns quo2.foundations.typography) + +(def heading-1 {:font-size 27 + :line-height 32.4 + :letter-spacing -2.1}) + +(def heading-2 {:font-size 19 + :line-height 25.65 + :letter-spacing -1.6}) + +(def paragraph-1 {:font-size 15 + :line-height 21.75 + :letter-spacing -0.9}) + +(def paragraph-2 {:font-size 13 + :line-height 18.2 + :letter-spacing -0.3}) + +(def label {:font-size 11 + :line-height 15.62 + :letter-spacing 0.5}) + +(def font-regular {:font-family "Inter-Regular"}) ; 400 + +(def font-medium {:font-family "Inter-Medium"}) ; 500 ff + +(def font-semi-bold {:font-family "Inter-SemiBold"}) ; 600 + +(def font-bold {:font-family "Inter-Bold"}) ; 700 + +(def monospace {:font-family "InterStatus-Regular"}) \ No newline at end of file diff --git a/src/quo2/screens/button.cljs b/src/quo2/screens/button.cljs new file mode 100644 index 0000000000..82eb60b2d8 --- /dev/null +++ b/src/quo2/screens/button.cljs @@ -0,0 +1,78 @@ +(ns quo2.screens.button + (:require [reagent.core :as reagent] + [quo.react-native :as rn] + [quo.previews.preview :as preview] + [quo.design-system.colors :as colors] + [quo2.components.button :as quo2])) + +(def descriptor [{:label "Type:" + :key :type + :type :select + :options [{:key :primary + :value "Primary"} + {:key :secondary + :value "Secondary"} + {:key :grey + :value "Grey"} + {:key :outline + :value "Outline"} + {:key :ghost + :value "Ghost"} + {:key :danger + :value "Danger"}]} + {:label "Size:" + :key :size + :type :select + :options [{:key 40 + :value "40"} + {:key 32 + :value "32"} + {:key 24 + :value "24"}]} + {:label "Icon:" + :key :icon + :type :boolean} + {:label "After icon:" + :key :after + :type :boolean} + {:label "Before icon:" + :key :before + :type :boolean} + {:label "Disabled:" + :key :disabled + :type :boolean} + {:label "Label" + :key :label + :type :text}]) + +(defn cool-preview [] + (let [state (reagent/atom {:label "Press Me" + :size 40}) + label (reagent/cursor state [:label]) + before (reagent/cursor state [:before]) + after (reagent/cursor state [:after]) + icon (reagent/cursor state [:icon])] + (fn [] + [rn/view {:margin-bottom 50 + :padding 16} + [rn/view {:flex 1} + [preview/customizer state descriptor]] + [rn/view {:padding-vertical 60 + :flex-direction :row + :justify-content :center} + [quo2/button (merge (dissoc @state + :theme :before :after) + {:on-press #(println "Hello world!")} + (when @before + {:before :main-icons/back}) + (when @after + {:after :main-icons/next})) + (if @icon :main-icons/close-circle @label)]]]))) + +(defn preview-button [] + [rn/view {:background-color (:ui-background @colors/theme) + :flex 1} + [rn/flat-list {:flex 1 + :keyboardShouldPersistTaps :always + :header [cool-preview] + :key-fn str}]]) \ No newline at end of file diff --git a/src/quo2/screens/main.cljs b/src/quo2/screens/main.cljs new file mode 100644 index 0000000000..bcf021cb15 --- /dev/null +++ b/src/quo2/screens/main.cljs @@ -0,0 +1,55 @@ +(ns quo2.screens.main + (:require [quo.react-native :as rn] + [quo.theme :as theme] + [quo.design-system.colors :as colors] + [re-frame.core :as re-frame] + [quo2.screens.button :as button] + [quo2.screens.text :as text] + [quo.core :as quo])) + +(def screens [{:name :quo2-texts + :insets {:top false} + :component text/preview-text} + {:name :quo2-button + :insets {:top false} + :component button/preview-button}]) + +(defn theme-switcher [] + [rn/view {:style {:flex-direction :row + :margin-vertical 8 + :border-radius 4 + :background-color (:ui-01 @colors/theme) + :border-width 1 + :border-color (:ui-02 @colors/theme)}} + [rn/touchable-opacity {:style {:padding 8 + :flex 1 + :justify-content :center + :align-items :center} + :on-press #(theme/set-theme :light)} + [quo/text "Set light theme"]] + [rn/view {:width 1 + :margin-vertical 4 + :background-color (:ui-02 @colors/theme)}] + [rn/touchable-opacity {:style {:padding 8 + :flex 1 + :justify-content :center + :align-items :center} + :on-press #(theme/set-theme :dark)} + [quo/text "Set dark theme"]]]) + +(defn main-screen [] + [rn/scroll-view {:flex 1 + :padding-vertical 8 + :padding-horizontal 16 + :background-color (:ui-background @colors/theme)} + [theme-switcher] + [rn/view + (for [{:keys [name]} screens] + ^{:key name} + [rn/touchable-opacity {:on-press #(re-frame/dispatch [:navigate-to name])} + [rn/view {:style {:padding-vertical 8}} + [quo/text (str "Preview " name)]]])]]) + +(def main-screens [{:name :quo2-preview + :insets {:top false} + :component main-screen}]) \ No newline at end of file diff --git a/src/quo2/screens/text.cljs b/src/quo2/screens/text.cljs new file mode 100644 index 0000000000..4bc327310b --- /dev/null +++ b/src/quo2/screens/text.cljs @@ -0,0 +1,51 @@ +(ns quo2.screens.text + (:require [quo.react-native :as rn] + [quo.previews.preview :as preview] + [reagent.core :as reagent] + [quo2.components.text :as quo2] + [quo.design-system.colors :as colors])) + +(def descriptor [{:label "Size:" + :key :size + :type :select + :options [{:key :heading-1 + :value "Heading 1"} + {:key :heading-2 + :value "Heading 2"} + {:key :paragraph-1 + :value "Paragraph 1"} + {:key :paragraph-2 + :value "Paragraph 2"} + {:key :label + :value "Label"}]} + {:label "Weight:" + :key :weight + :type :select + :options [{:key :regular + :value "Regular"} + {:key :medium + :value "Medium"} + {:key :semi-bold + :value "Semi-bold"} + {:key :bold + :value "Bold"} + {:key :monospace + :value "Monospace"}]}]) + +(defn cool-preview [] + (let [state (reagent/atom {})] + (fn [] + [rn/view {:margin-bottom 50 + :padding 16} + [preview/customizer state descriptor] + [rn/view {:padding-vertical 60} + [quo2/text @state + "The quick brown fox jumped over the lazy dog."]]]))) + +(defn preview-text [] + [rn/view {:background-color (:ui-background @colors/theme) + :flex 1} + [rn/flat-list {:flex 1 + :keyboardShouldPersistTaps :always + :header [cool-preview] + :key-fn str}]]) \ No newline at end of file diff --git a/src/status_im/ui/screens/profile/user/views.cljs b/src/status_im/ui/screens/profile/user/views.cljs index 2f040ff097..62c52f0235 100644 --- a/src/status_im/ui/screens/profile/user/views.cljs +++ b/src/status_im/ui/screens/profile/user/views.cljs @@ -116,6 +116,13 @@ :accessibility-label :appearance-settings-button :chevron true :on-press #(re-frame/dispatch [:navigate-to :quo-preview])}]) + (when config/quo-preview-enabled? + [quo/list-item + {:icon :main-icons/appearance + :title "Quo2.0 Preview" + :accessibility-label :appearance-settings-button + :chevron true + :on-press #(re-frame/dispatch [:navigate-to :quo2-preview])}]) [quo/list-item {:icon :main-icons/appearance :title (i18n/label :t/appearance) diff --git a/src/status_im/ui/screens/screens.cljs b/src/status_im/ui/screens/screens.cljs index 2a5cc6cf4e..7f9f700e1b 100644 --- a/src/status_im/ui/screens/screens.cljs +++ b/src/status_im/ui/screens/screens.cljs @@ -119,7 +119,9 @@ [status-im.ui.screens.wallet.accounts-manage.views :as accounts-manage] [status-im.ui.screens.wallet.buy-crypto.views :as wallet.buy-crypto] [status-im.ui.screens.wallet.recipient.views :as recipient] - [status-im.ui.screens.wallet.send.views :as wallet.send])) + [status-im.ui.screens.wallet.send.views :as wallet.send] + [quo2.screens.main :as quo2.preview] + [status-im.utils.config :as config])) (def components [{:name :chat-toolbar @@ -903,7 +905,11 @@ :options {:topBar {:visible false}} :component bug-report/bug-report}] - (when js/goog.DEBUG + (when config/quo-preview-enabled? quo.preview/screens) - (when js/goog.DEBUG - quo.preview/main-screens))) + (when config/quo-preview-enabled? + quo.preview/main-screens) + (when config/quo-preview-enabled? + quo2.preview/screens) + (when config/quo-preview-enabled? + quo2.preview/main-screens)))