Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
frontend
Commits
0f710c19
Commit
0f710c19
authored
Nov 30, 2022
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor scroll direction context
parent
7bc58a3f
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
123 additions
and
123 deletions
+123
-123
scrollDirection.tsx
lib/contexts/scrollDirection.tsx
+23
-6
_app.tsx
pages/_app.tsx
+3
-6
ScrollDirectionContext.tsx
ui/ScrollDirectionContext.tsx
+0
-5
ActionBar.tsx
ui/shared/ActionBar.tsx
+20
-23
Header.tsx
ui/snippets/header/Header.tsx
+44
-47
SearchBarMobile.tsx
ui/snippets/searchBar/SearchBarMobile.tsx
+33
-36
No files found.
lib/
hooks/useScrollDirection.ts
→
lib/
contexts/scrollDirection.tsx
View file @
0f710c19
...
...
@@ -2,22 +2,27 @@ import clamp from 'lodash/clamp';
import
throttle
from
'
lodash/throttle
'
;
import
React
from
'
react
'
;
const
ScrollDirectionContext
=
React
.
createContext
<
'
up
'
|
'
down
'
|
null
>
(
null
);
import
isBrowser
from
'
lib/isBrowser
'
;
const
SCROLL_DIFF_THRESHOLD
=
20
;
type
Directions
=
'
up
'
|
'
down
'
;
export
default
function
useScrollDirection
()
{
interface
Props
{
children
:
React
.
ReactNode
;
}
export
function
ScrollDirectionProvider
({
children
}:
Props
)
{
const
prevScrollPosition
=
React
.
useRef
(
isBrowser
()
?
window
.
pageYOffset
:
0
);
const
[
scrollDirection
,
setDirection
]
=
React
.
useState
<
Directions
>
(
);
const
[
scrollDirection
,
setDirection
]
=
React
.
useState
<
Directions
|
null
>
(
null
);
const
handleScroll
=
React
.
useCallback
(()
=>
{
const
currentScrollPosition
=
clamp
(
window
.
pageYOffset
,
0
,
window
.
document
.
body
.
scrollHeight
-
window
.
innerHeight
);
const
scrollDiff
=
currentScrollPosition
-
prevScrollPosition
.
current
;
if
(
window
.
pageYOffset
===
0
)
{
setDirection
(
undefined
);
setDirection
(
null
);
}
else
if
(
Math
.
abs
(
scrollDiff
)
>
SCROLL_DIFF_THRESHOLD
)
{
setDirection
(
scrollDiff
<
0
?
'
up
'
:
'
down
'
);
}
...
...
@@ -33,9 +38,21 @@ export default function useScrollDirection() {
return
()
=>
{
window
.
removeEventListener
(
'
scroll
'
,
throttledHandleScroll
);
};
// replicate componentDidMount
// eslint-disable-next-line react-hooks/exhaustive-deps
// replicate componentDidMount
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[]);
return
scrollDirection
;
return
(
<
ScrollDirectionContext
.
Provider
value=
{
scrollDirection
}
>
{
children
}
</
ScrollDirectionContext
.
Provider
>
);
}
export
function
useScrollDirection
()
{
const
context
=
React
.
useContext
(
ScrollDirectionContext
);
if
(
context
===
undefined
)
{
throw
new
Error
(
'
useScrollDirection must be used within a ScrollDirectionProvider
'
);
}
return
context
;
}
pages/_app.tsx
View file @
0f710c19
...
...
@@ -7,19 +7,16 @@ import React, { useState } from 'react';
import
appConfig
from
'
configs/app/config
'
;
import
{
AppContextProvider
}
from
'
lib/appContext
'
;
import
{
Chakra
}
from
'
lib/Chakra
'
;
import
{
ScrollDirectionProvider
}
from
'
lib/contexts/scrollDirection
'
;
import
useConfigSentry
from
'
lib/hooks/useConfigSentry
'
;
import
type
{
ErrorType
}
from
'
lib/hooks/useFetch
'
;
import
useScrollDirection
from
'
lib/hooks/useScrollDirection
'
;
import
{
SocketProvider
}
from
'
lib/socket/context
'
;
import
theme
from
'
theme
'
;
import
ScrollDirectionContext
from
'
ui/ScrollDirectionContext
'
;
import
AppError
from
'
ui/shared/AppError/AppError
'
;
import
ErrorBoundary
from
'
ui/shared/ErrorBoundary
'
;
function
MyApp
({
Component
,
pageProps
}:
AppProps
)
{
useConfigSentry
();
const
directionContext
=
useScrollDirection
();
const
[
queryClient
]
=
useState
(()
=>
new
QueryClient
({
defaultOptions
:
{
queries
:
{
...
...
@@ -62,11 +59,11 @@ function MyApp({ Component, pageProps }: AppProps) {
<
ErrorBoundary
renderErrorScreen=
{
renderErrorScreen
}
onError=
{
handleError
}
>
<
AppContextProvider
pageProps=
{
pageProps
}
>
<
QueryClientProvider
client=
{
queryClient
}
>
<
ScrollDirection
Context
.
Provider
value=
{
directionContext
}
>
<
ScrollDirection
Provider
>
<
SocketProvider
url=
{
`${ appConfig.api.socket }${ appConfig.api.basePath }/socket/v2`
}
>
<
Component
{
...
pageProps
}
/>
</
SocketProvider
>
</
ScrollDirection
Context
.
Provider
>
</
ScrollDirectionProvider
>
<
ReactQueryDevtools
/>
</
QueryClientProvider
>
</
AppContextProvider
>
...
...
ui/ScrollDirectionContext.tsx
deleted
100644 → 0
View file @
7bc58a3f
import
React
from
'
react
'
;
const
ScrollDirectionContext
=
React
.
createContext
<
'
up
'
|
'
down
'
|
undefined
>
(
undefined
);
export
default
ScrollDirectionContext
;
ui/shared/ActionBar.tsx
View file @
0f710c19
...
...
@@ -2,7 +2,7 @@ import { Flex, useColorModeValue, chakra } from '@chakra-ui/react';
import
throttle
from
'
lodash/throttle
'
;
import
React
from
'
react
'
;
import
ScrollDirectionContext
from
'
ui/ScrollDirectionContext
'
;
import
{
useScrollDirection
}
from
'
lib/contexts/scrollDirection
'
;
type
Props
=
{
children
:
React
.
ReactNode
;
...
...
@@ -15,6 +15,7 @@ const TOP_DOWN = 0;
const
ActionBar
=
({
children
,
className
}:
Props
)
=>
{
const
[
isSticky
,
setIsSticky
]
=
React
.
useState
(
false
);
const
ref
=
React
.
useRef
<
HTMLDivElement
>
(
null
);
const
scrollDirection
=
useScrollDirection
();
const
handleScroll
=
React
.
useCallback
(()
=>
{
if
(
...
...
@@ -41,28 +42,24 @@ const ActionBar = ({ children, className }: Props) => {
const
bgColor
=
useColorModeValue
(
'
white
'
,
'
black
'
);
return
(
<
ScrollDirectionContext
.
Consumer
>
{
(
scrollDirection
)
=>
(
<
Flex
className=
{
className
}
backgroundColor=
{
bgColor
}
py=
{
6
}
mx=
{
{
base
:
-
4
,
lg
:
0
}
}
px=
{
{
base
:
4
,
lg
:
0
}
}
justifyContent=
"space-between"
width=
{
{
base
:
'
100vw
'
,
lg
:
'
unset
'
}
}
position=
"sticky"
top=
{
{
base
:
scrollDirection
===
'
down
'
?
`${ TOP_DOWN }px`
:
`${ TOP_UP }px`
,
lg
:
0
}
}
transitionProperty=
"top,box-shadow,background-color,color"
transitionDuration=
"slow"
zIndex=
{
{
base
:
'
sticky2
'
,
lg
:
'
docked
'
}
}
boxShadow=
{
{
base
:
isSticky
?
'
md
'
:
'
none
'
,
lg
:
'
none
'
}
}
ref=
{
ref
}
>
{
children
}
</
Flex
>
)
}
</
ScrollDirectionContext
.
Consumer
>
<
Flex
className=
{
className
}
backgroundColor=
{
bgColor
}
py=
{
6
}
mx=
{
{
base
:
-
4
,
lg
:
0
}
}
px=
{
{
base
:
4
,
lg
:
0
}
}
justifyContent=
"space-between"
width=
{
{
base
:
'
100vw
'
,
lg
:
'
unset
'
}
}
position=
"sticky"
top=
{
{
base
:
scrollDirection
===
'
down
'
?
`${ TOP_DOWN }px`
:
`${ TOP_UP }px`
,
lg
:
0
}
}
transitionProperty=
"top,box-shadow,background-color,color"
transitionDuration=
"slow"
zIndex=
{
{
base
:
'
sticky2
'
,
lg
:
'
docked
'
}
}
boxShadow=
{
{
base
:
isSticky
?
'
md
'
:
'
none
'
,
lg
:
'
none
'
}
}
ref=
{
ref
}
>
{
children
}
</
Flex
>
);
};
...
...
ui/snippets/header/Header.tsx
View file @
0f710c19
import
{
HStack
,
Box
,
Flex
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
ScrollDirectionContext
from
'
ui/ScrollDirectionContext
'
;
import
{
useScrollDirection
}
from
'
lib/contexts/scrollDirection
'
;
import
NetworkLogo
from
'
ui/snippets/networkMenu/NetworkLogo
'
;
import
ProfileMenuDesktop
from
'
ui/snippets/profileMenu/ProfileMenuDesktop
'
;
import
ProfileMenuMobile
from
'
ui/snippets/profileMenu/ProfileMenuMobile
'
;
...
...
@@ -17,56 +17,53 @@ type Props = {
const
Header
=
({
hideOnScrollDown
,
isHomePage
}:
Props
)
=>
{
const
bgColor
=
useColorModeValue
(
'
white
'
,
'
black
'
);
const
scrollDirection
=
useScrollDirection
();
return
(
<
ScrollDirectionContext
.
Consumer
>
{
(
scrollDirection
)
=>
(
<>
<
Box
bgColor=
{
bgColor
}
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
>
<
Flex
as=
"header"
position=
"fixed"
top=
{
0
}
left=
{
0
}
paddingX=
{
4
}
paddingY=
{
2
}
bgColor=
{
bgColor
}
width=
"100%"
alignItems=
"center"
justifyContent=
"space-between"
zIndex=
"sticky2"
transitionProperty=
"box-shadow"
transitionDuration=
"slow"
boxShadow=
{
!
hideOnScrollDown
&&
scrollDirection
===
'
down
'
?
'
md
'
:
'
none
'
}
>
<
Burger
/>
<
NetworkLogo
/>
<
ProfileMenuMobile
/>
</
Flex
>
{
!
isHomePage
&&
<
SearchBar
withShadow=
{
!
hideOnScrollDown
}
/>
}
<>
<
Box
bgColor=
{
bgColor
}
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
>
<
Flex
as=
"header"
position=
"fixed"
top=
{
0
}
left=
{
0
}
paddingX=
{
4
}
paddingY=
{
2
}
bgColor=
{
bgColor
}
width=
"100%"
alignItems=
"center"
justifyContent=
"space-between"
zIndex=
"sticky2"
transitionProperty=
"box-shadow"
transitionDuration=
"slow"
boxShadow=
{
!
hideOnScrollDown
&&
scrollDirection
===
'
down
'
?
'
md
'
:
'
none
'
}
>
<
Burger
/>
<
NetworkLogo
/>
<
ProfileMenuMobile
/>
</
Flex
>
{
!
isHomePage
&&
<
SearchBar
withShadow=
{
!
hideOnScrollDown
}
/>
}
</
Box
>
{
!
isHomePage
&&
(
<
HStack
as=
"header"
width=
"100%"
alignItems=
"center"
justifyContent=
"center"
gap=
{
12
}
display=
{
{
base
:
'
none
'
,
lg
:
'
flex
'
}
}
paddingX=
{
12
}
paddingTop=
{
9
}
paddingBottom=
"52px"
>
<
Box
width=
"100%"
>
<
SearchBar
/>
</
Box
>
{
!
isHomePage
&&
(
<
HStack
as=
"header"
width=
"100%"
alignItems=
"center"
justifyContent=
"center"
gap=
{
12
}
display=
{
{
base
:
'
none
'
,
lg
:
'
flex
'
}
}
paddingX=
{
12
}
paddingTop=
{
9
}
paddingBottom=
"52px"
>
<
Box
width=
"100%"
>
<
SearchBar
/>
</
Box
>
<
ColorModeToggler
/>
<
ProfileMenuDesktop
/>
</
HStack
>
)
}
</>
<
ColorModeToggler
/>
<
ProfileMenuDesktop
/>
</
HStack
>
)
}
</
ScrollDirectionContext
.
Consumer
>
</>
);
};
...
...
ui/snippets/searchBar/SearchBarMobile.tsx
View file @
0f710c19
...
...
@@ -4,7 +4,7 @@ import React from 'react';
import
type
{
ChangeEvent
,
FormEvent
}
from
'
react
'
;
import
searchIcon
from
'
icons/search.svg
'
;
import
ScrollDirectionContext
from
'
ui/ScrollDirectionContext
'
;
import
{
useScrollDirection
}
from
'
lib/contexts/scrollDirection
'
;
const
TOP
=
55
;
...
...
@@ -17,6 +17,7 @@ interface Props {
const
SearchBarMobile
=
({
onChange
,
onSubmit
,
withShadow
}:
Props
)
=>
{
const
[
isSticky
,
setIsSticky
]
=
React
.
useState
(
false
);
const
scrollDirection
=
useScrollDirection
();
const
handleScroll
=
React
.
useCallback
(()
=>
{
if
(
window
.
pageYOffset
!==
0
)
{
...
...
@@ -43,41 +44,37 @@ const SearchBarMobile = ({ onChange, onSubmit, withShadow }: Props) => {
const
bgColor
=
useColorModeValue
(
'
white
'
,
'
black
'
);
return
(
<
ScrollDirectionContext
.
Consumer
>
{
(
scrollDirection
)
=>
(
<
chakra
.
form
noValidate
onSubmit=
{
onSubmit
}
paddingX=
{
4
}
paddingTop=
{
1
}
paddingBottom=
{
2
}
position=
"fixed"
top=
{
`${ TOP }px`
}
left=
"0"
zIndex=
"sticky1"
bgColor=
{
bgColor
}
transform=
{
scrollDirection
!==
'
down
'
?
'
translateY(0)
'
:
'
translateY(-100%)
'
}
transitionProperty=
"transform,box-shadow"
transitionDuration=
"slow"
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
w=
"100%"
boxShadow=
{
withShadow
&&
scrollDirection
!==
'
down
'
&&
isSticky
?
'
md
'
:
'
none
'
}
>
<
InputGroup
size=
"sm"
>
<
InputLeftElement
>
<
Icon
as=
{
searchIcon
}
boxSize=
{
4
}
color=
{
searchIconColor
}
/>
</
InputLeftElement
>
<
Input
paddingInlineStart=
"38px"
placeholder=
"Search by addresses / ... "
ml=
"1px"
onChange=
{
onChange
}
borderColor=
{
inputBorderColor
}
/>
</
InputGroup
>
</
chakra
.
form
>
)
}
</
ScrollDirectionContext
.
Consumer
>
<
chakra
.
form
noValidate
onSubmit=
{
onSubmit
}
paddingX=
{
4
}
paddingTop=
{
1
}
paddingBottom=
{
2
}
position=
"fixed"
top=
{
`${ TOP }px`
}
left=
"0"
zIndex=
"sticky1"
bgColor=
{
bgColor
}
transform=
{
scrollDirection
!==
'
down
'
?
'
translateY(0)
'
:
'
translateY(-100%)
'
}
transitionProperty=
"transform,box-shadow"
transitionDuration=
"slow"
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
w=
"100%"
boxShadow=
{
withShadow
&&
scrollDirection
!==
'
down
'
&&
isSticky
?
'
md
'
:
'
none
'
}
>
<
InputGroup
size=
"sm"
>
<
InputLeftElement
>
<
Icon
as=
{
searchIcon
}
boxSize=
{
4
}
color=
{
searchIconColor
}
/>
</
InputLeftElement
>
<
Input
paddingInlineStart=
"38px"
placeholder=
"Search by addresses / ... "
ml=
"1px"
onChange=
{
onChange
}
borderColor=
{
inputBorderColor
}
/>
</
InputGroup
>
</
chakra
.
form
>
);
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment