From 1cdcd298b0e33868a28dbed725b88c0f2e623fce Mon Sep 17 00:00:00 2001 From: John Ngei Date: Sun, 8 Jan 2023 22:40:59 +0300 Subject: [PATCH] Scrollable tags (#14182) * refactored scrollable-tags to share the same logic with scrollable-tabs * refactored tabs component to support scrollable-behaviour --- .../components/community/community_view.cljs | 12 +- src/quo2/components/tabs/tabs.cljs | 267 +++++++++--------- src/quo2/components/tags/base_tag.cljs | 14 +- src/quo2/components/tags/tag.cljs | 50 ++-- src/quo2/components/tags/tags.cljs | 194 +++++++++++-- src/quo2/core.cljs | 1 - .../contexts/activity_center/view.cljs | 3 +- .../contexts/quo_preview/tabs/tabs.cljs | 14 +- .../contexts/quo_preview/tags/tag.cljs | 98 +++++++ .../contexts/quo_preview/tags/tags.cljs | 107 ++++--- 10 files changed, 520 insertions(+), 240 deletions(-) create mode 100644 src/status_im2/contexts/quo_preview/tags/tag.cljs diff --git a/src/quo2/components/community/community_view.cljs b/src/quo2/components/community/community_view.cljs index fbe6c02036..983328b4b9 100644 --- a/src/quo2/components/community/community_view.cljs +++ b/src/quo2/components/community/community_view.cljs @@ -46,12 +46,12 @@ ^{:key id} [rn/view {:margin-right 8} [tag/tag - {:id id - :size 24 - :label tag-label - :type :emoji - :labelled true - :resource resource}]])]) + {:id id + :size 24 + :label tag-label + :type :emoji + :labelled? true + :resource resource}]])]) (defn community-title [{:keys [title description size] :or {size :small}}] diff --git a/src/quo2/components/tabs/tabs.cljs b/src/quo2/components/tabs/tabs.cljs index b8cc323740..1231bc79a6 100644 --- a/src/quo2/components/tabs/tabs.cljs +++ b/src/quo2/components/tabs/tabs.cljs @@ -28,28 +28,6 @@ :background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}} [notification-dot]]) -(defn tabs - [{:keys [default-active on-change style]}] - (let [active-tab-id (reagent/atom default-active)] - (fn [{:keys [data size] :or {size default-tab-size}}] - [rn/view (merge {:flex-direction :row} style) - (doall - (for [{:keys [label id notification-dot? accessibility-label]} data] - ^{:key id} - [rn/view {:style {:margin-right (if (= size default-tab-size) 12 8)}} - (when notification-dot? - [indicator]) - [tab/tab - {:id id - :size size - :accessibility-label accessibility-label - :active (= id @active-tab-id) - :on-press (fn [] - (reset! active-tab-id id) - (when on-change - (on-change id)))} - label]]))]))) - (defn- calculate-fade-end-percentage [{:keys [offset-x content-width layout-width max-fade-percentage]}] (let [fade-percentage (max max-fade-percentage @@ -60,30 +38,35 @@ 0.99 (utils.number/naive-round fade-percentage 2)))) -(defn scrollable-tabs - "Just like the component `tabs`, displays horizontally scrollable tabs with - extra options to control if/how the end of the scroll view fades. - - Tabs are rendered using ReactNative's FlatList, which offers the convenient - `scrollToIndex` method. FlatList accepts VirtualizedList and ScrollView props, - and so does this component. - - Usage: - [tabs/scrollable-tabs - {:scroll-on-press? true - :fade-end? true - :on-change #(...) - :default-active :tab-a - :data [{:id :tab-a :label \"Tab A\"} - {:id :tab-b :label \"Tab B\"}]}]] - +(defn tabs + "Usage: + {:type :icon/:emoji/:label + :component tag/tab + :size 32/24 + :on-press fn + :blurred? true/false + :labelled? true/false + :disabled? true/false + :scrollable? false + :scroll-on-press? true + :fade-end? true + :on-change fn + :default-active tag-id + :data [{:id :label \"\" :resource \"url\"} + {:id :label \"\" :resource \"url\"}]} Opts: - - `size` number - - `scroll-on-press?` When non-nil, clicking on a tab centers it the middle + - `component` this is to determine which component is to be rendered since the + logic in this view is shared between tab and tag component + - `blurred` boolean: use to determine border color if the background is blurred + - `type` can be icon or emoji with or without a tag label + - `labelled` boolean: is true if tag has label else false + - `size` number + - `scroll-on-press?` When non-nil, clicking on a tag centers it the middle (with animation enabled). - - `fade-end?` When non-nil, causes the end of the scrollable view to fade out. - - `fade-end-percentage` Percentage where fading starts relative to the total + - `fade-end?` When non-nil, causes the end of the scrollable view to fade out. + - `fade-end-percentage` Percentage where fading starts relative to the total layout width of the `flat-list` data." + [{:keys [default-active fade-end-percentage] :or {fade-end-percentage 0.8}}] (let [active-tab-id (reagent/atom default-active) @@ -97,99 +80,123 @@ on-scroll scroll-event-throttle scroll-on-press? + scrollable? + style size blur? override-theme] :or {fade-end-percentage fade-end-percentage fade-end? false scroll-event-throttle 64 + scrollable? false scroll-on-press? false size default-tab-size} :as props}] - (let [maybe-mask-wrapper (if fade-end? - [masked-view/masked-view - {:mask-element - (reagent/as-element - [linear-gradient/linear-gradient - {:colors [:black :transparent] - :locations [(get @fading :fade-end-percentage) 1] - :start {:x 0 :y 0} - :end {:x 1 :y 0} - :pointer-events :none - :style {:width "100%" - :height "100%"}}])}] - [:<>])] - (conj - maybe-mask-wrapper - [rn/flat-list - (merge - (dissoc props - :default-active - :fade-end-percentage - :fade-end? - :on-change - :scroll-on-press? - :size) - (when scroll-on-press? - {:initial-scroll-index (utils.collection/first-index #(= @active-tab-id (:id %)) data)}) - {:ref #(reset! flat-list-ref %) - :extra-data (str @active-tab-id) - :horizontal true - :scroll-event-throttle scroll-event-throttle - :shows-horizontal-scroll-indicator false - :data data - :key-fn (comp str :id) - :on-scroll-to-index-failed identity - :on-scroll (fn [^js e] - (when fade-end? - (let [offset-x (oget - e - "nativeEvent.contentOffset.x") - content-width (oget - e - "nativeEvent.contentSize.width") - layout-width - (oget e "nativeEvent.layoutMeasurement.width") - new-percentage - (calculate-fade-end-percentage - {:offset-x offset-x - :content-width content-width - :layout-width layout-width - :max-fade-percentage fade-end-percentage})] - ;; Avoid unnecessary re-rendering. - (when (not= new-percentage - (get @fading :fade-end-percentage)) - (swap! fading assoc - :fade-end-percentage - new-percentage)))) - (when on-scroll - (on-scroll e))) - :render-fn (fn [{:keys [id label]} index] - [rn/view - {:style {:margin-right (if (= size default-tab-size) - 12 - 8) - :padding-right (when (= index - (dec (count data))) - (get-in props - [:style - :padding-left]))}} - [tab/tab - {:id id - :size size - :override-theme override-theme - :blur? blur? - :active (= id @active-tab-id) - :on-press (fn [id] - (reset! active-tab-id id) - (when scroll-on-press? - (.scrollToIndex ^js - @flat-list-ref - #js - {:animated true - :index index - :viewPosition - 0.5})) - (when on-change - (on-change id)))} - label]])})]))))) + (if scrollable? + (let [maybe-mask-wrapper (if fade-end? + [masked-view/masked-view + {:mask-element + (reagent/as-element + [linear-gradient/linear-gradient + {:colors [:black :transparent] + :locations [(get @fading :fade-end-percentage) 1] + :start {:x 0 :y 0} + :end {:x 1 :y 0} + :pointer-events :none + :style {:width "100%" + :height "100%"}}])}] + [:<>])] + (conj + maybe-mask-wrapper + [rn/flat-list + (merge + (dissoc props + :default-active + :fade-end-percentage + :fade-end? + :on-change + :scroll-on-press? + :size) + (when scroll-on-press? + {:initial-scroll-index (utils.collection/first-index #(= @active-tab-id (:id %)) data)}) + {:ref #(reset! flat-list-ref %) + :extra-data (str @active-tab-id) + :horizontal true + :scroll-event-throttle scroll-event-throttle + :shows-horizontal-scroll-indicator false + :data data + :key-fn (comp str :id) + :on-scroll-to-index-failed identity + :on-scroll (fn [^js e] + (when fade-end? + (let [offset-x (oget + e + "nativeEvent.contentOffset.x") + content-width + (oget + e + "nativeEvent.contentSize.width") + layout-width + (oget e + "nativeEvent.layoutMeasurement.width") + new-percentage + (calculate-fade-end-percentage + {:offset-x offset-x + :content-width content-width + :layout-width layout-width + :max-fade-percentage fade-end-percentage})] + ;; Avoid unnecessary re-rendering. + (when (not= new-percentage + (get @fading :fade-end-percentage)) + (swap! fading assoc + :fade-end-percentage + new-percentage)))) + (when on-scroll + (on-scroll e))) + :render-fn (fn [{:keys [id label]} index] + [rn/view + {:style {:margin-right (if (= size default-tab-size) + 12 + 8) + :padding-right (when (= index + (dec (count data))) + (get-in props + [:style + :padding-left]))}} + [tab/tab + {:id id + :size size + :override-theme override-theme + :blur? blur? + :active (= id @active-tab-id) + :on-press (fn [id] + (reset! active-tab-id id) + (when scroll-on-press? + (.scrollToIndex + ^js + @flat-list-ref + #js + {:animated true + :index index + :viewPosition + 0.5})) + (when on-change + (on-change id)))} + label]])})])) + [rn/view (merge {:flex-direction :row} style) + (doall + (for [{:keys [label id notification-dot? accessibility-label]} data] + ^{:key id} + [rn/view {:style {:margin-right (if (= size default-tab-size) 12 8)}} + (when notification-dot? + [indicator]) + [tab/tab + {:id id + :size size + :accessibility-label accessibility-label + :active (= id @active-tab-id) + :on-press (fn [] + (reset! active-tab-id id) + (when on-change + (on-change id)))} + label]]))])))) diff --git a/src/quo2/components/tags/base_tag.cljs b/src/quo2/components/tags/base_tag.cljs index 6329a445d6..8197cb7dc7 100644 --- a/src/quo2/components/tags/base_tag.cljs +++ b/src/quo2/components/tags/base_tag.cljs @@ -16,25 +16,21 @@ {:width size}))) (defn base-tag - "opts - {:type :icon/:emoji/:label/:permission - :size 32/24} - :labelled true" [_] - (fn [{:keys [id size disabled border-color border-width background-color on-press - accessibility-label label type] + (fn [{:keys [id size disabled? border-color border-width background-color on-press + accessibility-label labelled? type] :or {size 32}} children] [rn/touchable-without-feedback - (merge {:disabled disabled + (merge {:disabled disabled? :accessibility-label accessibility-label} (when on-press {:on-press #(on-press id)})) [rn/view {:style (merge (style-container size - disabled + disabled? border-color border-width background-color - label + labelled? type))} children]])) diff --git a/src/quo2/components/tags/tag.cljs b/src/quo2/components/tags/tag.cljs index e99663343b..56579ad751 100644 --- a/src/quo2/components/tags/tag.cljs +++ b/src/quo2/components/tags/tag.cljs @@ -68,26 +68,40 @@ label])]) (defn tag + "opts + {:type :icon/:emoji/:label + :size 32/24 + :on-press fn + :blurred? true/false + :resource icon/image + :labelled? true/false + :disabled? true/false} + + opts + - `blurred` boolean: use to determine border color if the background is blurred + - `type` can be icon or emoji with or without a tag label + - `labelled` boolean: is true if tag has label else false" [_ _] - (fn [{:keys [id on-press disabled size resource active accessibility-label - label type labelled blurred icon-color] + (fn [{:keys [id on-press disabled? size resource active accessibility-label + label type labelled? blurred? icon-color] :or {size 32}}] - (let [state (cond disabled :disabled - active :active - :else :default) + (let [state (cond disabled? :disabled + active :active + :else :default) {:keys [border-color blurred-border-color text-color]} (get-in themes [(theme/get-theme) state])] - [base-tag/base-tag - {:id id - :size size - :border-width 1 - :border-color (if blurred - blurred-border-color - border-color) - :on-press on-press - :accessibility-label accessibility-label - :disabled disabled - :type type - :label label} - [tag-resources size type resource icon-color label text-color labelled]]))) + [rn/view {:style {:align-items :center}} + [base-tag/base-tag + {:id id + :size size + :border-width 1 + :border-color (if blurred? + blurred-border-color + border-color) + :on-press on-press + :accessibility-label accessibility-label + :disabled? disabled? + :type type + :labelled? (if (= type :label) true labelled?)} + [tag-resources size type resource icon-color label text-color labelled?]]]))) diff --git a/src/quo2/components/tags/tags.cljs b/src/quo2/components/tags/tags.cljs index f5fc322d8e..d513c031a8 100644 --- a/src/quo2/components/tags/tags.cljs +++ b/src/quo2/components/tags/tags.cljs @@ -1,29 +1,171 @@ (ns quo2.components.tags.tags - (:require [quo2.components.tags.tag :as tag] - [react-native.core :as rn] - [reagent.core :as reagent])) + (:require [reagent.core :as reagent] + [quo.react-native :as rn] + [oops.core :refer [oget]] + [status-im.ui.components.react :as react] + [status-im.utils.core :as utils] + [quo2.components.tags.tag :as tag] + [utils.number :as number-utils])) + +(def default-tab-size 32) + +(defn calculate-fade-end-percentage + [{:keys [offset-x content-width layout-width max-fade-percentage]}] + (let [fade-percentage (max max-fade-percentage + (/ (+ layout-width offset-x) + content-width))] + ;; Truncate to avoid unnecessary rendering. + (if (> fade-percentage 0.99) + 0.99 + (number-utils/naive-round fade-percentage 2)))) (defn tags - [{:keys [default-active on-change]}] - (let [active-tab-id (reagent/atom default-active)] - (fn [{:keys [data size type labelled disabled blurred icon-color] :or {size 32}}] - (let [active-id @active-tab-id] - [rn/view {:flex-direction :row} - (for [{:keys [tag-label id resource]} data] - ^{:key id} - [rn/view {:margin-right 8} - [tag/tag - (merge {:id id - :size size - :type type - :label (if labelled tag-label (when (= type :label) tag-label)) - :active (= id active-id) - :disabled disabled - :blurred blurred - :icon-color icon-color - :labelled (if (= type :label) true labelled) - :resource (if (= type :icon) - :i/placeholder - resource) - :on-press #(do (reset! active-tab-id %) - (when on-change (on-change %)))})]])])))) + "Usage: + {:type :icon/:emoji/:label + :component tag/tab + :size 32/24 + :on-press fn + :blurred? true/false + :labelled? true/false + :disabled? true/false + :scroll-on-press? true + :scrollable? false + :fade-end? true + :on-change fn + :default-active tag-id + :data [{:id :label \"\" :resource \"url\"} + {:id :label \"\" :resource \"url\"}]} + Opts: + - `component` this is to determine which component is to be rendered since the + logic in this view is shared between tab and tag component + - `blurred` boolean: use to determine border color if the background is blurred + - `type` can be icon or emoji with or without a tag label + - `labelled` boolean: is true if tag has label else false + - `size` number + - `scroll-on-press?` When non-nil, clicking on a tag centers it the middle + (with animation enabled). + - `fade-end?` When non-nil, causes the end of the scrollable view to fade out. + - `fade-end-percentage` Percentage where fading starts relative to the total + layout width of the `flat-list` data." + + [{:keys [default-active fade-end-percentage] + :or {fade-end-percentage 0.8}}] + (let [active-tab-id (reagent/atom default-active) + fading (reagent/atom {:fade-end-percentage fade-end-percentage}) + flat-list-ref (atom nil)] + (fn + [{:keys [data + fade-end-percentage + fade-end? + on-change + on-scroll + scroll-event-throttle + scrollable? + scroll-on-press? + size + type + labelled? + disabled? + blurred? + icon-color] + :or {fade-end-percentage fade-end-percentage + fade-end? false + scroll-event-throttle 64 + scrollable? false + scroll-on-press? false + size default-tab-size} + :as props}] + (let [maybe-mask-wrapper (if fade-end? + [react/masked-view + {:mask-element (reagent/as-element + [react/linear-gradient + {:colors [:black :transparent] + :locations [(get @fading :fade-end-percentage) + 1] + :start {:x 0 :y 0} + :end {:x 1 :y 0} + :pointer-events :none + :style {:width "100%" + :height "100%"}}])}] + [:<>])] + (if scrollable? + (conj + maybe-mask-wrapper + [rn/flat-list + (merge (dissoc props + :default-active + :fade-end-percentage + :fade-end? + :on-change + :scroll-on-press? + :size) + (when scroll-on-press? + {:initial-scroll-index (utils/first-index #(= @active-tab-id (:id %)) data)}) + {:ref #(reset! flat-list-ref %) + :extra-data (str @active-tab-id) + :horizontal true + :scroll-event-throttle scroll-event-throttle + :shows-horizontal-scroll-indicator false + :data data + :key-fn (comp str :id) + :on-scroll (fn [^js e] + (when fade-end? + (let [offset-x (oget e "nativeEvent.contentOffset.x") + content-width (oget e "nativeEvent.contentSize.width") + layout-width (oget e "nativeEvent.layoutMeasurement.width") + new-percentage (calculate-fade-end-percentage + {:offset-x offset-x + :content-width content-width + :layout-width layout-width + :max-fade-percentage fade-end-percentage})] + ;; Avoid unnecessary re-rendering. + (when (not= new-percentage (get @fading :fade-end-percentage)) + (swap! fading assoc :fade-end-percentage new-percentage)))) + (when on-scroll + (on-scroll e))) + :render-fn (fn [{:keys [id label resource]} index] + [rn/view + {:style {:margin-right (if (= size default-tab-size) 12 8) + :padding-right (when (= index (dec (count data))) + (get-in props [:style :padding-left]))}} + [tag/tag + {:id id + :size size + :active (= id @active-tab-id) + :resource resource + :blurred? blurred? + :icon-color icon-color + :disabled? disabled? + :label label + :type type + :labelled? labelled? + :on-press (fn [id] + (reset! active-tab-id id) + (when scroll-on-press? + (.scrollToIndex @flat-list-ref + #js + {:animated true + :index index + :viewPosition 0.5})) + (when on-change + (on-change id)))} + label]])})]) + [rn/view {:style {:flex-direction :row}} + (for [{:keys [label id resource]} data] + ^{:key id} + [rn/view {:style {:margin-right 8}} + [tag/tag + (merge {:id id + :size size + :type type + :label (if labelled? label (when (= type :label) label)) + :active (= id active-tab-id) + :disabled? disabled? + :blurred? blurred? + :icon-color icon-color + :labelled? (if (= type :label) true labelled?) + :resource (if (= type :icon) + :i/placeholder + resource) + :on-press #(do (reset! active-tab-id %) + (when on-change (on-change %)))})]])]))))) diff --git a/src/quo2/core.cljs b/src/quo2/core.cljs index ea566c9f72..7054421422 100644 --- a/src/quo2/core.cljs +++ b/src/quo2/core.cljs @@ -78,7 +78,6 @@ (def audio-tag quo2.components.tags.context-tags/audio-tag) (def community-tag quo2.components.tags.context-tags/community-tag) (def tabs quo2.components.tabs.tabs/tabs) -(def scrollable-tabs quo2.components.tabs.tabs/scrollable-tabs) (def account-selector quo2.components.tabs.account-selector/account-selector) (def floating-shell-button quo2.components.navigation.floating-shell-button/floating-shell-button) (def status-tag quo2.components.tags.status-tags/status-tag) diff --git a/src/status_im2/contexts/activity_center/view.cljs b/src/status_im2/contexts/activity_center/view.cljs index 8566abb841..9b58913f60 100644 --- a/src/status_im2/contexts/activity_center/view.cljs +++ b/src/status_im2/contexts/activity_center/view.cljs @@ -42,8 +42,9 @@ (defn tabs [] (let [filter-type (rf/sub [:activity-center/filter-type])] - [quo/scrollable-tabs + [quo/tabs {:size 32 + :scrollable? true :blur? true :override-theme :dark :style style/tabs diff --git a/src/status_im2/contexts/quo_preview/tabs/tabs.cljs b/src/status_im2/contexts/quo_preview/tabs/tabs.cljs index 89e46e6ff0..83554962f1 100644 --- a/src/status_im2/contexts/quo_preview/tabs/tabs.cljs +++ b/src/status_im2/contexts/quo_preview/tabs/tabs.cljs @@ -12,11 +12,15 @@ :options [{:key 32 :value "32"} {:key 24 - :value "24"}]}]) + :value "24"}]} + {:label "Scrollable:" + :key :scrollable? + :type :boolean}]) (defn cool-preview [] - (let [state (reagent/atom {:size 32})] + (let [state (reagent/atom {:size 32 + :scrollable? false})] (fn [] [rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!} [rn/view {:padding-bottom 150} @@ -33,7 +37,11 @@ {:id 2 :label "Tab 2"} {:id 3 :label "Tab 3"} {:id 4 :label "Tab 4"}] - :on-change #(println "Active tab" %)})]]]]))) + :on-change #(println "Active tab" %)} + (when (:scrollable? @state) + {:scroll-on-press? true + :fade-end-percentage 0.4 + :fade-end? true}))]]]]))) (defn preview-tabs [] diff --git a/src/status_im2/contexts/quo_preview/tags/tag.cljs b/src/status_im2/contexts/quo_preview/tags/tag.cljs new file mode 100644 index 0000000000..b2db5dbe53 --- /dev/null +++ b/src/status_im2/contexts/quo_preview/tags/tag.cljs @@ -0,0 +1,98 @@ +(ns status-im2.contexts.quo-preview.tags.tag + (:require [quo.react-native :as rn] + [quo.previews.preview :as preview] + [quo2.foundations.colors :as colors] + [quo2.components.tags.tag :as tag] + [status-im.ui.components.react :as react] + [status-im.react-native.resources :as resources] + [reagent.core :as reagent])) + +(def descriptor + [{:label "Size:" + :key :size + :type :select + :options [{:key 32 + :value "32"} + {:key 24 + :value "24"}]} + {:label "Type:" + :key :type + :type :select + :options [{:key :emoji + :value "Emoji"} + {:key :icon + :value "Icons"} + {:key :label + :value "Label"}]} + {:label "Labelled:" + :key :labelled? + :type :boolean} + {:label "Disabled:" + :key :disabled? + :type :boolean} + {:label "Blurred background:" + :key :blurred? + :type :boolean}]) + +(defn cool-preview + [] + (let [state (reagent/atom {:size 32 + :labelled? true + :type :emoji})] + (fn [] + [rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!} + [rn/view + {:style {:padding-bottom 150 + :padding-top 60}} + [rn/view {:flex 1} + [preview/customizer state descriptor]] + [rn/view + {:style {:flex 1 + :justify-content :center + :top 60 + :padding-horizontal 16}} + (when (:blurred? @state) + [rn/view + {:style {:flex 1 + :height 100}} + [react/image + {:source (resources/get-image :community-cover) + :style {:flex 1 + :width "100%" + :border-radius 16}}] + [react/blur-view + {:flex 1 + :style {:border-radius 16 + :height 100 + :position :absolute + :left 0 + :right 0} + :blur-amount 20 + :overlay-color (colors/theme-colors + colors/white-opa-70 + colors/neutral-80-opa-80)}]]) + [rn/view + {:style {:position :absolute + :align-self :center}} + [tag/tag + (merge @state + {:id 1 + :label "Tag" + :labelled? (if (= (:type @state) :label) + true + (:labelled? @state)) + :resource (if (= :emoji (:type @state)) + (resources/get-image :music) + :main-icons2/placeholder)})]]]]]))) +(defn preview-tag + [] + [rn/view + {:flex 1 + :background-color (colors/theme-colors + colors/white + colors/neutral-90)} + [rn/flat-list + {:flex 1 + :keyboardShouldPersistTaps :always + :header [cool-preview] + :key-fn str}]]) diff --git a/src/status_im2/contexts/quo_preview/tags/tags.cljs b/src/status_im2/contexts/quo_preview/tags/tags.cljs index 95162dbf17..90ec83a6e1 100644 --- a/src/status_im2/contexts/quo_preview/tags/tags.cljs +++ b/src/status_im2/contexts/quo_preview/tags/tags.cljs @@ -24,70 +24,85 @@ :value "Icons"} {:key :label :value "Label"}]} + {:label "Scrollable:" + :key :scrollable? + :type :boolean} + {:label "Fade Out:" + :key :fade-end-percentage + :type :select + :options [{:key 1 + :value "1%"} + {:key 0.4 + :value "0.4%"}]} {:label "Labelled:" - :key :labelled + :key :labelled? :type :boolean} {:label "Disabled:" - :key :disabled + :key :disabled? :type :boolean} {:label "Blurred background:" - :key :blurred + :key :blurred? :type :boolean}]) (defn cool-preview [] - (let [state (reagent/atom {:size 32 - :labelled true - :type :emoji})] + (let [state (reagent/atom {:size 32 + :labelled? true + :type :emoji + :fade-end-percentage 0.4 + :scrollable? false})] (fn [] [rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!} [rn/view - {:padding-bottom 150 - :padding-top 60} - [rn/view {:flex 1} + {:style {:padding-bottom 150 + :padding-top 60}} + [rn/view {:style {:flex 1}} [preview/customizer state descriptor]] [rn/view - {:flex 1 - :justify-content :center - :top 60} - (when (:blurred @state) - [rn/view {:flex 1} - [react/view - {:flex-direction :row - :height 100} - [react/image - {:source (resources/get-image :community-cover) - :style {:flex 1 - :height 100 - :border-radius 16}}]] - [react/view - {:flex-direction :row - :height 100 - :position :absolute - :left 0 - :right 0} - [react/blur-view - {:flex 1 - :style {:border-radius 16 - :height 100} - :blur-amount 40 - :overlay-color (colors/theme-colors - colors/white-opa-70 - colors/neutral-80-opa-80)}]]]) - [rn/scroll-view - {:justify-content :center - :align-items :center - :position :absolute - :padding-horizontal 10} + {:style {:flex 1 + :justify-content :center + :top 60 + :padding-horizontal 16}} + (when (:blurred? @state) + [rn/view + {:align-items :center + :height 100 + :border-radius 16} + [react/image + {:source (resources/get-image :community-cover) + :style {:flex 1 + :width "100%" + :border-radius 16}}] + [react/blur-view + {:flex 1 + :style {:border-radius 16 + :height 100 + :position :absolute + :left 0 + :right 0} + :blur-amount 20 + :overlay-color (colors/theme-colors + colors/white-opa-70 + colors/neutral-80-opa-80)}]]) + [rn/view + {:style {:position :absolute + :align-self :center}} [tags/tags (merge @state {:default-active 1 - :data [{:id 1 :tag-label "Music" :resource (resources/get-image :music)} - {:id 2 :tag-label "Lifestyle" :resource (resources/get-image :lifestyle)} - {:id 3 - :tag-label "Podcasts" - :resource (resources/get-image :podcasts)}]})]]]]]))) + :component :tags + :labelled? (if (= :label type) true (:labelled? @state)) + :resource (when (= type :icon) + :main-icons2/placeholder) + :data [{:id 1 :label "Music" :resource (resources/get-image :music)} + {:id 2 :label "Lifestyle" :resource (resources/get-image :lifestyle)} + {:id 2 :label "Podcasts" :resource (resources/get-image :podcasts)} + {:id 2 :label "Music" :resource (resources/get-image :music)} + {:id 3 :label "Lifestyle" :resource (resources/get-image :lifestyle)}]} + (when (:scrollable? @state) + {:scroll-on-press? true + :fade-end? true}))]]]]]))) (defn preview-tags [] [rn/view