[issue-13578] Dropdown component (#13866)
After Width: | Height: | Size: 747 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 565 B |
After Width: | Height: | Size: 812 B |
After Width: | Height: | Size: 729 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 547 B |
After Width: | Height: | Size: 774 B |
|
@ -0,0 +1,147 @@
|
||||||
|
(ns quo2.components.list-items.dropdown
|
||||||
|
(:require [quo.react-native :as rn]
|
||||||
|
[quo2.components.icon :as icons]
|
||||||
|
[quo2.components.markdown.text :as text]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[quo2.reanimated :as reanimated]
|
||||||
|
[reagent.core :as reagent]))
|
||||||
|
|
||||||
|
(defn apply-anim [dd-height val]
|
||||||
|
(reanimated/animate-shared-value-with-delay dd-height
|
||||||
|
val
|
||||||
|
300
|
||||||
|
:easing1
|
||||||
|
0))
|
||||||
|
|
||||||
|
(def sizes {:big {:icon-size 20
|
||||||
|
:font {:font-size :paragraph-1}
|
||||||
|
:height 40
|
||||||
|
:padding {:padding-with-icon {:padding-vertical 9
|
||||||
|
:padding-horizontal 12}
|
||||||
|
:padding-with-no-icon {:padding-vertical 9
|
||||||
|
:padding-left 12
|
||||||
|
:padding-right 8}}}
|
||||||
|
:medium {:icon-size 20
|
||||||
|
:font {:font-size :paragraph-1}
|
||||||
|
:height 32
|
||||||
|
:padding {:padding-with-icon {:padding-vertical 5
|
||||||
|
:padding-horizontal 8}
|
||||||
|
:padding-with-no-icon {:padding-vertical 5
|
||||||
|
:padding-left 12
|
||||||
|
:padding-right 8}}}
|
||||||
|
:small {:icon-size 15
|
||||||
|
:font {:font-size :paragraph-2}
|
||||||
|
:height 24
|
||||||
|
:padding {:padding-with-icon {:padding-vertical 3
|
||||||
|
:padding-horizontal 6}
|
||||||
|
:padding-with-no-icon {:padding-vertical 3
|
||||||
|
:padding-horizontal 6}}}})
|
||||||
|
(defn color-by-10
|
||||||
|
[color]
|
||||||
|
(colors/alpha color 0.6))
|
||||||
|
|
||||||
|
(defn dropdown-comp [{:keys [icon open? dd-height size disabled? dd-color use-border? border-color]}]
|
||||||
|
(let [dark? (colors/dark?)
|
||||||
|
{:keys [width height width-with-icon padding font icon-size]} (size sizes)
|
||||||
|
{:keys [padding-with-icon padding-with-no-icon]} padding
|
||||||
|
font-size (:font-size font)
|
||||||
|
spacing (case size
|
||||||
|
:big 4
|
||||||
|
:medium 2
|
||||||
|
:small 2)]
|
||||||
|
[rn/touchable-opacity (cond-> {:on-press (fn []
|
||||||
|
(if (swap! open? not)
|
||||||
|
(apply-anim dd-height 120)
|
||||||
|
(apply-anim dd-height 0)))
|
||||||
|
:style (cond-> (merge
|
||||||
|
(if icon
|
||||||
|
padding-with-icon
|
||||||
|
padding-with-no-icon)
|
||||||
|
{:width (if icon
|
||||||
|
width-with-icon
|
||||||
|
width)
|
||||||
|
:height height
|
||||||
|
:border-radius (case size
|
||||||
|
:big 12
|
||||||
|
:medium 10
|
||||||
|
:small 8)
|
||||||
|
:flex-direction :row
|
||||||
|
:align-items :center
|
||||||
|
:background-color (if @open?
|
||||||
|
dd-color
|
||||||
|
(color-by-10 dd-color))})
|
||||||
|
use-border? (assoc :border-width 1
|
||||||
|
:border-color (if @open? border-color (color-by-10 border-color))))}
|
||||||
|
disabled? (assoc-in [:style :opacity] 0.3)
|
||||||
|
disabled? (assoc :disabled true))
|
||||||
|
(when icon
|
||||||
|
[icons/icon icon {:no-color true
|
||||||
|
:size 20
|
||||||
|
:container-style {:margin-right spacing
|
||||||
|
:margin-top 1
|
||||||
|
:width icon-size
|
||||||
|
:height icon-size}}])
|
||||||
|
[text/text {:size font-size
|
||||||
|
:weight :medium
|
||||||
|
:font :font-medium
|
||||||
|
:color :main} "Dropdown"]
|
||||||
|
[icons/icon (if @open?
|
||||||
|
(if dark?
|
||||||
|
:main-icons/pullup-dark
|
||||||
|
:main-icons/pullup)
|
||||||
|
(if dark?
|
||||||
|
:main-icons/dropdown-dark
|
||||||
|
:main-icons/dropdown))
|
||||||
|
{:size 20
|
||||||
|
:no-color true
|
||||||
|
:container-style {:width (+ icon-size 3)
|
||||||
|
:border-radius 20
|
||||||
|
:margin-left (if (= :small size)
|
||||||
|
2
|
||||||
|
4)
|
||||||
|
:margin-top 1
|
||||||
|
:height (+ icon-size 4)}}]]))
|
||||||
|
|
||||||
|
(defn items-comp
|
||||||
|
[{:keys [items on-select]}]
|
||||||
|
(let [items-count (count items)]
|
||||||
|
[rn/scroll-view {:style {:height "100%"}
|
||||||
|
:horizontal false
|
||||||
|
:nestedScrollEnabled true}
|
||||||
|
(doall
|
||||||
|
(map-indexed (fn [index item]
|
||||||
|
[rn/touchable-opacity
|
||||||
|
{:key (str item index)
|
||||||
|
:style {:padding 4
|
||||||
|
:border-bottom-width (if (= index (- items-count 1))
|
||||||
|
0
|
||||||
|
1)
|
||||||
|
:border-color (colors/theme-colors
|
||||||
|
colors/black
|
||||||
|
colors/white)
|
||||||
|
:text-align :center}
|
||||||
|
:on-press #(on-select item)}
|
||||||
|
[text/text {:style {:text-align :center}} item]]) items))]))
|
||||||
|
|
||||||
|
(defn dropdown [{:keys [items icon text default-item on-select size disabled? border-color use-border? dd-color]}]
|
||||||
|
[:f>
|
||||||
|
(fn []
|
||||||
|
(let [open? (reagent/atom false)
|
||||||
|
dd-height (reanimated/use-shared-value 0)]
|
||||||
|
[rn/view {:style {:flex-grow 1}}
|
||||||
|
[dropdown-comp {:items items
|
||||||
|
:icon icon
|
||||||
|
:disabled? disabled?
|
||||||
|
:size size
|
||||||
|
:dd-color dd-color
|
||||||
|
:text text
|
||||||
|
:border-color (colors/custom-color-by-theme border-color 50 60)
|
||||||
|
:use-border? use-border?
|
||||||
|
:default-item default-item
|
||||||
|
:open? open?
|
||||||
|
:dd-height dd-height}]
|
||||||
|
[reanimated/view {:style (reanimated/apply-animations-to-style
|
||||||
|
{:height dd-height}
|
||||||
|
{:height dd-height})}
|
||||||
|
[items-comp {:items items
|
||||||
|
:on-select on-select}]]]))])
|
|
@ -0,0 +1,79 @@
|
||||||
|
(ns quo2.screens.list-items.dropdown
|
||||||
|
(:require [quo.components.text :as text]
|
||||||
|
[quo.previews.preview :as preview]
|
||||||
|
[quo.react-native :as rn]
|
||||||
|
[quo2.components.list-items.dropdown :as quo2]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[reagent.core :as reagent]))
|
||||||
|
|
||||||
|
(def descriptor [{:label "Icon"
|
||||||
|
:key :icon
|
||||||
|
:type :select
|
||||||
|
:options [{:key :main-icons/placeholder
|
||||||
|
:value "Placeholder"}
|
||||||
|
{:key :main-icons/locked
|
||||||
|
:value "Wallet"}]}
|
||||||
|
{:label "Disabled"
|
||||||
|
:key :disabled?
|
||||||
|
:type :boolean}
|
||||||
|
{:label "Default item"
|
||||||
|
:key :default-item
|
||||||
|
:type :text}
|
||||||
|
{:label "Use border?"
|
||||||
|
:key :use-border?
|
||||||
|
:type :boolean}
|
||||||
|
{:label "Border color"
|
||||||
|
:key :border-color
|
||||||
|
:type :select
|
||||||
|
:options (map
|
||||||
|
(fn [c]
|
||||||
|
{:key c
|
||||||
|
:value c})
|
||||||
|
(keys colors/customization))}
|
||||||
|
{:label "DD color"
|
||||||
|
:key :dd-color
|
||||||
|
:type :text}
|
||||||
|
{:label "Size"
|
||||||
|
:key :size
|
||||||
|
:type :select
|
||||||
|
:options [{:key :big
|
||||||
|
:value "big"}
|
||||||
|
{:key :medium
|
||||||
|
:value "medium"}
|
||||||
|
{:key :small
|
||||||
|
:value "small"}]}])
|
||||||
|
|
||||||
|
(defn cool-preview []
|
||||||
|
(let [items ["Banana"
|
||||||
|
"Apple"
|
||||||
|
"COVID +18"
|
||||||
|
"Orange"
|
||||||
|
"Kryptonite"
|
||||||
|
"BMW"
|
||||||
|
"Meh"]
|
||||||
|
state (reagent/atom {:icon :main-icons/placeholder
|
||||||
|
:default-item "item1"
|
||||||
|
:use-border? false
|
||||||
|
:dd-color (colors/custom-color :purple 50)
|
||||||
|
:size :big})
|
||||||
|
selected-item (reagent/cursor state [:default-item])
|
||||||
|
on-select #(reset! selected-item %)]
|
||||||
|
(fn []
|
||||||
|
[rn/view {:margin-bottom 50
|
||||||
|
:padding 16}
|
||||||
|
[preview/customizer state descriptor]
|
||||||
|
[rn/view {:padding-vertical 60
|
||||||
|
:align-items :center}
|
||||||
|
[text/text {:color :main} (str "Selected item: " @selected-item)]
|
||||||
|
[quo2/dropdown (merge @state {:on-select on-select
|
||||||
|
:items items})]]])))
|
||||||
|
|
||||||
|
(defn preview-dropdown []
|
||||||
|
[rn/view {:background-color (colors/theme-colors colors/white colors/neutral-90)
|
||||||
|
:flex 1}
|
||||||
|
[rn/flat-list {:flex 1
|
||||||
|
:flex-grow 1
|
||||||
|
:nestedScrollEnabled true
|
||||||
|
:keyboardShouldPersistTaps :always
|
||||||
|
:header [cool-preview]
|
||||||
|
:key-fn str}]])
|
|
@ -35,6 +35,7 @@
|
||||||
[quo2.screens.avatars.channel-avatar :as channel-avatar]
|
[quo2.screens.avatars.channel-avatar :as channel-avatar]
|
||||||
[quo2.screens.switcher.switcher-cards :as switcher-cards]
|
[quo2.screens.switcher.switcher-cards :as switcher-cards]
|
||||||
[quo2.screens.tabs.account-selector :as account-selector]
|
[quo2.screens.tabs.account-selector :as account-selector]
|
||||||
|
[quo2.screens.list-items.dropdown :as dropdown]
|
||||||
[re-frame.core :as re-frame]))
|
[re-frame.core :as re-frame]))
|
||||||
|
|
||||||
(def screens-categories
|
(def screens-categories
|
||||||
|
@ -116,6 +117,9 @@
|
||||||
:wallet [{:name :token-overview
|
:wallet [{:name :token-overview
|
||||||
:insets {:top false}
|
:insets {:top false}
|
||||||
:component token-overview/preview-token-overview}]
|
:component token-overview/preview-token-overview}]
|
||||||
|
:dropdowns [{:name :dropdown
|
||||||
|
:insets {:top false}
|
||||||
|
:component dropdown/preview-dropdown}]
|
||||||
:list-items [{:name :preview-lists
|
:list-items [{:name :preview-lists
|
||||||
:insets {:top false}
|
:insets {:top false}
|
||||||
:component preview-lists/preview-preview-lists}]
|
:component preview-lists/preview-preview-lists}]
|
||||||
|
@ -176,4 +180,4 @@
|
||||||
|
|
||||||
(def main-screens [{:name :quo2-preview
|
(def main-screens [{:name :quo2-preview
|
||||||
:insets {:top false}
|
:insets {:top false}
|
||||||
:component main-screen}])
|
:component main-screen}])
|