Skip to content

Commit

Permalink
chore: add floating button page component
Browse files Browse the repository at this point in the history
  • Loading branch information
J-Son89 committed Oct 26, 2023
1 parent 876b020 commit 67339ee
Show file tree
Hide file tree
Showing 16 changed files with 405 additions and 33 deletions.
2 changes: 1 addition & 1 deletion doc/component-tests-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ setups and runs the test suite once.
setups and runs the test suite and watches for code changes will then retrigger the test suite.

## Writing Tests
New test files will need their namespace added to either the file "src/quo2/core_spec.cljs" or "src/status_im2/core_spec.cljs. These locations may update overtime but it is dependent on the entrypoint in shadow-cljs config discussed below.
New test files will need their namespace added to either the file "src/quo/core_spec.cljs" or "src/status_im2/core_spec.cljs. These locations may update overtime but it is dependent on the entrypoint in shadow-cljs config discussed below.


### Best practices
Expand Down
40 changes: 20 additions & 20 deletions doc/new-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ It's important to name functional components with `f-` prefix.

### Component props and API scheme to match Figma as closely as possible

Ideally, the prop names for components (particularly in quo2 Design System)
Ideally, the prop names for components (particularly in Quo Design System)
should match the Figma properties as best as possible. This makes it easier for
the developer using that component to configure it correctly for the screen it
is being used on and avoids unnecessary overwrites and adjustments being made.
Expand Down Expand Up @@ -134,7 +134,7 @@ For example if Figma has sizes `:small`, `:medium` and `:large`

Prefer to define styles in a separate file named `style.cljs`, colocated with
the source file. For a real example, see
[src/quo2/components/record_audio/record_audio/style.cljs](../src/quo2/components/record_audio/record_audio/style.cljs).
[src//components/record_audio/record_audio/style.cljs](../src/quo/components/record_audio/record_audio/style.cljs).

```clojure
;; bad
Expand Down Expand Up @@ -528,27 +528,27 @@ due to performance constraints.
(:preferred-name multiaccount)))
```

### Requiring quo2 components
### Requiring quo components

Consume `quo2` components from `quo2.core`, unless the namespace is also inside
the `quo2/` directory.
Consume `quo` components from `quo.core`, unless the namespace is also inside
the `quo/` directory.

```clojure
;; bad
(ns my-namespace
(:require [quo2.components.icon :as icon]))
(:require [quo.components.icon :as icon]))

(icon/icon :i/verified)

;; good
(ns my-namespace
(:require [quo2.core :as quo]))
(:require [quo.core :as quo]))

(quo/icon :i/verified)

;; also good because both namespaces are inside quo2/
(ns quo2.components.tabs.account-selector
(:require [quo2.components.markdown.text :as text]))
;; also good because both namespaces are inside quo/
(ns quo.components.tabs.account-selector
(:require [quo.components.markdown.text :as text]))
```

### Require/import
Expand Down Expand Up @@ -615,12 +615,12 @@ Use the appropriate keyword qualification/namespace.

```clojure
;; bad
(require '[quo2.components.icon :as icons])
(require '[quo.components.icon :as icons])
(icons/icon :main-icons2/verified)

;; good
(require '[quo2.core :as quo2])
(quo2/icon :i/verified)
(require '[quo.core :as quo])
(quo/icon :i/verified)
```

### Translations
Expand Down Expand Up @@ -695,7 +695,7 @@ First, the bird's-eye view with some example ClojureScript files:
src
├── js/
├── mocks/
├── quo2
├── quo
│ ├── components/
│ ├── foundations/
│ └── theme.cljs
Expand All @@ -716,7 +716,7 @@ src

- `src/js`: Raw Javascript files, e.g. React Native Reanimated worklets.
- `src/mocks`: Plumbing configuration to be able to run tests.
- `src/quo2/`: The component library for Status Mobile.
- `src/quo/`: The component library for Status Mobile.
- `src/react_native/`: Contains only low-level constructs to help React Native
work in tandem with Clojure(Script).
- `src/status_im2/`: Directory where we try to be as strict as possible about
Expand All @@ -728,7 +728,7 @@ src
of the directory tree. Just like directories named `utils`, their directory
nesting level communicates their applicable limits.
- `src/status_im2/common/components/`: Contains reusable components that are not
part of the design system (quo2).
part of the design system (Quo).
- `src/status_im2/contexts/`: Contains [bounded contexts](#glossary), like
`browser/`, `messaging/`, etc. As much as possible, _bounded contexts_ should
not directly require each other's namespaces.
Expand All @@ -743,24 +743,24 @@ directory nesting level precisely indicates its boundaries. For example, a
`contexts/user_settings/utils/datetime.cljs` file communicates that it should
only be used in the `user_settings` context.

### src/quo2
### src/quo

The `src/quo2/` directory holds all components for the new design system. As
The `src/quo/` directory holds all components for the new design system. As
much as possible, its sub-directories and component names should reflect the
same language used by designers.

Even though the directory lives alongside the rest of the codebase, we should
think of it as an external entity that abstracts away particular Status domain
knowledge.

Components inside `src/quo2/` should not rely on re-frame, i.e. they should not
Components inside `src/quo/` should not rely on re-frame, i.e. they should not
dispatch events or use subscriptions.

Example structure:

```
src
└── quo2
└── quo
├── components
│ └── dropdown
│ ├── style.cljs
Expand Down
7 changes: 7 additions & 0 deletions src/status_im/ui/screens/profile/user/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,13 @@
:accessibility-label :appearance-settings-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :quo-preview])}])
(when config/quo-preview-enabled?
[list.item/list-item
{:icon :main-icons/appearance
:title "Status IM Components"
:accessibility-label :status-im-common-components
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :status-im-preview])}])
[list.item/list-item
{:icon :main-icons/appearance
:title (i18n/label :t/appearance)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
(ns status-im2.common.floating-button-page.floating-container.style
(:require [react-native.platform :as platform]))

(def container
{:width "100%"
:margin-top :auto
:align-self :flex-end})

(def view-container
(assoc container
:padding-left 20
:padding-right 20
:padding-top 12
:padding-bottom 12))

(def blur-container
(merge container
(when platform/android? {:margin-left 20})))
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
(ns status-im2.common.floating-button-page.floating-container.view
(:require [quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.blur :as blur]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area]
[status-im2.common.floating-button-page.floating-container.style :as style]))

(def duration 110)

(defn blur-container-props
[theme]
{:blur-amount 12
:blur-radius 25
:blur-type (quo.theme/theme-value :light :dark theme)
:style (when platform/ios? {:width "100%"
:padding-horizontal 20
:padding-vertical 12})
:background-color (colors/theme-colors colors/white-70-blur colors/neutral-80-opa-1-blur theme)})

(defn- blur-container
[props & children]
[rn/view
(merge props
{:width "100%"
:overflow :hidden}
(when platform/android?
{:padding-horizontal 20
:padding-vertical 12}))
(into [blur/view (blur-container-props (:theme props))] children)])

"
- on-layout : will trigger to dynamically get the height of the container to screen using it.
- show-background? : blurred container that is activated when this component is on top of the page content.
- keyboard-shown? : keyboard is visible on the current page.
"
(defn get-margin-bottom
[show-background? keyboard-shown?]
(if platform/android? 0
(cond keyboard-shown? (safe-area/get-top)
(and show-background? keyboard-shown?) (safe-area/get-bottom)
:else (safe-area/get-bottom))))

(defn f-view
[{:keys [on-layout theme show-background? keyboard-shown?]}
children]
(let [blur-active? show-background?
container-view (if blur-active? blur-container rn/view)
inline-container-style (if blur-active? style/blur-container style/view-container)
margin-bottom (reanimated/use-shared-value (get-margin-bottom show-background?
keyboard-shown?))]
(rn/use-effect #(reanimated/animate-shared-value-with-timing
margin-bottom
(get-margin-bottom show-background? keyboard-shown?)
duration
:easing4)
[show-background? keyboard-shown?])
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:margin-bottom margin-bottom}
{:margin-top :auto})}
[container-view
{:on-layout on-layout
:theme theme
:style
(merge inline-container-style)}
children]]))

(defn view
[props children]
[:f> f-view props children])
15 changes: 15 additions & 0 deletions src/status_im2/common/floating_button_page/style.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
(ns status-im2.common.floating-button-page.style)

(def page-container
{:position :absolute
:top 0
:bottom 0
:left 0
:right 0})

(def keyboard-avoiding-view
{:position :absolute
:top 0
:bottom 0
:left 0
:right 0})
114 changes: 114 additions & 0 deletions src/status_im2/common/floating_button_page/view.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
(ns status-im2.common.floating-button-page.view
(:require
[oops.core :as oops]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.hooks :as hooks]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im2.common.floating-button-page.floating-container.view :as floating-container]
[status-im2.common.floating-button-page.style :as style]))

(defn- show-background-android
[{:keys [window-height keyboard-height floating-container-height
content-scroll-y content-container-height header-height]} keyboard-shown?]
(let [available-space (- window-height
keyboard-height
floating-container-height
(safe-area/get-top)
(safe-area/get-bottom))
content-height (+ content-scroll-y
content-container-height
header-height)]
(and keyboard-shown? (< available-space content-height))))

(defn- show-background-ios
[{:keys [window-height keyboard-height floating-container-height
content-scroll-y content-container-height header-height]} keyboard-shown?]
(let [available-space (- window-height
keyboard-height
floating-container-height
(safe-area/get-top))
content-height (+ (safe-area/get-bottom)
header-height
content-scroll-y
content-container-height)]
(and keyboard-shown? (< content-height available-space))))

(defn show-background
[props keyboard-shown?]
(if platform/android?
(show-background-android props keyboard-shown?)
(show-background-ios props keyboard-shown?)))

(defn f-view
[{:keys [header footer]}
page-content]
(reagent/with-let [theme (quo.theme/use-theme-value)
window-height (:height (rn/get-window))

floating-container-height (reagent/atom 0)
header-height (reagent/atom 0)
content-container-height (reagent/atom 0)
show-keyboard? (reagent/atom false)
content-scroll-y (reagent/atom 0)

show-listener (oops/ocall rn/keyboard
"addListener"
(if platform/android?
"keyboardDidShow"
"keyboardWillShow")
#(reset! show-keyboard? true))
hide-listener (oops/ocall rn/keyboard
"addListener"
(if platform/android?
"keyboardDidHide"
"keyboardWillHide")
#(reset! show-keyboard? false))]
(let [{:keys [keyboard-shown
keyboard-height]} (hooks/use-keyboard)
show-background? (show-background {:window-height window-height
:floating-container-height
@floating-container-height
:keyboard-height keyboard-height
:content-scroll-y @content-scroll-y
:content-container-height @content-container-height
:header-height @header-height}
keyboard-shown)]

[rn/view {:style style/page-container}
[rn/view
{:on-layout (fn [event]
(let [height (oops/oget event "nativeEvent.layout.height")]
(reset! header-height height)))}
header]
[rn/scroll-view
{:on-scroll (fn [event]
(let [y (oops/oget event "nativeEvent.contentOffset.y")]
(reset! content-scroll-y y)))
:scroll-event-throttle 64
:content-container-style {:flexGrow 1}}
[rn/view
{:on-layout (fn [event]
(let [height (oops/oget event "nativeEvent.layout.height")]
(reset! content-container-height height)))}
page-content]]
[rn/keyboard-avoiding-view
{:style style/keyboard-avoiding-view
:pointer-events :box-none}
[floating-container/view
{:theme theme
:keyboard-shown? keyboard-shown
:show-background? show-background?
:on-layout (fn [event]
(let [height (oops/oget event "nativeEvent.layout.height")]
(reset! floating-container-height height)))}
footer]]])
(finally
(oops/ocall show-listener "remove")
(oops/ocall hide-listener "remove"))))

(defn view
[props header page-content button-component]
[:f> f-view props header page-content button-component])
4 changes: 2 additions & 2 deletions src/status_im2/contexts/quo_preview/common.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@


(defn- view-internal
[{:keys [theme]}]
[{:keys [theme title]}]
(let [logged-in? (rf/sub [:multiaccount/logged-in?])
has-profiles? (boolean (rf/sub [:profile/profiles-overview]))
root (if has-profiles? :profiles :intro)
light? (= theme :light)]
[quo/page-nav
{:type :title
:title "quo components preview"
:title title
:text-align :left
:icon-name :i/close
:right-side [{:icon-name (if light? :i/dark :i/light)
Expand Down
2 changes: 1 addition & 1 deletion src/status_im2/contexts/quo_preview/main.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@
(defn- main-screen
[]
[:<>
[common/navigation-bar]
[common/navigation-bar {:title "Quo components preview"}]
[rn/scroll-view {:style (style/main)}
(for [category (sort screens-categories)]
^{:key (first category)}
Expand Down
Loading

0 comments on commit 67339ee

Please sign in to comment.