From 8fdfeb5e45b09a5ff9e1fd08fc86e30af226e01e Mon Sep 17 00:00:00 2001 From: Icaro Motta Date: Wed, 14 Jun 2023 15:07:46 -0300 Subject: [PATCH] Various fixes for the Information Box component (#16272) Fixes UI bugs described in https://github.com/status-im/status-mobile/issues/16271, and it also rewrites the component to follow our guidelines i.e. move code to style namespace, fix docstring, add component specs, move to separate quo2 directory, etc. This commit is part of the effort to fix the Community Overview screen. --- src/quo2/components/info/information_box.cljs | 102 ------------------ .../info/information_box/component_spec.cljs | 30 ++++++ .../info/information_box/style.cljs | 65 +++++++++++ .../components/info/information_box/view.cljs | 79 ++++++++++++++ src/quo2/core.cljs | 4 +- .../quo_preview/info/information_box.cljs | 38 ++++--- 6 files changed, 199 insertions(+), 119 deletions(-) delete mode 100644 src/quo2/components/info/information_box.cljs create mode 100644 src/quo2/components/info/information_box/component_spec.cljs create mode 100644 src/quo2/components/info/information_box/style.cljs create mode 100644 src/quo2/components/info/information_box/view.cljs diff --git a/src/quo2/components/info/information_box.cljs b/src/quo2/components/info/information_box.cljs deleted file mode 100644 index 8c309e26af..0000000000 --- a/src/quo2/components/info/information_box.cljs +++ /dev/null @@ -1,102 +0,0 @@ -(ns quo2.components.info.information-box - (:require [clojure.string :as string] - [quo2.components.buttons.button :as quo2.button] - [quo2.components.icon :as quo2.icons] - [quo2.components.info.info-message :as info-message] - [quo2.foundations.colors :as colors] - [quo2.theme :as theme] - [react-native.core :as rn])) - -(def themes - {:light {:default {:bg colors/white - :border colors/neutral-20 - :icon colors/neutral-50 - :text colors/neutral-100} - :informative {:bg colors/primary-50-opa-5 - :border colors/primary-50-opa-10 - :icon colors/primary-50 - :text colors/neutral-100} - :error {:bg colors/danger-50-opa-5 - :border colors/danger-50-opa-10 - :icon colors/danger-50 - :text colors/danger-50} - :close-button colors/neutral-100} - :dark {:default {:bg colors/neutral-90 - :border colors/neutral-70 - :icon colors/neutral-40 - :text colors/white} - :informative {:bg colors/primary-50-opa-5 - :border colors/primary-50-opa-10 - :icon colors/white - :text colors/white} - :error {:bg colors/danger-50-opa-5 - :border colors/danger-50-opa-10 - :icon colors/danger-50 - :text colors/danger-50} - :close-button colors/white}}) - -(defn get-color - [key] - (get-in themes [(theme/get-theme) key])) - -(defn get-color-by-type - [type key] - (get-in themes [(theme/get-theme) type key])) - -(defn information-box - "[information-box opts \"message\"] - opts - {:type :default/:informative/:error - :closable? true/false ;; allow information box to be closed? - :closed? true/false ;; information box's state - :id :information-box-id ;; unique id (required for closable? information box) - :icon :main-icons/info ;; information box icon - :no-icon-color? false ;; disable tint color for icon - :style style - :button-label \"PressMe\" ;; add action button with label - :on-button-press action ;; (required for information box with button-label) - :on-close on-close ;; (optional on-close call)" - [{:keys [type closable? closed? id icon style button-label on-button-press on-close no-icon-color?]} - message] - (let [background-color (get-color-by-type type :bg) - border-color (get-color-by-type type :border) - icon-color (get-color-by-type type :icon) - text-color (get-color-by-type type :text) - include-button? (not (string/blank? button-label))] - (when-not closed? - [rn/view - {:accessibility-label (or id :information-box) - :style (merge {:background-color background-color - :border-color border-color - :border-width 1 - :border-radius 12 - :padding-top (if include-button? 10 11) - :padding-bottom (if include-button? 12 11) - :padding-horizontal 16} - style)} - [rn/view - {:style {:flex-direction :row - :align-self :flex-start}} - [info-message/info-message - {:size :default - :icon icon - :text-color text-color - :icon-color icon-color - :no-icon-color? no-icon-color?} message] - (when closable? - [rn/touchable-opacity - {:on-press on-close - :accessibility-label (str (or id "information-box") "-close-button")} - [quo2.icons/icon :i/close - {:size 12 - :color (get-color :close-button) - :container-style {:margin-top 4 - :margin-left 8}}]])] - (when include-button? - [quo2.button/button - {:type :primary - :size 24 - :on-press on-button-press - :style {:margin-left 20 - :margin-top 8 - :align-self :flex-start}} button-label])]))) diff --git a/src/quo2/components/info/information_box/component_spec.cljs b/src/quo2/components/info/information_box/component_spec.cljs new file mode 100644 index 0000000000..64685a50f2 --- /dev/null +++ b/src/quo2/components/info/information_box/component_spec.cljs @@ -0,0 +1,30 @@ +(ns quo2.components.info.information-box.component-spec + (:require [quo2.components.info.information-box.view :as view] + [test-helpers.component :as h])) + +(h/describe "Info - Information Box" + (h/test "default render" + (h/render [view/view {:icon :i/placeholder} + "Lorem ipsum"]) + (h/is-null (h/query-by-label-text :information-box-action-button)) + (h/is-null (h/query-by-label-text :information-box-close-button))) + + (h/test "with close button" + (let [on-close (h/mock-fn)] + (h/render [view/view + {:icon :i/placeholder + :on-close on-close} + "Lorem ipsum"]) + (h/is-null (h/query-by-label-text :information-box-action-button)) + (h/fire-event :on-press (h/get-by-label-text :information-box-close-button)) + (h/was-called on-close))) + + (h/test "with button" + (let [on-press (h/mock-fn)] + (h/render [view/view + {:icon :i/placeholder + :button-label "Press me" + :on-button-press on-press} + "Lorem ipsum"]) + (h/fire-event :on-press (h/get-by-label-text :information-box-action-button)) + (h/was-called on-press)))) diff --git a/src/quo2/components/info/information_box/style.cljs b/src/quo2/components/info/information_box/style.cljs new file mode 100644 index 0000000000..c250856cd6 --- /dev/null +++ b/src/quo2/components/info/information_box/style.cljs @@ -0,0 +1,65 @@ +(ns quo2.components.info.information-box.style + (:require [quo2.foundations.colors :as colors])) + +(def ^:private themes + {:light {:default {:bg colors/white + :border colors/neutral-20 + :icon colors/neutral-50 + :text colors/neutral-100} + :informative {:bg colors/primary-50-opa-5 + :border colors/primary-50-opa-10 + :icon colors/primary-50 + :text colors/neutral-100} + :error {:bg colors/danger-50-opa-5 + :border colors/danger-50-opa-10 + :icon colors/danger-50 + :text colors/danger-50} + :close-button colors/neutral-100} + :dark {:default {:bg colors/neutral-90 + :border colors/neutral-70 + :icon colors/neutral-40 + :text colors/white} + :informative {:bg colors/primary-50-opa-5 + :border colors/primary-50-opa-10 + :icon colors/white + :text colors/white} + :error {:bg colors/danger-50-opa-5 + :border colors/danger-50-opa-10 + :icon colors/danger-50 + :text colors/danger-50} + :close-button colors/white}}) + +(defn get-color + [theme key] + (get-in themes [theme key])) + +(defn get-color-by-type + [theme type key] + (get-in themes [theme type key])) + +(defn container + [{:keys [theme type include-button?]}] + {:background-color (get-color-by-type theme type :bg) + :border-color (get-color-by-type theme type :border) + :border-width 1 + :border-radius 12 + :padding-top (if include-button? 10 11) + :padding-bottom (if include-button? 12 11) + :flex-direction :row + :padding-horizontal 16}) + +(def icon + {:margin-top 1 :margin-right 8}) + +(def close-button + {:margin-top 4 + :margin-left 8}) + +(defn content-text + [theme type] + {:color (get-color-by-type theme type :text) + :margin-right 8}) + +(def content-button + {:margin-top 8 + :align-self :flex-start}) diff --git a/src/quo2/components/info/information_box/view.cljs b/src/quo2/components/info/information_box/view.cljs new file mode 100644 index 0000000000..e08a73ed8d --- /dev/null +++ b/src/quo2/components/info/information_box/view.cljs @@ -0,0 +1,79 @@ +(ns quo2.components.info.information-box.view + (:require [clojure.string :as string] + [quo2.components.buttons.button :as button] + [quo2.components.icon :as icons] + [quo2.components.info.information-box.style :as style] + [quo2.components.markdown.text :as text] + [quo2.theme :as theme] + [react-native.core :as rn])) + +(defn- info-type->button-type + [type] + (if (= type :error) + :danger + :primary)) + +(defn- close-button + [{:keys [theme on-close]}] + [rn/touchable-opacity + {:on-press on-close + :hit-slop {:top 3 :right 3 :bottom 3 :left 3} + :accessibility-label :information-box-close-button} + [icons/icon :i/close + {:size 12 + :color (style/get-color theme :close-button) + :container-style style/close-button}]]) + +(defn- content + [{:keys [theme type button-label on-button-press message]}] + [rn/view {:style {:flex 1}} + [text/text + {:size :paragraph-2 + :style (style/content-text theme type)} + message] + (when (not (string/blank? button-label)) + [button/button + {:type (info-type->button-type type) + :accessibility-label :information-box-action-button + :size 24 + :on-press on-button-press + :style style/content-button} + button-label])]) + +(defn view + "[view opts \"message\"] + opts + {:type :default/:informative/:error + :closed? bool (false) ;; Information box's state + :icon keyword, required (:i/info) + :icon-size int (16) + :no-icon-color? bool (false) + :style map + :button-label string + :on-button-press function + :on-close function" + [{:keys [type closed? icon style button-label + on-button-press on-close no-icon-color? icon-size]} + message] + (when-not closed? + (let [theme (theme/get-theme) + include-button? (not (string/blank? button-label))] + [rn/view + {:accessibility-label :information-box + :style (merge (style/container {:theme theme + :type type + :include-button? include-button?}) + style)} + [icons/icon icon + {:color (style/get-color-by-type theme type :icon) + :no-color no-icon-color? + :size (or icon-size 16) + :container-style style/icon}] + [content + {:theme theme + :type type + :button-label button-label + :on-button-press on-button-press + :message message}] + (when on-close + [close-button {:theme theme :on-close on-close}])]))) diff --git a/src/quo2/core.cljs b/src/quo2/core.cljs index 8028fd9f6e..b68988be3e 100644 --- a/src/quo2/core.cljs +++ b/src/quo2/core.cljs @@ -33,7 +33,7 @@ quo2.components.empty-state.empty-state.view quo2.components.icon quo2.components.info.info-message - quo2.components.info.information-box + quo2.components.info.information-box.view quo2.components.inputs.input.view quo2.components.inputs.profile-input.view quo2.components.inputs.recovery-phrase.view @@ -94,7 +94,7 @@ (def header quo2.components.header/header) (def dropdown quo2.components.dropdowns.dropdown/dropdown) (def info-message quo2.components.info.info-message/info-message) -(def information-box quo2.components.info.information-box/information-box) +(def information-box quo2.components.info.information-box.view/view) (def gap quo2.components.messages.gap/gap) (def system-message quo2.components.messages.system-message/system-message) (def reaction quo2.components.reactions.reaction/reaction) diff --git a/src/status_im2/contexts/quo_preview/info/information_box.cljs b/src/status_im2/contexts/quo_preview/info/information_box.cljs index 9f5ef275d5..d6248edba3 100644 --- a/src/status_im2/contexts/quo_preview/info/information_box.cljs +++ b/src/status_im2/contexts/quo_preview/info/information_box.cljs @@ -1,5 +1,5 @@ (ns status-im2.contexts.quo-preview.info.information-box - (:require [quo2.components.info.information-box :as quo2] + (:require [quo2.core :as quo] [quo2.foundations.colors :as colors] [react-native.core :as rn] [reagent.core :as reagent] @@ -15,7 +15,7 @@ :value "Informative"} {:key :error :value "Error"}]} - {:label "Closable?:" + {:label "Closable?" :key :closable? :type :boolean} {:label "Message" @@ -27,23 +27,31 @@ (defn cool-preview [] - (let [state (reagent/atom {:type :default - :closable? true - :icon :i/placeholder - :message "This is an information box This is an information" - :button-label "Press Me" - :style {:width 335} - :id (keyword (str "id-" (rand-int 10000)))}) - closed? (reagent/cursor state [:closed?]) - on-close #(reset! closed? true)] + (let [state (reagent/atom + {:type :default + :closable? true + :message (str "If you registered a stateofus.eth name " + "you might be eligible to connect $ENS") + :button-label "Button"}) + closable? (reagent/cursor state [:closable?]) + closed? (reagent/cursor state [:closed?]) + on-close (fn [] + (reset! closed? true) + (js/setTimeout (fn [] (reset! closed? false)) + 2000))] (fn [] [rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!} - [rn/view {:padding-bottom 150} + [rn/view [preview/customizer state descriptor] [rn/view - {:padding-vertical 60 - :align-items :center} - [quo2/information-box (merge @state {:on-close on-close}) (:message @state)]]]]))) + {:style {:padding-vertical 20 + :align-items :center}} + [quo/information-box + (merge {:icon :i/info + :style {:width 335} + :on-close (when @closable? on-close)} + @state) + (:message @state)]]]]))) (defn preview-information-box []