From fcbe6fe2b48aa30c3b958946761a947d7d557446 Mon Sep 17 00:00:00 2001 From: mmilad75 <55688834+mmilad75@users.noreply.github.com> Date: Tue, 12 Sep 2023 12:03:15 +0330 Subject: [PATCH] Implement "Drawer top" component (#17196) Implement "Drawer top" component --- .../drawers/drawer_top/component_spec.cljs | 98 +++++++++ .../components/drawers/drawer_top/style.cljs | 31 +++ .../components/drawers/drawer_top/view.cljs | 204 ++++++++++++++++++ src/quo2/core.cljs | 2 + src/quo2/core_spec.cljs | 1 + src/quo2/foundations/colors.cljs | 45 ++-- .../quo_preview/drawers/drawer_top.cljs | 71 ++++++ src/status_im2/contexts/quo_preview/main.cljs | 3 + 8 files changed, 436 insertions(+), 19 deletions(-) create mode 100644 src/quo2/components/drawers/drawer_top/component_spec.cljs create mode 100644 src/quo2/components/drawers/drawer_top/style.cljs create mode 100644 src/quo2/components/drawers/drawer_top/view.cljs create mode 100644 src/status_im2/contexts/quo_preview/drawers/drawer_top.cljs diff --git a/src/quo2/components/drawers/drawer_top/component_spec.cljs b/src/quo2/components/drawers/drawer_top/component_spec.cljs new file mode 100644 index 0000000000..537b9fcccc --- /dev/null +++ b/src/quo2/components/drawers/drawer_top/component_spec.cljs @@ -0,0 +1,98 @@ +(ns quo2.components.drawers.drawer-top.component-spec + (:require [test-helpers.component :as h] + [quo2.core :as quo])) + +(h/describe "drawer top tests" + (h/test "component renders in default type" + (h/render [quo/drawer-top + {:title "Title" + :type :default}]) + (h/is-truthy (h/get-by-text "Title"))) + + (h/test "component renders in default + description type" + (h/render [quo/drawer-top + {:title "Title" + :type :default + :description "Description"}]) + (h/is-truthy (h/get-by-text "Title")) + (h/is-truthy (h/get-by-text "Description"))) + + (h/test "component renders in info type" + (h/render [quo/drawer-top + {:title "Title" + :type :info}]) + (h/is-truthy (h/get-by-text "Title")) + (h/is-truthy (h/get-by-label-text :info-icon))) + + (h/test "component renders in info + description type" + (h/render [quo/drawer-top + {:title "Title" + :description "Description" + :type :info}]) + (h/is-truthy (h/get-by-text "Title")) + (h/is-truthy (h/get-by-text "Description")) + (h/is-truthy (h/get-by-label-text :info-icon))) + + (h/test "component renders in context-tag type" + (h/render [quo/drawer-top + {:title "Title" + :type :context-tag + :community-name "Coinbase"}]) + (h/is-truthy (h/get-by-text "Title")) + (h/is-truthy (h/get-by-label-text :context-tag-wrapper))) + + (h/test "component renders in context-tag + button type" + (h/render [quo/drawer-top + {:title "Title" + :type :context-tag + :button-icon :i/placeholder + :community-name "Coinbase"}]) + (h/is-truthy (h/get-by-text "Title")) + (h/is-truthy (h/get-by-label-text :button-icon)) + (h/is-truthy (h/get-by-label-text :context-tag-wrapper))) + + (h/test "component renders in account type" + (h/render [quo/drawer-top + {:title "Title" + :type :account + :account-avatar-emoji "🍿" + :networks [:ethereum] + :description "0x62b...0a5" + :customization-color :purple}]) + (h/is-truthy (h/get-by-text "Title")) + (h/is-truthy (h/get-by-text "0x62b...0a5")) + (h/is-truthy (h/get-by-label-text :account-avatar))) + + (h/test "component renders in keypair type when keycard? is false" + (h/render [quo/drawer-top + {:title "Title" + :keycard? false + :icon-avatar :i/placeholder + :type :keypair}]) + (h/is-truthy (h/get-by-text "Title")) + (-> (h/expect (h/get-by-translation-text :on-device)) + (.toBeTruthy))) + + (h/test "component renders in keypair type when keycard? is true" + (h/render [quo/drawer-top + {:title "Title" + :keycard? true + :icon-avatar :i/placeholder + :type :keypair}]) + (h/is-truthy (h/get-by-text "Title")) + (-> (h/expect (h/get-by-translation-text :on-keycard)) + (.toBeTruthy))) + + (h/test "component renders in default-keypair type" + (h/render [quo/drawer-top + {:title "Title" + :description "0x62b...0a5" + :type :default-keypair}]) + (h/is-truthy (h/get-by-text "Title")) + (h/is-truthy (h/get-by-label-text :default-keypair-text))) + + (h/test "component renders in label type" + (h/render [quo/drawer-top + {:label "label" + :type :label}]) + (h/is-truthy (h/get-by-text "label")))) diff --git a/src/quo2/components/drawers/drawer_top/style.cljs b/src/quo2/components/drawers/drawer_top/style.cljs new file mode 100644 index 0000000000..1ecb80fc73 --- /dev/null +++ b/src/quo2/components/drawers/drawer_top/style.cljs @@ -0,0 +1,31 @@ +(ns quo2.components.drawers.drawer-top.style + (:require [quo2.foundations.colors :as colors])) + +(def container + {:padding-horizontal 20 + :padding-bottom 12 + :flex-direction :row}) + +(def body-container + {:flex 1}) + +(defn description + [theme blur?] + {:color (if blur? + colors/white-opa-40 + (colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}) + +(def left-container + {:margin-right 8 + :justify-content :center}) + +(defn network-text-color + [network] + {:color (colors/custom-color network)}) + +(def row + {:flex-direction :row + :align-items :center}) + +(def keycard-icon + {:margin-left 4}) diff --git a/src/quo2/components/drawers/drawer_top/view.cljs b/src/quo2/components/drawers/drawer_top/view.cljs new file mode 100644 index 0000000000..6ac0d779f1 --- /dev/null +++ b/src/quo2/components/drawers/drawer_top/view.cljs @@ -0,0 +1,204 @@ +(ns quo2.components.drawers.drawer-top.view + (:require [quo2.theme :as quo.theme] + [quo2.components.markdown.text :as text] + [quo2.components.drawers.drawer-top.style :as style] + [quo2.components.buttons.button.view :as button] + [quo2.components.tags.context-tag.view :as context-tag] + [react-native.core :as rn] + [quo2.components.icon :as icons] + [quo2.components.avatars.account-avatar.view :as account-avatar] + [quo2.components.avatars.icon-avatar :as icon-avatar] + [quo2.components.avatars.user-avatar.view :as user-avatar] + [quo2.foundations.colors :as colors] + [utils.i18n :as i18n])) + +(defn- left-image + [{:keys [type customization-color account-avatar-emoji icon-avatar profile-picture]}] + (case type + :account [account-avatar/view + {:customization-color customization-color + :size 32 + :emoji account-avatar-emoji + :type :default}] + :keypair [icon-avatar/icon-avatar + {:icon icon-avatar + :border? true + :color :neutral}] + + :default-keypair [user-avatar/user-avatar + {:size :small + :status-indicator? false + :profile-picture profile-picture}] + nil)) + +(defn- network-view + [network] + [text/text + {:size :paragraph-2 + :weight :regular + :style (style/network-text-color network)} + (str (subs (name network) 0 3) ":")]) + +(defn- keypair-subtitle + [{:keys [theme blur? keycard?]}] + [rn/view {:style style/row} + [text/text + {:size :paragraph-2 + :weight :regular + :style (style/description theme blur?)} + (if keycard? + (i18n/label :t/on-keycard) + (i18n/label :t/on-device))] + (when keycard? + [icons/icon + :i/keycard-card + {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme) + :size 16 + :container-style style/keycard-icon}])]) + +(defn- acocunt-subtitle + [{:keys [networks theme blur? description]}] + [rn/view {:style style/row} + (for [network networks] + ^{:key (str network)} + [network-view network]) + [text/text + {:size :paragraph-2 + :weight :regular + :style (style/description theme blur?)} + description]]) + +(defn- default-keypair-subtitle + [{:keys [description theme blur?]}] + [text/text + {:accessibility-label :default-keypair-text + :size :paragraph-2 + :weight :regular + :style (style/description theme blur?)} + (str description " · " (i18n/label :t/on-device))]) + +(defn- context-tag-subtitle + [{:keys [community-logo community-name]}] + [rn/view + {:accessibility-label :context-tag-wrapper + :style {:flex-wrap :wrap}} + [context-tag/view + {:type :community + :community-name community-name + :community-logo community-logo + :size 24}]]) + +(defn- description-subtitle + [{:keys [theme blur? description]}] + [text/text + {:size :paragraph-1 + :weight :regular + :style (style/description theme blur?)} + description]) + +(defn- subtitle + [{:keys [type theme blur? keycard? networks description community-name community-logo]}] + (cond + (= :keypair type) + [keypair-subtitle + {:theme theme + :blur? blur? + :keycard? keycard?}] + + (= :account type) + [acocunt-subtitle + {:networks networks + :theme theme + :blur? blur? + :description description}] + + (= :default-keypair type) + [default-keypair-subtitle + {:description description + :theme theme + :blur? blur?}] + + (= :context-tag type) + [context-tag-subtitle + {:community-logo community-logo + :community-name community-name}] + + (and (not= :label type) description) + [description-subtitle + {:theme theme + :blur? blur? + :description description}])) + +(defn- right-icon + [{:keys [theme type on-button-press on-button-long-press button-disabled? button-icon]}] + (cond + (= :info type) + [icons/icon + :i/info + {:accessibility-label :info-icon + :size 20 + :color (colors/theme-colors colors/neutral-50 + colors/neutral-40 + theme)}] + (and (= :context-tag type) button-icon) + [button/button + {:accessibility-label :button-icon + :on-press on-button-press + :on-long-press on-button-long-press + :disabled? button-disabled? + :type :primary + :size 24 + :icon-only? true} + button-icon])) + +(defn- left-title + [{:keys [type label title theme blur?]}] + (case type + :label [text/text + {:weight :medium + :size :paragraph-2 + :style (style/description theme blur?)} + label] + [text/text + {:size :heading-2 + :weight :semi-bold} + title])) + +(defn- view-internal + [{:keys [title type theme description blur? community-name community-logo button-icon on-button-press + on-button-long-press + button-disabled? account-avatar-emoji customization-color icon-avatar + profile-picture keycard? networks label]}] + [rn/view {:style style/container} + [rn/view {:style style/left-container} + [left-image + {:type type + :customization-color customization-color + :account-avatar-emoji account-avatar-emoji + :icon-avatar icon-avatar + :profile-picture profile-picture}]] + [rn/view {:style style/body-container} + [left-title + {:type type + :label label + :title title + :theme theme + :blur? blur?}] + [subtitle + {:type type + :theme theme + :blur? blur? + :keycard? keycard? + :networks networks + :description description + :community-name community-name + :community-logo community-logo}]] + [right-icon + {:theme theme + :type type + :on-button-press on-button-press + :on-button-long-press on-button-long-press + :button-disabled? button-disabled? + :button-icon button-icon}]]) + +(def view (quo.theme/with-theme view-internal)) diff --git a/src/quo2/core.cljs b/src/quo2/core.cljs index 8941b3b7d3..d9d6493d3f 100644 --- a/src/quo2/core.cljs +++ b/src/quo2/core.cljs @@ -40,6 +40,7 @@ quo2.components.drawers.action-drawers.view quo2.components.drawers.documentation-drawers.view quo2.components.drawers.drawer-buttons.view + quo2.components.drawers.drawer-top.view quo2.components.drawers.permission-context.view quo2.components.dropdowns.dropdown quo2.components.dropdowns.network-dropdown.view @@ -200,6 +201,7 @@ (def action-drawer quo2.components.drawers.action-drawers.view/action-drawer) (def documentation-drawers quo2.components.drawers.documentation-drawers.view/view) (def drawer-buttons quo2.components.drawers.drawer-buttons.view/view) +(def drawer-top quo2.components.drawers.drawer-top.view/view) (def permission-context quo2.components.drawers.permission-context.view/view) ;;;; Dropdowns diff --git a/src/quo2/core_spec.cljs b/src/quo2/core_spec.cljs index fc8036aa24..13629b6d2e 100644 --- a/src/quo2/core_spec.cljs +++ b/src/quo2/core_spec.cljs @@ -22,6 +22,7 @@ [quo2.components.drawers.action-drawers.component-spec] [quo2.components.drawers.documentation-drawers.component-spec] [quo2.components.drawers.drawer-buttons.component-spec] + [quo2.components.drawers.drawer-top.component-spec] [quo2.components.drawers.permission-context.component-spec] [quo2.components.dropdowns.network-dropdown.component-spec] [quo2.components.gradient.gradient-cover.component-spec] diff --git a/src/quo2/foundations/colors.cljs b/src/quo2/foundations/colors.cljs index 45bac2dad7..e2892b8c72 100644 --- a/src/quo2/foundations/colors.cljs +++ b/src/quo2/foundations/colors.cljs @@ -222,6 +222,18 @@ :magenta {50 "#EC266C" 60 "#BD1E56"}}) +;;;; Networks + +(def networks + {:ethereum "#758EEB" + :optimism "#E76E6E" + :arbitrum "#6BD5F0" + :zkSync "#9FA0FE" + :hermez "#EB8462" + :xDai "#3FC0BD" + :polygon "#AD71F3" + :unknown "#EEF2F5"}) + (def colors-map (merge {:primary {50 primary-50 ;; User can also use primary color as customisation color 60 primary-60} @@ -241,7 +253,12 @@ 60 danger-60} :success {50 success-50 60 success-60}} - customization)) + customization + networks)) + +(defn hex-string? + [s] + (and (string? s) (string/starts-with? s "#"))) (def custom-color "(custom-color color suffix opacity) @@ -250,18 +267,20 @@ opacity 0-100 (optional)" (memoize (fn + ([color] + (custom-color color nil nil)) ([color suffix] (custom-color color suffix nil)) ([color suffix opacity] - (let [hex? (not (keyword? color)) - color-keyword (keyword color) - base-color (get-in colors-map - [color-keyword suffix])] + (let [hex? (not (keyword? color)) + color (if (hex-string? (get colors-map color)) + (get colors-map color) + (get-in colors-map [color suffix]))] (cond (and opacity hex?) (alpha color (/ opacity 100)) - opacity (alpha base-color (/ opacity 100)) + opacity (alpha color (/ opacity 100)) hex? color - :else base-color)))))) + :else color)))))) (defn custom-color-by-theme "(custom-color-by-theme color suffix-light suffix-dark opacity-light opacity-dark) @@ -299,15 +318,3 @@ (defn dark? [] (theme/dark?)) - -;;;; Networks - -(def networks - {:ethereum "#758EEB" - :optimism "#E76E6E" - :arbitrum "#6BD5F0" - :zkSync "#9FA0FE" - :hermez "#EB8462" - :xDai "#3FC0BD" - :polygon "#AD71F3" - :unknown "#EEF2F5"}) diff --git a/src/status_im2/contexts/quo_preview/drawers/drawer_top.cljs b/src/status_im2/contexts/quo_preview/drawers/drawer_top.cljs new file mode 100644 index 0000000000..313f88a684 --- /dev/null +++ b/src/status_im2/contexts/quo_preview/drawers/drawer_top.cljs @@ -0,0 +1,71 @@ +(ns status-im2.contexts.quo-preview.drawers.drawer-top + (:require [quo2.core :as quo] + [reagent.core :as reagent] + [status-im2.common.resources :as resources] + [status-im2.contexts.quo-preview.preview :as preview] + [utils.re-frame :as rf] + [react-native.core :as rn] + [status-im.multiaccounts.core :as multiaccounts])) + +(def descriptor + [{:type :select + :key :type + :options [{:key :default} + {:key :default-keypair} + {:key :account} + {:key :keypair} + {:key :info} + {:key :context-tag} + {:key :label}]} + {:type :select + :key :button-icon + :options [{:key :i/placeholder} + {:key nil + :value "null"}]} + {:key :blur? + :type :boolean} + {:key :keycard? + :type :boolean} + {:key :title + :type :text} + {:key :description + :type :text} + {:key :community-name + :type :text} + {:key :label + :type :text}]) + +(defn view + [] + (let [account (rf/sub [:profile/multiaccount]) + state (reagent/atom + {:blur? false + :title "Title" + :type :default + :label "Drawer label" + :keycard? true + :networks [:ethereum] + :description "0x62b...0a5" + :button-icon :i/placeholder + :community-name "Coinbase" + :community-logo (resources/mock-images :coinbase) + :account-avatar-emoji "🍿" + :customization-color :purple + :icon-avatar :i/placeholder + :on-button-press #(js/alert "on press") + :on-button-long-press #(js/alert "on long press") + :profile-picture (multiaccounts/displayed-photo account)})] + (fn [] + [preview/preview-container + {:state state + :descriptor descriptor + :blur? (:blur? @state) + :show-blur-background? true} + [quo/button + {:container-style {:margin-horizontal 40} + :on-press #(rf/dispatch [:show-bottom-sheet + {:content (fn [] [quo/drawer-top @state]) + :theme (:theme @state)}])} + "See in bottom sheet"] + [rn/view {:style {:margin-top 20}} + [quo/drawer-top @state]]]))) diff --git a/src/status_im2/contexts/quo_preview/main.cljs b/src/status_im2/contexts/quo_preview/main.cljs index f1d7cb18d2..0a71a23152 100644 --- a/src/status_im2/contexts/quo_preview/main.cljs +++ b/src/status_im2/contexts/quo_preview/main.cljs @@ -45,6 +45,7 @@ [status-im2.contexts.quo-preview.drawers.action-drawers :as action-drawers] [status-im2.contexts.quo-preview.drawers.documentation-drawers :as documenation-drawers] [status-im2.contexts.quo-preview.drawers.drawer-buttons :as drawer-buttons] + [status-im2.contexts.quo-preview.drawers.drawer-top :as drawer-top] [status-im2.contexts.quo-preview.drawers.permission-drawers :as permission-drawers] [status-im2.contexts.quo-preview.dropdowns.dropdown :as dropdown] [status-im2.contexts.quo-preview.dropdowns.network-dropdown :as network-dropdown] @@ -209,6 +210,8 @@ :component documenation-drawers/view} {:name :drawer-buttons :component drawer-buttons/view} + {:name :drawer-top + :component drawer-top/view} {:name :permission-drawers :component permission-drawers/view}] :dropdowns [{:name :dropdown