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
70c9cce4
Commit
70c9cce4
authored
Nov 30, 2022
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sticky pagination for blocks
parent
0f710c19
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
82 additions
and
36 deletions
+82
-36
useIsSticky.tsx
lib/hooks/useIsSticky.tsx
+34
-0
BlocksContent.tsx
ui/blocks/BlocksContent.tsx
+1
-1
Block.tsx
ui/pages/Block.tsx
+1
-1
Blocks.tsx
ui/pages/Blocks.tsx
+10
-1
PrivateTags.tsx
ui/pages/PrivateTags.tsx
+1
-1
Transaction.tsx
ui/pages/Transaction.tsx
+1
-1
Transactions.tsx
ui/pages/Transactions.tsx
+1
-1
ActionBar.tsx
ui/shared/ActionBar.tsx
+2
-25
RoutedTabs.tsx
ui/shared/RoutedTabs/RoutedTabs.tsx
+31
-5
No files found.
lib/hooks/useIsSticky.tsx
0 → 100644
View file @
70c9cce4
import
throttle
from
'
lodash/throttle
'
;
import
React
from
'
react
'
;
export
default
function
useIsSticky
(
ref
:
React
.
RefObject
<
HTMLDivElement
>
,
offset
=
0
,
isEnabled
=
true
)
{
const
[
isSticky
,
setIsSticky
]
=
React
.
useState
(
false
);
const
handleScroll
=
React
.
useCallback
(()
=>
{
if
(
Number
(
ref
.
current
?.
getBoundingClientRect
().
y
)
<
offset
)
{
setIsSticky
(
true
);
}
else
{
setIsSticky
(
false
);
}
},
[
ref
,
offset
]);
React
.
useEffect
(()
=>
{
if
(
!
isEnabled
)
{
return
;
}
const
throttledHandleScroll
=
throttle
(
handleScroll
,
300
);
window
.
addEventListener
(
'
scroll
'
,
throttledHandleScroll
);
return
()
=>
{
window
.
removeEventListener
(
'
scroll
'
,
throttledHandleScroll
);
};
// replicate componentDidMount
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[
isEnabled
]);
return
isSticky
;
}
ui/blocks/BlocksContent.tsx
View file @
70c9cce4
...
@@ -93,7 +93,7 @@ const BlocksContent = ({ type, query }: Props) => {
...
@@ -93,7 +93,7 @@ const BlocksContent = ({ type, query }: Props) => {
<>
<>
{
socketAlert
&&
<
Alert
status=
"warning"
mb=
{
6
}
as=
"a"
href=
{
window
.
document
.
location
.
href
}
>
{
socketAlert
}
</
Alert
>
}
{
socketAlert
&&
<
Alert
status=
"warning"
mb=
{
6
}
as=
"a"
href=
{
window
.
document
.
location
.
href
}
>
{
socketAlert
}
</
Alert
>
}
<
Show
below=
"lg"
key=
"content-mobile"
><
BlocksList
data=
{
query
.
data
.
items
}
/></
Show
>
<
Show
below=
"lg"
key=
"content-mobile"
><
BlocksList
data=
{
query
.
data
.
items
}
/></
Show
>
<
Hide
below=
"lg"
key=
"content-desktop"
><
BlocksTable
data=
{
query
.
data
.
items
}
top=
{
0
}
page=
{
1
}
/></
Hide
>
<
Hide
below=
"lg"
key=
"content-desktop"
><
BlocksTable
data=
{
query
.
data
.
items
}
top=
{
8
0
}
page=
{
1
}
/></
Hide
>
</>
</>
);
);
...
...
ui/pages/Block.tsx
View file @
70c9cce4
...
@@ -24,7 +24,7 @@ const BlockPageContent = () => {
...
@@ -24,7 +24,7 @@ const BlockPageContent = () => {
return
(
return
(
<
Page
>
<
Page
>
<
PageTitle
text=
{
`Block #${ router.query.id }`
}
/>
<
PageTitle
text=
{
`Block #${ router.query.id }`
}
/>
<
RoutedTabs
tabs=
{
TABS
}
tabListMarginBottom=
{
{
base
:
6
,
lg
:
8
}
}
/>
<
RoutedTabs
tabs=
{
TABS
}
/>
</
Page
>
</
Page
>
);
);
};
};
...
...
ui/pages/Blocks.tsx
View file @
70c9cce4
...
@@ -5,6 +5,7 @@ import type { BlockType } from 'types/api/block';
...
@@ -5,6 +5,7 @@ import type { BlockType } from 'types/api/block';
import
{
QueryKeys
}
from
'
types/client/queries
'
;
import
{
QueryKeys
}
from
'
types/client/queries
'
;
import
type
{
RoutedTab
}
from
'
ui/shared/RoutedTabs/types
'
;
import
type
{
RoutedTab
}
from
'
ui/shared/RoutedTabs/types
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
useQueryWithPages
from
'
lib/hooks/useQueryWithPages
'
;
import
useQueryWithPages
from
'
lib/hooks/useQueryWithPages
'
;
import
BlocksContent
from
'
ui/blocks/BlocksContent
'
;
import
BlocksContent
from
'
ui/blocks/BlocksContent
'
;
import
BlocksTabSlot
from
'
ui/blocks/BlocksTabSlot
'
;
import
BlocksTabSlot
from
'
ui/blocks/BlocksTabSlot
'
;
...
@@ -18,8 +19,15 @@ const TAB_TO_TYPE: Record<string, BlockType> = {
...
@@ -18,8 +19,15 @@ const TAB_TO_TYPE: Record<string, BlockType> = {
uncles
:
'
uncle
'
,
uncles
:
'
uncle
'
,
};
};
const
TAB_LIST_PROPS
=
{
marginBottom
:
0
,
py
:
5
,
marginTop
:
-
5
,
};
const
BlocksPageContent
=
()
=>
{
const
BlocksPageContent
=
()
=>
{
const
router
=
useRouter
();
const
router
=
useRouter
();
const
isMobile
=
useIsMobile
();
const
type
=
router
.
query
.
tab
&&
!
Array
.
isArray
(
router
.
query
.
tab
)
?
TAB_TO_TYPE
[
router
.
query
.
tab
]
:
undefined
;
const
type
=
router
.
query
.
tab
&&
!
Array
.
isArray
(
router
.
query
.
tab
)
?
TAB_TO_TYPE
[
router
.
query
.
tab
]
:
undefined
;
const
blocksQuery
=
useQueryWithPages
({
const
blocksQuery
=
useQueryWithPages
({
apiPath
:
'
/node-api/blocks
'
,
apiPath
:
'
/node-api/blocks
'
,
...
@@ -38,8 +46,9 @@ const BlocksPageContent = () => {
...
@@ -38,8 +46,9 @@ const BlocksPageContent = () => {
<
PageTitle
text=
"Blocks"
/>
<
PageTitle
text=
"Blocks"
/>
<
RoutedTabs
<
RoutedTabs
tabs=
{
tabs
}
tabs=
{
tabs
}
tabList
MarginBottom=
{
{
base
:
6
,
lg
:
8
}
}
tabList
Props=
{
isMobile
?
undefined
:
TAB_LIST_PROPS
}
rightSlot=
{
<
BlocksTabSlot
pagination=
{
blocksQuery
.
pagination
}
/>
}
rightSlot=
{
<
BlocksTabSlot
pagination=
{
blocksQuery
.
pagination
}
/>
}
stickyEnabled=
{
!
isMobile
}
/>
/>
</
Page
>
</
Page
>
);
);
...
...
ui/pages/PrivateTags.tsx
View file @
70c9cce4
...
@@ -20,7 +20,7 @@ const PrivateTags = () => {
...
@@ -20,7 +20,7 @@ const PrivateTags = () => {
return
(
return
(
<
Page
>
<
Page
>
<
PageTitle
text=
"Private tags"
/>
<
PageTitle
text=
"Private tags"
/>
<
RoutedTabs
tabs=
{
TABS
}
tabListMarginBottom=
{
{
base
:
6
,
lg
:
8
}
}
/>
<
RoutedTabs
tabs=
{
TABS
}
/>
</
Page
>
</
Page
>
);
);
};
};
...
...
ui/pages/Transaction.tsx
View file @
70c9cce4
...
@@ -82,7 +82,7 @@ const TransactionPageContent = () => {
...
@@ -82,7 +82,7 @@ const TransactionPageContent = () => {
</
Flex
>
</
Flex
>
)
}
)
}
</
Flex
>
</
Flex
>
<
RoutedTabs
tabs=
{
TABS
}
tabListMarginBottom=
{
{
base
:
6
,
lg
:
8
}
}
/>
<
RoutedTabs
tabs=
{
TABS
}
/>
</
Page
>
</
Page
>
);
);
};
};
...
...
ui/pages/Transactions.tsx
View file @
70c9cce4
...
@@ -22,7 +22,7 @@ const Transactions = () => {
...
@@ -22,7 +22,7 @@ const Transactions = () => {
<
Page
hideMobileHeaderOnScrollDown
>
<
Page
hideMobileHeaderOnScrollDown
>
<
Box
h=
"100%"
>
<
Box
h=
"100%"
>
<
PageTitle
text=
"Transactions"
/>
<
PageTitle
text=
"Transactions"
/>
<
RoutedTabs
tabs=
{
TABS
}
tabListMarginBottom=
{
{
base
:
6
,
lg
:
8
}
}
/>
<
RoutedTabs
tabs=
{
TABS
}
/>
</
Box
>
</
Box
>
</
Page
>
</
Page
>
);
);
...
...
ui/shared/ActionBar.tsx
View file @
70c9cce4
import
{
Flex
,
useColorModeValue
,
chakra
}
from
'
@chakra-ui/react
'
;
import
{
Flex
,
useColorModeValue
,
chakra
}
from
'
@chakra-ui/react
'
;
import
throttle
from
'
lodash/throttle
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
{
useScrollDirection
}
from
'
lib/contexts/scrollDirection
'
;
import
{
useScrollDirection
}
from
'
lib/contexts/scrollDirection
'
;
import
useIsSticky
from
'
lib/hooks/useIsSticky
'
;
type
Props
=
{
type
Props
=
{
children
:
React
.
ReactNode
;
children
:
React
.
ReactNode
;
...
@@ -13,32 +13,9 @@ const TOP_UP = 106;
...
@@ -13,32 +13,9 @@ const TOP_UP = 106;
const
TOP_DOWN
=
0
;
const
TOP_DOWN
=
0
;
const
ActionBar
=
({
children
,
className
}:
Props
)
=>
{
const
ActionBar
=
({
children
,
className
}:
Props
)
=>
{
const
[
isSticky
,
setIsSticky
]
=
React
.
useState
(
false
);
const
ref
=
React
.
useRef
<
HTMLDivElement
>
(
null
);
const
ref
=
React
.
useRef
<
HTMLDivElement
>
(
null
);
const
scrollDirection
=
useScrollDirection
();
const
scrollDirection
=
useScrollDirection
();
const
isSticky
=
useIsSticky
(
ref
,
TOP_UP
+
5
);
const
handleScroll
=
React
.
useCallback
(()
=>
{
if
(
Number
(
ref
.
current
?.
getBoundingClientRect
().
y
)
<
TOP_UP
+
5
)
{
setIsSticky
(
true
);
}
else
{
setIsSticky
(
false
);
}
},
[
]);
React
.
useEffect
(()
=>
{
const
throttledHandleScroll
=
throttle
(
handleScroll
,
300
);
window
.
addEventListener
(
'
scroll
'
,
throttledHandleScroll
);
return
()
=>
{
window
.
removeEventListener
(
'
scroll
'
,
throttledHandleScroll
);
};
// replicate componentDidMount
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[
]);
const
bgColor
=
useColorModeValue
(
'
white
'
,
'
black
'
);
const
bgColor
=
useColorModeValue
(
'
white
'
,
'
black
'
);
return
(
return
(
...
...
ui/shared/RoutedTabs/RoutedTabs.tsx
View file @
70c9cce4
...
@@ -6,6 +6,7 @@ import {
...
@@ -6,6 +6,7 @@ import {
TabPanel
,
TabPanel
,
TabPanels
,
TabPanels
,
Box
,
Box
,
useColorModeValue
,
}
from
'
@chakra-ui/react
'
;
}
from
'
@chakra-ui/react
'
;
import
type
{
StyleProps
}
from
'
@chakra-ui/styled-system
'
;
import
type
{
StyleProps
}
from
'
@chakra-ui/styled-system
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
{
useRouter
}
from
'
next/router
'
;
...
@@ -13,7 +14,9 @@ import React, { useEffect, useState } from 'react';
...
@@ -13,7 +14,9 @@ import React, { useEffect, useState } from 'react';
import
type
{
RoutedTab
}
from
'
./types
'
;
import
type
{
RoutedTab
}
from
'
./types
'
;
import
{
useScrollDirection
}
from
'
lib/contexts/scrollDirection
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
useIsSticky
from
'
lib/hooks/useIsSticky
'
;
import
RoutedTabsMenu
from
'
./RoutedTabsMenu
'
;
import
RoutedTabsMenu
from
'
./RoutedTabsMenu
'
;
import
useAdaptiveTabs
from
'
./useAdaptiveTabs
'
;
import
useAdaptiveTabs
from
'
./useAdaptiveTabs
'
;
...
@@ -27,12 +30,14 @@ const hiddenItemStyles: StyleProps = {
...
@@ -27,12 +30,14 @@ const hiddenItemStyles: StyleProps = {
interface
Props
{
interface
Props
{
tabs
:
Array
<
RoutedTab
>
;
tabs
:
Array
<
RoutedTab
>
;
tabList
MarginBottom
?:
ChakraProps
[
'
marginBottom
'
]
;
tabList
Props
?:
ChakraProps
;
rightSlot
?:
React
.
ReactNode
;
rightSlot
?:
React
.
ReactNode
;
stickyEnabled
?:
boolean
;
}
}
const
RoutedTabs
=
({
tabs
,
tabList
MarginBottom
,
rightSlot
}:
Props
)
=>
{
const
RoutedTabs
=
({
tabs
,
tabList
Props
,
rightSlot
,
stickyEnabled
}:
Props
)
=>
{
const
router
=
useRouter
();
const
router
=
useRouter
();
const
scrollDirection
=
useScrollDirection
();
const
[
activeTabIndex
,
setActiveTabIndex
]
=
useState
<
number
>
(
tabs
.
length
+
1
);
const
[
activeTabIndex
,
setActiveTabIndex
]
=
useState
<
number
>
(
tabs
.
length
+
1
);
useEffect
(()
=>
{
useEffect
(()
=>
{
...
@@ -50,6 +55,8 @@ const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
...
@@ -50,6 +55,8 @@ const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
const
isMobile
=
useIsMobile
();
const
isMobile
=
useIsMobile
();
const
{
tabsCut
,
tabsList
,
tabsRefs
,
listRef
,
rightSlotRef
}
=
useAdaptiveTabs
(
tabs
,
isMobile
);
const
{
tabsCut
,
tabsList
,
tabsRefs
,
listRef
,
rightSlotRef
}
=
useAdaptiveTabs
(
tabs
,
isMobile
);
const
isSticky
=
useIsSticky
(
listRef
,
5
,
stickyEnabled
);
const
listBgColor
=
useColorModeValue
(
'
white
'
,
'
black
'
);
const
handleTabChange
=
React
.
useCallback
((
index
:
number
)
=>
{
const
handleTabChange
=
React
.
useCallback
((
index
:
number
)
=>
{
const
nextTab
=
tabs
[
index
];
const
nextTab
=
tabs
[
index
];
...
@@ -62,9 +69,16 @@ const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
...
@@ -62,9 +69,16 @@ const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
},
[
tabs
,
router
]);
},
[
tabs
,
router
]);
return
(
return
(
<
Tabs
variant=
"soft-rounded"
colorScheme=
"blue"
isLazy
onChange=
{
handleTabChange
}
index=
{
activeTabIndex
}
position=
"relative"
>
<
Tabs
variant=
"soft-rounded"
colorScheme=
"blue"
isLazy
onChange=
{
handleTabChange
}
index=
{
activeTabIndex
}
position=
"relative"
>
<
TabList
<
TabList
marginBottom=
{
tabListMarginBottom
}
marginBottom=
{
{
base
:
6
,
lg
:
8
}
}
flexWrap=
"nowrap"
flexWrap=
"nowrap"
whiteSpace=
"nowrap"
whiteSpace=
"nowrap"
ref=
{
listRef
}
ref=
{
listRef
}
...
@@ -80,6 +94,18 @@ const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
...
@@ -80,6 +94,18 @@ const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
'
-ms-overflow-style
'
:
'
none
'
,
/* IE and Edge */
'
-ms-overflow-style
'
:
'
none
'
,
/* IE and Edge */
'
scrollbar-width
'
:
'
none
'
,
/* Firefox */
'
scrollbar-width
'
:
'
none
'
,
/* Firefox */
}
}
}
}
bgColor=
{
listBgColor
}
transitionProperty=
"top,box-shadow,background-color,color"
transitionDuration=
"slow"
{
...
(
stickyEnabled
?
{
position
:
'
sticky
',
boxShadow
:
{
base
:
isSticky
?
'
md
'
:
'
none
',
lg
:
'
none
'
},
top
:
{
base
:
scrollDirection
===
'
down
'
?
`0
px
`
:
`106
px
`,
lg
:
0
},
zIndex
:
{
base
:
'
sticky2
',
lg
:
'
docked
'
},
}
:
{
})
}
{
...
tabListProps
}
>
>
{
tabsList
.
map
((
tab
,
index
)
=>
{
{
tabsList
.
map
((
tab
,
index
)
=>
{
if
(
!
tab
.
id
)
{
if
(
!
tab
.
id
)
{
...
@@ -114,8 +140,8 @@ const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
...
@@ -114,8 +140,8 @@ const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
</
Tab
>
</
Tab
>
);
);
})
}
})
}
{
rightSlot
?
<
Box
ref=
{
rightSlotRef
}
ml=
"auto"
>
{
rightSlot
}
</
Box
>
:
null
}
</
TabList
>
</
TabList
>
{
rightSlot
?
<
Box
position=
"absolute"
top=
{
0
}
right=
{
0
}
ref=
{
rightSlotRef
}
>
{
rightSlot
}
</
Box
>
:
null
}
<
TabPanels
>
<
TabPanels
>
{
tabsList
.
map
((
tab
)
=>
<
TabPanel
padding=
{
0
}
key=
{
tab
.
id
}
>
{
tab
.
component
}
</
TabPanel
>)
}
{
tabsList
.
map
((
tab
)
=>
<
TabPanel
padding=
{
0
}
key=
{
tab
.
id
}
>
{
tab
.
component
}
</
TabPanel
>)
}
</
TabPanels
>
</
TabPanels
>
...
...
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