feat: new keycard component (#15892)
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,20 @@
|
||||||
|
(ns quo2.components.keycard.component-spec
|
||||||
|
(:require [quo2.components.keycard.view :as keycard]
|
||||||
|
[test-helpers.component :as h]
|
||||||
|
[utils.i18n :as i18n]))
|
||||||
|
|
||||||
|
(h/describe "keycard component"
|
||||||
|
(h/test "Render of keycard component when: Status = Empty, Locked = False"
|
||||||
|
(h/render [keycard/keycard])
|
||||||
|
(-> (h/expect (h/query-by-label-text :holder-name))
|
||||||
|
(h/is-equal (i18n/label :t/empty-keycard))))
|
||||||
|
|
||||||
|
(h/test "Render of keycard component when: Status = Filled, Locked = False"
|
||||||
|
(h/render [keycard/keycard {:holder-name? "Alisha"}])
|
||||||
|
(-> (h/expect (h/query-by-label-text :holder-name))
|
||||||
|
(h/is-equal (i18n/label :t/user-keycard {:name :holder-name}))))
|
||||||
|
|
||||||
|
(h/test "Render of keycard component when: Status = Filled, Locked = True"
|
||||||
|
(h/render [keycard/keycard {:holder-name? "Alisha"}])
|
||||||
|
(-> (h/expect (h/query-by-label-text :holder-name))
|
||||||
|
(h/is-equal (i18n/label :t/user-keycard {:name :holder-name})))))
|
|
@ -0,0 +1,42 @@
|
||||||
|
(ns quo2.components.keycard.style
|
||||||
|
(:require [quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
|
(def keycard-height 210)
|
||||||
|
(def keycard-chip-height 28)
|
||||||
|
|
||||||
|
(defn card-container
|
||||||
|
[locked?]
|
||||||
|
{:overflow :hidden
|
||||||
|
:height keycard-height
|
||||||
|
:align-items :flex-start
|
||||||
|
:justify-content :space-between
|
||||||
|
:border-width 1
|
||||||
|
:border-color (if locked?
|
||||||
|
colors/white-opa-5
|
||||||
|
(colors/theme-colors colors/neutral-20 colors/neutral-80))
|
||||||
|
:border-style :solid
|
||||||
|
:border-radius 16
|
||||||
|
:padding 16
|
||||||
|
:background-color (if locked?
|
||||||
|
(colors/theme-colors colors/danger colors/danger-opa-40)
|
||||||
|
(colors/theme-colors colors/neutral-5 colors/neutral-90))})
|
||||||
|
|
||||||
|
(defn keycard-logo
|
||||||
|
[locked?]
|
||||||
|
{:tint-color (if locked? colors/white (colors/theme-colors colors/neutral-100 colors/white))})
|
||||||
|
|
||||||
|
(defn keycard-watermark
|
||||||
|
[locked?]
|
||||||
|
{:position :absolute
|
||||||
|
:tint-color (if locked? colors/white-opa-5 (colors/theme-colors colors/neutral-100 colors/white))
|
||||||
|
:align-self :center
|
||||||
|
:height 280.48
|
||||||
|
:transform [{:rotate "-30deg"} {:translateY -30}]
|
||||||
|
:opacity (when-not locked? 0.02)
|
||||||
|
:z-index 1})
|
||||||
|
|
||||||
|
(def keycard-chip
|
||||||
|
{:height keycard-chip-height
|
||||||
|
:position :absolute
|
||||||
|
:right 16
|
||||||
|
:top (/ (- keycard-height 28) 2)})
|
|
@ -0,0 +1,38 @@
|
||||||
|
(ns quo2.components.keycard.view
|
||||||
|
(:require [react-native.core :as rn]
|
||||||
|
[quo2.components.keycard.style :as style]
|
||||||
|
[quo2.components.tags.tag :as tag]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[quo2.foundations.resources :as resources]
|
||||||
|
[utils.i18n :as i18n]))
|
||||||
|
|
||||||
|
(defn keycard
|
||||||
|
"This component based on the following properties:
|
||||||
|
- :holder-name - Can be owner's name. Default is Empty
|
||||||
|
- :locked? - Boolean to specify whether the keycard is locked or not
|
||||||
|
"
|
||||||
|
[{:keys [holder-name locked?]}]
|
||||||
|
(let [label (if (boolean holder-name)
|
||||||
|
(i18n/label :t/user-keycard {:name holder-name})
|
||||||
|
(i18n/label :t/empty-keycard))]
|
||||||
|
[rn/view {:style (style/card-container locked?)}
|
||||||
|
[rn/image
|
||||||
|
{:source (resources/get-image :keycard-logo)
|
||||||
|
:style (style/keycard-logo locked?)}]
|
||||||
|
[rn/image
|
||||||
|
{:source (resources/get-image
|
||||||
|
(if (or locked? (colors/dark?)) :keycard-chip-dark :keycard-chip-light))
|
||||||
|
:style style/keycard-chip}]
|
||||||
|
[rn/image
|
||||||
|
{:source (resources/get-image :keycard-watermark)
|
||||||
|
:style (style/keycard-watermark locked?)}]
|
||||||
|
[tag/tag
|
||||||
|
{:size 32
|
||||||
|
:type (when locked? :icon)
|
||||||
|
:label label
|
||||||
|
:labelled? true
|
||||||
|
:blurred? true
|
||||||
|
:resource (when locked? :i/locked)
|
||||||
|
:accessibility-label :holder-name
|
||||||
|
:icon-color colors/white-70-blur
|
||||||
|
:override-theme (when locked? :dark)}]]))
|
|
@ -38,6 +38,7 @@
|
||||||
quo2.components.inputs.recovery-phrase.view
|
quo2.components.inputs.recovery-phrase.view
|
||||||
quo2.components.inputs.search-input.view
|
quo2.components.inputs.search-input.view
|
||||||
quo2.components.inputs.title-input.view
|
quo2.components.inputs.title-input.view
|
||||||
|
quo2.components.keycard.view
|
||||||
quo2.components.links.url-preview-list.view
|
quo2.components.links.url-preview-list.view
|
||||||
quo2.components.links.url-preview.view
|
quo2.components.links.url-preview.view
|
||||||
quo2.components.links.link-preview.view
|
quo2.components.links.link-preview.view
|
||||||
|
@ -126,6 +127,7 @@
|
||||||
|
|
||||||
;;;; CARDS
|
;;;; CARDS
|
||||||
(def small-option-card quo2.components.onboarding.small-option-card.view/small-option-card)
|
(def small-option-card quo2.components.onboarding.small-option-card.view/small-option-card)
|
||||||
|
(def keycard quo2.components.keycard.view/keycard)
|
||||||
|
|
||||||
;;;; COLORS
|
;;;; COLORS
|
||||||
(def color-picker quo2.components.colors.color-picker.view/view)
|
(def color-picker quo2.components.colors.color-picker.view/view)
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
(ns quo2.foundations.resources)
|
||||||
|
|
||||||
|
(def ui
|
||||||
|
{:keycard-logo (js/require "../resources/images/ui2/keycard-logo.png")
|
||||||
|
:keycard-chip-light (js/require "../resources/images/ui2/keycard-chip-light.png")
|
||||||
|
:keycard-chip-dark (js/require "../resources/images/ui2/keycard-chip-dark.png")
|
||||||
|
:keycard-watermark (js/require "../resources/images/ui2/keycard-watermark.png")})
|
||||||
|
|
||||||
|
(defn get-image
|
||||||
|
[k]
|
||||||
|
(get ui k))
|
|
@ -15,7 +15,10 @@
|
||||||
:use-keycard (js/require "../resources/images/ui2/keycard.png")
|
:use-keycard (js/require "../resources/images/ui2/keycard.png")
|
||||||
:onboarding-illustration (js/require "../resources/images/ui2/onboarding_illustration.png")
|
:onboarding-illustration (js/require "../resources/images/ui2/onboarding_illustration.png")
|
||||||
:qr-code (js/require "../resources/images/ui2/qr-code.png")
|
:qr-code (js/require "../resources/images/ui2/qr-code.png")
|
||||||
})
|
:keycard-logo (js/require "../resources/images/ui2/keycard-logo.png")
|
||||||
|
:keycard-chip-light (js/require "../resources/images/ui2/keycard-chip-light.png")
|
||||||
|
:keycard-chip-dark (js/require "../resources/images/ui2/keycard-chip-dark.png")
|
||||||
|
:keycard-watermark (js/require "../resources/images/ui2/keycard-watermark.png")})
|
||||||
|
|
||||||
(def mock-images
|
(def mock-images
|
||||||
{:coinbase (js/require "../resources/images/mock2/coinbase.png")
|
{:coinbase (js/require "../resources/images/mock2/coinbase.png")
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
(ns status-im2.contexts.quo-preview.keycard.keycard
|
||||||
|
(:require [status-im2.contexts.quo-preview.preview :as preview]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
[quo2.core :as quo]))
|
||||||
|
|
||||||
|
(def descriptor
|
||||||
|
[{:label "Holder"
|
||||||
|
:key :holder-name
|
||||||
|
:type :text}
|
||||||
|
{:label "Locked?"
|
||||||
|
:key :locked?
|
||||||
|
:type :boolean}])
|
||||||
|
|
||||||
|
(defn cool-preview
|
||||||
|
[]
|
||||||
|
(let [state (reagent/atom {:holder-name nil
|
||||||
|
:locked? true})]
|
||||||
|
(fn
|
||||||
|
[]
|
||||||
|
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
|
||||||
|
[rn/view [preview/customizer state descriptor]
|
||||||
|
[quo/keycard
|
||||||
|
{:holder-name? (:holder-name @state)
|
||||||
|
:locked? (:locked? @state)}]]])))
|
||||||
|
|
||||||
|
(defn preview-keycard
|
||||||
|
[]
|
||||||
|
[rn/view
|
||||||
|
{:style {:background-color (colors/theme-colors colors/white colors/neutral-95)
|
||||||
|
:flex 1}}
|
||||||
|
[rn/flat-list
|
||||||
|
{:style {:flex 1}
|
||||||
|
:keyboard-should-persist-taps :always
|
||||||
|
:header [cool-preview]
|
||||||
|
:key-fn str}]])
|
|
@ -90,7 +90,8 @@
|
||||||
[status-im2.contexts.quo-preview.wallet.lowest-price :as lowest-price]
|
[status-im2.contexts.quo-preview.wallet.lowest-price :as lowest-price]
|
||||||
[status-im2.contexts.quo-preview.wallet.network-amount :as network-amount]
|
[status-im2.contexts.quo-preview.wallet.network-amount :as network-amount]
|
||||||
[status-im2.contexts.quo-preview.wallet.network-breakdown :as network-breakdown]
|
[status-im2.contexts.quo-preview.wallet.network-breakdown :as network-breakdown]
|
||||||
[status-im2.contexts.quo-preview.wallet.token-overview :as token-overview]))
|
[status-im2.contexts.quo-preview.wallet.token-overview :as token-overview]
|
||||||
|
[status-im2.contexts.quo-preview.keycard.keycard :as keycard]))
|
||||||
|
|
||||||
(def screens-categories
|
(def screens-categories
|
||||||
{:foundations [{:name :shadows
|
{:foundations [{:name :shadows
|
||||||
|
@ -344,7 +345,10 @@
|
||||||
:component network-breakdown/preview-network-breakdown}
|
:component network-breakdown/preview-network-breakdown}
|
||||||
{:name :network-amount
|
{:name :network-amount
|
||||||
:options {:topBar {:visible true}}
|
:options {:topBar {:visible true}}
|
||||||
:component network-amount/preview}]})
|
:component network-amount/preview}]
|
||||||
|
:keycard [{:name :keycard-component
|
||||||
|
:options {:topBar {:visible true}}
|
||||||
|
:component keycard/preview-keycard}]})
|
||||||
|
|
||||||
(def screens (flatten (map val screens-categories)))
|
(def screens (flatten (map val screens-categories)))
|
||||||
|
|
||||||
|
|
|
@ -992,7 +992,9 @@
|
||||||
:your-data-belongs-to-you
|
:your-data-belongs-to-you
|
||||||
:your-data-belongs-to-you-description
|
:your-data-belongs-to-you-description
|
||||||
:your-recovery-phrase
|
:your-recovery-phrase
|
||||||
:your-recovery-phrase-description})
|
:your-recovery-phrase-description
|
||||||
|
:empty-keycard
|
||||||
|
:user-keycard})
|
||||||
|
|
||||||
;; NOTE: the rest checkpoints are based on the previous one, defined
|
;; NOTE: the rest checkpoints are based on the previous one, defined
|
||||||
;; like this:
|
;; like this:
|
||||||
|
|
|
@ -1687,6 +1687,8 @@
|
||||||
"database-reset-content": "Chats, contacts and settings have been deleted. You can use your account with your Keycard",
|
"database-reset-content": "Chats, contacts and settings have been deleted. You can use your account with your Keycard",
|
||||||
"database-reset-warning": "Database will be reset. Chats, contacts and settings will be deleted",
|
"database-reset-warning": "Database will be reset. Chats, contacts and settings will be deleted",
|
||||||
"empty-keycard-required": "Requires an empty Keycard",
|
"empty-keycard-required": "Requires an empty Keycard",
|
||||||
|
"empty-keycard": "Empty Keycard",
|
||||||
|
"user-keycard": "{{name}} Card",
|
||||||
"current": "Current",
|
"current": "Current",
|
||||||
"choose-storage": "Choose storage",
|
"choose-storage": "Choose storage",
|
||||||
"choose-new-location-for-keystore": "Choose a new location to save your keystore file",
|
"choose-new-location-for-keystore": "Choose a new location to save your keystore file",
|
||||||
|
|