Commit dc784018 authored by isstuev's avatar isstuev

another variant of sticky headers

parent a5976aed
...@@ -6,20 +6,22 @@ import isBrowser from 'lib/isBrowser'; ...@@ -6,20 +6,22 @@ import isBrowser from 'lib/isBrowser';
const SCROLL_DIFF_THRESHOLD = 20; const SCROLL_DIFF_THRESHOLD = 20;
export default function useScrollVisibility(direction: 'up' | 'down') { type Directions = 'up' | 'down';
export default function useScrollDirection() {
const prevScrollPosition = React.useRef(isBrowser() ? window.pageYOffset : 0); const prevScrollPosition = React.useRef(isBrowser() ? window.pageYOffset : 0);
const [ isVisible, setVisibility ] = React.useState(true); const [ scrollDirection, setDirection ] = React.useState<Directions>();
const handleScroll = React.useCallback(() => { const handleScroll = React.useCallback(() => {
const currentScrollPosition = clamp(window.pageYOffset, 0, window.document.body.scrollHeight - window.innerHeight); const currentScrollPosition = clamp(window.pageYOffset, 0, window.document.body.scrollHeight - window.innerHeight);
const scrollDiff = currentScrollPosition - prevScrollPosition.current; const scrollDiff = currentScrollPosition - prevScrollPosition.current;
if (Math.abs(scrollDiff) > SCROLL_DIFF_THRESHOLD) { if (Math.abs(scrollDiff) > SCROLL_DIFF_THRESHOLD) {
setVisibility(direction === 'up' ? scrollDiff < 0 : scrollDiff > 0); setDirection(scrollDiff < 0 ? 'up' : 'down');
} }
prevScrollPosition.current = currentScrollPosition; prevScrollPosition.current = currentScrollPosition;
}, [ direction ]); }, [ ]);
React.useEffect(() => { React.useEffect(() => {
const throttledHandleScroll = throttle(handleScroll, 300); const throttledHandleScroll = throttle(handleScroll, 300);
...@@ -33,5 +35,5 @@ export default function useScrollVisibility(direction: 'up' | 'down') { ...@@ -33,5 +35,5 @@ export default function useScrollVisibility(direction: 'up' | 'down') {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
return isVisible; return scrollDirection;
} }
...@@ -19,7 +19,7 @@ const Transactions = () => { ...@@ -19,7 +19,7 @@ const Transactions = () => {
]; ];
return ( return (
<Page> <Page hideMobileHeaderOnScrollDown>
<Box h="100%"> <Box h="100%">
<PageTitle text="Transactions"/> <PageTitle text="Transactions"/>
<RoutedTabs tabs={ TABS }/> <RoutedTabs tabs={ TABS }/>
......
...@@ -13,9 +13,10 @@ import NavigationDesktop from 'ui/snippets/navigation/NavigationDesktop'; ...@@ -13,9 +13,10 @@ import NavigationDesktop from 'ui/snippets/navigation/NavigationDesktop';
interface Props { interface Props {
children: React.ReactNode; children: React.ReactNode;
wrapChildren?: boolean; wrapChildren?: boolean;
hideMobileHeaderOnScrollDown?: boolean;
} }
const Page = ({ children, wrapChildren = true }: Props) => { const Page = ({ children, wrapChildren = true, hideMobileHeaderOnScrollDown }: Props) => {
const fetch = useFetch(); const fetch = useFetch();
useQuery<unknown, unknown, unknown>([ QueryKeys.csrf ], async() => await fetch('/node-api/account/csrf'), { useQuery<unknown, unknown, unknown>([ QueryKeys.csrf ], async() => await fetch('/node-api/account/csrf'), {
...@@ -30,7 +31,7 @@ const Page = ({ children, wrapChildren = true }: Props) => { ...@@ -30,7 +31,7 @@ const Page = ({ children, wrapChildren = true }: Props) => {
<Flex w="100%" minH="100vh" alignItems="stretch"> <Flex w="100%" minH="100vh" alignItems="stretch">
<NavigationDesktop/> <NavigationDesktop/>
<Flex flexDir="column" width="100%"> <Flex flexDir="column" width="100%">
<Header/> <Header hideOnScrollDown={ hideMobileHeaderOnScrollDown }/>
{ renderedChildren } { renderedChildren }
</Flex> </Flex>
</Flex> </Flex>
......
import { HStack, Box, Flex, useColorModeValue } from '@chakra-ui/react'; import { HStack, Box, Flex, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import useScrollDirection from 'lib/hooks/useScrollDirection';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo'; import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import ProfileMenuDesktop from 'ui/snippets/profileMenu/ProfileMenuDesktop'; import ProfileMenuDesktop from 'ui/snippets/profileMenu/ProfileMenuDesktop';
import ProfileMenuMobile from 'ui/snippets/profileMenu/ProfileMenuMobile'; import ProfileMenuMobile from 'ui/snippets/profileMenu/ProfileMenuMobile';
...@@ -9,8 +10,11 @@ import SearchBar from 'ui/snippets/searchBar/SearchBar'; ...@@ -9,8 +10,11 @@ import SearchBar from 'ui/snippets/searchBar/SearchBar';
import Burger from './Burger'; import Burger from './Burger';
import ColorModeToggler from './ColorModeToggler'; import ColorModeToggler from './ColorModeToggler';
const Header = () => { const Header = ({ hideOnScrollDown }: {hideOnScrollDown?: boolean}) => {
const scrollDirection = useScrollDirection();
const bgColor = useColorModeValue('white', 'black'); const bgColor = useColorModeValue('white', 'black');
const transform = hideOnScrollDown && scrollDirection === 'down' ? 'translateY(-100%)' : 'translateY(0)';
return ( return (
<> <>
<Box bgColor={ bgColor } display={{ base: 'block', lg: 'none' }}> <Box bgColor={ bgColor } display={{ base: 'block', lg: 'none' }}>
...@@ -26,6 +30,9 @@ const Header = () => { ...@@ -26,6 +30,9 @@ const Header = () => {
alignItems="center" alignItems="center"
justifyContent="space-between" justifyContent="space-between"
zIndex="sticky" zIndex="sticky"
transform={ transform }
transitionProperty="transform"
transitionDuration="slow"
> >
<Burger/> <Burger/>
<NetworkLogo/> <NetworkLogo/>
......
...@@ -3,7 +3,7 @@ import React from 'react'; ...@@ -3,7 +3,7 @@ import React from 'react';
import type { ChangeEvent, FormEvent } from 'react'; import type { ChangeEvent, FormEvent } from 'react';
import searchIcon from 'icons/search.svg'; import searchIcon from 'icons/search.svg';
import useScrollVisibility from 'lib/hooks/useScrollVisibility'; import useScrollDirection from 'lib/hooks/useScrollDirection';
interface Props { interface Props {
onChange: (event: ChangeEvent<HTMLInputElement>) => void; onChange: (event: ChangeEvent<HTMLInputElement>) => void;
...@@ -12,7 +12,7 @@ interface Props { ...@@ -12,7 +12,7 @@ interface Props {
const SearchBarMobile = ({ onChange, onSubmit }: Props) => { const SearchBarMobile = ({ onChange, onSubmit }: Props) => {
const isVisible = useScrollVisibility('up'); const isVisible = useScrollDirection() === 'up';
const searchIconColor = useColorModeValue('blackAlpha.600', 'whiteAlpha.600'); const searchIconColor = useColorModeValue('blackAlpha.600', 'whiteAlpha.600');
const inputBorderColor = useColorModeValue('blackAlpha.100', 'whiteAlpha.200'); const inputBorderColor = useColorModeValue('blackAlpha.100', 'whiteAlpha.200');
...@@ -30,9 +30,9 @@ const SearchBarMobile = ({ onChange, onSubmit }: Props) => { ...@@ -30,9 +30,9 @@ const SearchBarMobile = ({ onChange, onSubmit }: Props) => {
left="0" left="0"
zIndex="docked" zIndex="docked"
bgColor={ bgColor } bgColor={ bgColor }
transform={ isVisible ? 'translateY(0)' : 'translateY(-100%)' } transform={ isVisible ? 'translateY(0)' : 'translateY(-108px)' }
// transitionProperty="transform" transitionProperty="transform"
// transitionDuration="slow" transitionDuration="slow"
display={{ base: 'block', lg: 'none' }} display={{ base: 'block', lg: 'none' }}
w="100%" w="100%"
> >
......
import { HStack, Flex } from '@chakra-ui/react'; import { HStack, Flex, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { Sort } from 'types/client/txs-sort'; import type { Sort } from 'types/client/txs-sort';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
// import FilterInput from 'ui/shared/FilterInput'; // import FilterInput from 'ui/shared/FilterInput';
import useScrollVisibility from 'lib/hooks/useScrollVisibility'; import useScrollDirection from 'lib/hooks/useScrollDirection';
import Pagination from 'ui/shared/Pagination'; import Pagination from 'ui/shared/Pagination';
import type { Props as PaginationProps } from 'ui/shared/Pagination'; import type { Props as PaginationProps } from 'ui/shared/Pagination';
import SortButton from 'ui/shared/SortButton'; import SortButton from 'ui/shared/SortButton';
...@@ -18,21 +18,22 @@ type Props = { ...@@ -18,21 +18,22 @@ type Props = {
} }
const TxsHeader = ({ sorting, paginationProps }: Props) => { const TxsHeader = ({ sorting, paginationProps }: Props) => {
const isVisible = useScrollVisibility('down'); const scrollDirection = useScrollDirection();
const isMobile = useIsMobile(false); const isMobile = useIsMobile(false);
return ( return (
<Flex <Flex
backgroundColor="white" backgroundColor={ useColorModeValue('white', 'black') }
mt={ -6 } mt={ -6 }
pt={ 6 } pt={ 6 }
pb={ 6 } pb={ 6 }
justifyContent="space-between" justifyContent="space-between"
width="100%" width="100%"
position="sticky" position="sticky"
top={{ base: isVisible ? '56px' : '108px', lg: 0 }} top="108px"
// transitionDuration="slow" transform={ scrollDirection === 'up' ? 'translateY(0)' : 'translateY(-108px)' }
// transitionProperty="top" transitionProperty="transform"
transitionDuration="slow"
zIndex={{ base: 0, lg: 'docked' }} zIndex={{ base: 0, lg: 'docked' }}
> >
<HStack> <HStack>
......
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