Commit 70c9cce4 authored by tom's avatar tom

sticky pagination for blocks

parent 0f710c19
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;
}
......@@ -93,7 +93,7 @@ const BlocksContent = ({ type, query }: Props) => {
<>
{ 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>
<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={ 80 } page={ 1 }/></Hide>
</>
);
......
......@@ -24,7 +24,7 @@ const BlockPageContent = () => {
return (
<Page>
<PageTitle text={ `Block #${ router.query.id }` }/>
<RoutedTabs tabs={ TABS } tabListMarginBottom={{ base: 6, lg: 8 }}/>
<RoutedTabs tabs={ TABS }/>
</Page>
);
};
......
......@@ -5,6 +5,7 @@ import type { BlockType } from 'types/api/block';
import { QueryKeys } from 'types/client/queries';
import type { RoutedTab } from 'ui/shared/RoutedTabs/types';
import useIsMobile from 'lib/hooks/useIsMobile';
import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import BlocksContent from 'ui/blocks/BlocksContent';
import BlocksTabSlot from 'ui/blocks/BlocksTabSlot';
......@@ -18,8 +19,15 @@ const TAB_TO_TYPE: Record<string, BlockType> = {
uncles: 'uncle',
};
const TAB_LIST_PROPS = {
marginBottom: 0,
py: 5,
marginTop: -5,
};
const BlocksPageContent = () => {
const router = useRouter();
const isMobile = useIsMobile();
const type = router.query.tab && !Array.isArray(router.query.tab) ? TAB_TO_TYPE[router.query.tab] : undefined;
const blocksQuery = useQueryWithPages({
apiPath: '/node-api/blocks',
......@@ -38,8 +46,9 @@ const BlocksPageContent = () => {
<PageTitle text="Blocks"/>
<RoutedTabs
tabs={ tabs }
tabListMarginBottom={{ base: 6, lg: 8 }}
tabListProps={ isMobile ? undefined : TAB_LIST_PROPS }
rightSlot={ <BlocksTabSlot pagination={ blocksQuery.pagination }/> }
stickyEnabled={ !isMobile }
/>
</Page>
);
......
......@@ -20,7 +20,7 @@ const PrivateTags = () => {
return (
<Page>
<PageTitle text="Private tags"/>
<RoutedTabs tabs={ TABS } tabListMarginBottom={{ base: 6, lg: 8 }}/>
<RoutedTabs tabs={ TABS }/>
</Page>
);
};
......
......@@ -82,7 +82,7 @@ const TransactionPageContent = () => {
</Flex>
) }
</Flex>
<RoutedTabs tabs={ TABS } tabListMarginBottom={{ base: 6, lg: 8 }}/>
<RoutedTabs tabs={ TABS }/>
</Page>
);
};
......
......@@ -22,7 +22,7 @@ const Transactions = () => {
<Page hideMobileHeaderOnScrollDown>
<Box h="100%">
<PageTitle text="Transactions"/>
<RoutedTabs tabs={ TABS } tabListMarginBottom={{ base: 6, lg: 8 }}/>
<RoutedTabs tabs={ TABS }/>
</Box>
</Page>
);
......
import { Flex, useColorModeValue, chakra } from '@chakra-ui/react';
import throttle from 'lodash/throttle';
import React from 'react';
import { useScrollDirection } from 'lib/contexts/scrollDirection';
import useIsSticky from 'lib/hooks/useIsSticky';
type Props = {
children: React.ReactNode;
......@@ -13,32 +13,9 @@ const TOP_UP = 106;
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 (
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 isSticky = useIsSticky(ref, TOP_UP + 5);
const bgColor = useColorModeValue('white', 'black');
return (
......
......@@ -6,6 +6,7 @@ import {
TabPanel,
TabPanels,
Box,
useColorModeValue,
} from '@chakra-ui/react';
import type { StyleProps } from '@chakra-ui/styled-system';
import { useRouter } from 'next/router';
......@@ -13,7 +14,9 @@ import React, { useEffect, useState } from 'react';
import type { RoutedTab } from './types';
import { useScrollDirection } from 'lib/contexts/scrollDirection';
import useIsMobile from 'lib/hooks/useIsMobile';
import useIsSticky from 'lib/hooks/useIsSticky';
import RoutedTabsMenu from './RoutedTabsMenu';
import useAdaptiveTabs from './useAdaptiveTabs';
......@@ -27,12 +30,14 @@ const hiddenItemStyles: StyleProps = {
interface Props {
tabs: Array<RoutedTab>;
tabListMarginBottom?: ChakraProps['marginBottom'];
tabListProps?: ChakraProps;
rightSlot?: React.ReactNode;
stickyEnabled?: boolean;
}
const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
const RoutedTabs = ({ tabs, tabListProps, rightSlot, stickyEnabled }: Props) => {
const router = useRouter();
const scrollDirection = useScrollDirection();
const [ activeTabIndex, setActiveTabIndex ] = useState<number>(tabs.length + 1);
useEffect(() => {
......@@ -50,6 +55,8 @@ const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
const isMobile = useIsMobile();
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 nextTab = tabs[index];
......@@ -62,9 +69,16 @@ const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
}, [ tabs, router ]);
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
marginBottom={ tabListMarginBottom }
marginBottom={{ base: 6, lg: 8 }}
flexWrap="nowrap"
whiteSpace="nowrap"
ref={ listRef }
......@@ -80,6 +94,18 @@ const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
'-ms-overflow-style': 'none', /* IE and Edge */
'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' ? `0px` : `106px`, lg: 0 },
zIndex: { base: 'sticky2', lg: 'docked' },
} : { })
}
{ ...tabListProps }
>
{ tabsList.map((tab, index) => {
if (!tab.id) {
......@@ -114,8 +140,8 @@ const RoutedTabs = ({ tabs, tabListMarginBottom, rightSlot }: Props) => {
</Tab>
);
}) }
{ rightSlot ? <Box ref={ rightSlotRef } ml="auto" > { rightSlot } </Box> : null }
</TabList>
{ rightSlot ? <Box position="absolute" top={ 0 } right={ 0 } ref={ rightSlotRef }>{ rightSlot }</Box> : null }
<TabPanels>
{ tabsList.map((tab) => <TabPanel padding={ 0 } key={ tab.id }>{ tab.component }</TabPanel>) }
</TabPanels>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment