diff --git a/src/quo2/components/colors/color_picker/component_spec.cljs b/src/quo2/components/colors/color_picker/component_spec.cljs new file mode 100644 index 0000000000..2831f1a176 --- /dev/null +++ b/src/quo2/components/colors/color_picker/component_spec.cljs @@ -0,0 +1,23 @@ +(ns quo2.components.colors.color-picker.component-spec + (:require [quo2.components.colors.color-picker.view :as color-picker] + [reagent.core :as reagent] + [test-helpers.component :as h])) + +(h/describe "color-picker" + (h/test "color picker rendered" + (h/render [color-picker/view]) + (-> (h/expect (h/get-all-by-label-text :color-picker-item)) + (.toHaveLength 12))) + (h/test "clicks on a color item" + (let [event (h/mock-fn)] + (h/render [color-picker/view {:on-change #(event)}]) + (h/fire-event :press (get (h/get-all-by-label-text :color-picker-item) 0)) + (-> (h/expect event) + (.toHaveBeenCalled)))) + (h/test "color picker color changed" + (let [selected (reagent/atom nil)] + (h/render [color-picker/view {:on-change #(reset! selected %)}]) + (h/fire-event :press (get (h/get-all-by-label-text :color-picker-item) 0)) + (-> (h/expect @selected) + (.toStrictEqual :blue))))) + diff --git a/src/quo2/components/colors/color_picker/style.cljs b/src/quo2/components/colors/color_picker/style.cljs new file mode 100644 index 0000000000..47952f0773 --- /dev/null +++ b/src/quo2/components/colors/color_picker/style.cljs @@ -0,0 +1,48 @@ +(ns quo2.components.colors.color-picker.style + (:require [quo2.foundations.colors :as colors])) + +(def color-picker-container + {:max-width 338 + :flex-direction :row + :flex-wrap :wrap + :justify-content :space-between}) + +(def flex-break + {:flex-basis "100%" + :height 10}) + +(defn color-button + [color selected?] + (merge {:width 48 + :height 48 + :border-width 4 + :border-radius 24 + :transform [{:rotate "45deg"}] + :border-color :transparent} + (when selected? + {:border-top-color (colors/alpha color 0.4) + :border-end-color (colors/alpha color 0.4) + :border-bottom-color (colors/alpha color 0.2) + :border-start-color (colors/alpha color 0.2)}))) + +(defn color-circle + [color border?] + {:width 40 + :height 40 + :transform [{:rotate "-45deg"}] + :background-color color + :justify-content :center + :align-items :center + :border-color color + :border-width (if border? 2 0) + :overflow :hidden + :border-radius 20}) + +(defn secondary-overlay + [secondary-color border?] + {:width (if border? 18 20) + :height 40 + :position :absolute + :right 0 + :background-color secondary-color}) + diff --git a/src/quo2/components/colors/color_picker/view.cljs b/src/quo2/components/colors/color_picker/view.cljs new file mode 100644 index 0000000000..ab126ae905 --- /dev/null +++ b/src/quo2/components/colors/color_picker/view.cljs @@ -0,0 +1,71 @@ +(ns quo2.components.colors.color-picker.view + (:require [react-native.core :as rn] + [quo2.foundations.colors :as colors] + [quo2.components.icon :as icon] + [reagent.core :as reagent] + [quo2.components.colors.color-picker.style :as style])) + +(def color-list [:blue :yellow :turquoise :copper :sky :camel :orange :army :pink :purple :magenta]) + +(defn picker-colors + [blur?] + (concat (map (fn [color] + {:name color + :color (colors/custom-color-by-theme color (if blur? 60 50) 60)}) + color-list) + [{:name :yinyang + :color (colors/theme-colors (colors/custom-color :yin 50) + (colors/custom-color :yang 50)) + :secondary-color (colors/theme-colors (colors/custom-color :yang 50) + (colors/custom-color :yin 50))}])) + +(defn- on-change-handler + [selected color-name on-change] + (reset! selected color-name) + (when on-change (on-change color-name))) + +(defn- color-item + [{:keys [name + color + secondary-color + selected? + on-press + blur?]}] + (let [border? (and (not blur?) (and secondary-color (not selected?)))] + [rn/touchable-opacity + {:style (style/color-button color selected?) + :accessibility-label :color-picker-item + :on-press #(on-press name)} + [rn/view + {:style (style/color-circle color border?)} + (when (and secondary-color (not selected?)) + [rn/view + {:style (style/secondary-overlay secondary-color border?)}]) + (when selected? + [icon/icon :i/check + {:size 20 + :color (or secondary-color + colors/white)}])]])) + +(defn view + "Options + - `default-selected?` Default selected color name. + - `selected` Selected color name. + - `on-change` Callback called when a color is selected `(fn [color-name])`. + - `blur?` Boolean to enable blur background support.}" + [{:keys [default-selected?]}] + (let [internal-selected (reagent/atom default-selected?)] + (fn [{:keys [blur? on-change selected]}] + (when (and (not (nil? selected)) (not= @internal-selected selected)) + (reset! internal-selected selected)) + [rn/view {:style style/color-picker-container} + (doall (map-indexed (fn [index color] + [:<> {:key (color :name)} + [color-item + (merge color + {:selected? (= (color :name) @internal-selected) + :on-press #(on-change-handler internal-selected % on-change) + :blur? blur?})] + (when (= index 5) [rn/view {:style style/flex-break}])]) + (picker-colors blur?)))]))) + diff --git a/src/quo2/core.cljs b/src/quo2/core.cljs index 759b817b4f..5e229d4b55 100644 --- a/src/quo2/core.cljs +++ b/src/quo2/core.cljs @@ -10,6 +10,7 @@ quo2.components.banners.banner.view quo2.components.buttons.button quo2.components.buttons.dynamic-button + quo2.components.colors.color-picker.view quo2.components.community.community-card-view quo2.components.community.community-list-view quo2.components.community.community-view @@ -106,6 +107,10 @@ ;;;; CARDS (def small-option-card quo2.components.onboarding.small-option-card.view/small-option-card) +;;;; COLORS +(def color-picker quo2.components.colors.color-picker.view/view) +(def picker-colors quo2.components.colors.color-picker.view/picker-colors) + ;;;; COMMUNITY (def community-card-view-item quo2.components.community.community-card-view/community-card-view-item) (def communities-list-view-item quo2.components.community.community-list-view/communities-list-view-item) diff --git a/src/quo2/core_spec.cljs b/src/quo2/core_spec.cljs index bdda70e934..5b8c36025f 100644 --- a/src/quo2/core_spec.cljs +++ b/src/quo2/core_spec.cljs @@ -6,6 +6,7 @@ [quo2.components.drawers.action-drawers.component-spec] [quo2.components.drawers.drawer-buttons.component-spec] [quo2.components.drawers.permission-context.component-spec] + [quo2.components.colors.color-picker.component-spec] [quo2.components.markdown.--tests--.text-component-spec] [quo2.components.onboarding.small-option-card.component-spec] [quo2.components.record-audio.record-audio.--tests--.record-audio-component-spec] diff --git a/src/quo2/foundations/colors.cljs b/src/quo2/foundations/colors.cljs index 9f9be077e9..ffc7c9f165 100644 --- a/src/quo2/foundations/colors.cljs +++ b/src/quo2/foundations/colors.cljs @@ -170,26 +170,40 @@ (def customization {:primary {50 primary-50 ;; User can also use primary color as customisation color 60 primary-60} - :purple {50 "#8661C1" - 60 "#5E478C"} + :purple {50 "#7140FD" + 60 "#5A33CA"} :indigo {50 "#496289" 60 "#3D5273"} - :turquoise {50 "#448EA2" - 60 "#397788"} - :blue {50 "#4CB4EF" - 60 "#4097C9"} + :turquoise {50 "#2A799B" + 60 "#22617C"} + :blue {50 "#2A4AF5" + 60 "#223BC4"} :green {50 "#5BCC95" 60 "#4CAB7D"} - :yellow {50 "#FFCB53" - 60 "#D6AA46"} - :orange {50 "#FB8F61" - 60 "#D37851"} + :yellow {50 "#F6B03C" + 60 "#C58D30"} + :orange {50 "#FF7D46" + 60 "#CC6438"} :red {50 "#F46666" 60 "#CD5656"} - :pink {50 "#FC7BAB" - 60 "#D46790"} + :pink {50 "#F66F8F" + 60 "#C55972"} :brown {50 "#99604D" 60 "#805141"} + :sky {50 "#1992D7" + 60 "#1475AC"} + :army {50 "#216266" + 60 "#1A4E52"} + :magenta {50 "#EC266C" + 60 "#BD1E56"} + :copper {50 "#CB6256" + 60 "#A24E45"} + :camel {50 "#C78F67" + 60 "#9F7252"} + :yin {50 "#09101C" + 60 "#1D232E"} + :yang {50 "#FFFFFF" + 60 "#EBEBEB"} :beige {50 "#CAAE93" 60 "#AA927C"}}) diff --git a/src/status_im2/contexts/quo_preview/colors/color_picker.cljs b/src/status_im2/contexts/quo_preview/colors/color_picker.cljs new file mode 100644 index 0000000000..310a87f85a --- /dev/null +++ b/src/status_im2/contexts/quo_preview/colors/color_picker.cljs @@ -0,0 +1,46 @@ +(ns status-im2.contexts.quo-preview.colors.color-picker + (:require [react-native.core :as rn] + [quo2.foundations.colors :as colors] + [reagent.core :as reagent] + [quo2.core :as quo] + [react-native.blur :as blur] + [status-im2.contexts.quo-preview.preview :as preview])) + +(def descriptor + [{:label "Color:" + :key :color + :type :select + :options (map (fn [color] (let [key (get color :name)] {:key key :value key})) (quo/picker-colors))} + {:label "Blur:" + :key :blur + :type :boolean}]) + +(defn cool-preview + [] + (let [state (reagent/atom {:color "orange" :blur false}) + blur (reagent/cursor state [:blur]) + color (reagent/cursor state [:color])] + (fn [] + [rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!} + [rn/view {:padding-bottom 150} + [preview/customizer state descriptor] + [(if @blur blur/view :<>) + [rn/view {:padding-vertical 60 :align-items :center} + [quo/color-picker + {:blur? @blur + :selected @color + :on-change #(reset! color %)}]]]]]))) + +(defn preview-color-picker + [] + [rn/view + {:background-color (colors/theme-colors + colors/white + colors/neutral-95) + :flex 1} + [rn/flat-list + {:flex 1 + :keyboardShouldPersistTaps :always + :header [cool-preview] + :key-fn str}]]) + diff --git a/src/status_im2/contexts/quo_preview/main.cljs b/src/status_im2/contexts/quo_preview/main.cljs index 89882e5e0b..0cbbb28f88 100644 --- a/src/status_im2/contexts/quo_preview/main.cljs +++ b/src/status_im2/contexts/quo_preview/main.cljs @@ -19,6 +19,7 @@ [status-im2.contexts.quo-preview.buttons.button :as button] [status-im2.contexts.quo-preview.buttons.dynamic-button :as dynamic-button] [status-im2.contexts.quo-preview.code.snippet :as code-snippet] + [status-im2.contexts.quo-preview.colors.color-picker :as color-picker] [status-im2.contexts.quo-preview.community.community-card-view :as community-card] [status-im2.contexts.quo-preview.community.community-list-view :as community-list-view] [status-im2.contexts.quo-preview.community.community-membership-list-view :as @@ -110,6 +111,9 @@ :code [{:name :snippet :insets {:top false} :component code-snippet/preview-code-snippet}] + :colors [{:name :color-picker + :insets {:top false} + :component color-picker/preview-color-picker}] :community [{:name :community-card-view :insets {:top false} :component community-card/preview-community-card} diff --git a/src/test_helpers/component.cljs b/src/test_helpers/component.cljs index 52119ed515..ee10412089 100644 --- a/src/test_helpers/component.cljs +++ b/src/test_helpers/component.cljs @@ -34,6 +34,10 @@ [label] (rtl/screen.getByLabelText (name label))) +(defn get-all-by-label-text + [label] + (rtl/screen.getAllByLabelText (name label))) + (defn expect [match] (js/expect match)) (defn use-fake-timers [] (js/jest.useFakeTimers))