Commit 1170ca50 authored by tom's avatar tom

Merge branch 'tabs' of github.com:blockscout/frontend into tx-mobile-view

parents d99da119 16ec3c3a
...@@ -7,6 +7,7 @@ const global = (props: StyleFunctionProps) => ({ ...@@ -7,6 +7,7 @@ const global = (props: StyleFunctionProps) => ({
body: { body: {
bg: mode('white', 'black')(props), bg: mode('white', 'black')(props),
...getDefaultTransitionProps(), ...getDefaultTransitionProps(),
'-webkit-tap-highlight-color': 'transparent',
}, },
form: { form: {
w: '100%', w: '100%',
......
...@@ -11,6 +11,7 @@ import React from 'react'; ...@@ -11,6 +11,7 @@ import React from 'react';
import type { RoutedTab } from './types'; import type { RoutedTab } from './types';
import useIsMobile from 'lib/hooks/useIsMobile';
import { link } from 'lib/link/link'; import { link } from 'lib/link/link';
import RoutedTabsMenu from './RoutedTabsMenu'; import RoutedTabsMenu from './RoutedTabsMenu';
...@@ -30,9 +31,10 @@ interface Props { ...@@ -30,9 +31,10 @@ interface Props {
const RoutedTabs = ({ tabs, defaultActiveTab }: Props) => { const RoutedTabs = ({ tabs, defaultActiveTab }: Props) => {
const defaultIndex = tabs.findIndex(({ routeName }) => routeName === defaultActiveTab); const defaultIndex = tabs.findIndex(({ routeName }) => routeName === defaultActiveTab);
const isMobile = useIsMobile();
const [ activeTab, setActiveTab ] = React.useState<number>(defaultIndex); const [ activeTab, setActiveTab ] = React.useState<number>(defaultIndex);
const { tabsCut, tabsWithMenu, tabsRefs, listRef } = useAdaptiveTabs(tabs); const { tabsCut, tabsList, tabsRefs, listRef } = useAdaptiveTabs(tabs, isMobile);
const router = useRouter(); const router = useRouter();
...@@ -49,8 +51,25 @@ const RoutedTabs = ({ tabs, defaultActiveTab }: Props) => { ...@@ -49,8 +51,25 @@ const RoutedTabs = ({ tabs, defaultActiveTab }: Props) => {
return ( return (
<Tabs variant="soft-rounded" colorScheme="blue" isLazy onChange={ handleTabChange } index={ activeTab }> <Tabs variant="soft-rounded" colorScheme="blue" isLazy onChange={ handleTabChange } index={ activeTab }>
<TabList marginBottom={{ base: 6, lg: 8 }} flexWrap="nowrap" whiteSpace="nowrap" ref={ listRef }> <TabList
{ tabsWithMenu.map((tab, index) => { marginBottom={{ base: 6, lg: 8 }}
flexWrap="nowrap"
whiteSpace="nowrap"
ref={ listRef }
overflowY="hidden"
overflowX={ isMobile ? 'auto' : undefined }
overscrollBehaviorX="contain"
css={{
'scroll-snap-type': 'x mandatory',
// hide scrollbar
'&::-webkit-scrollbar': { /* Chromiums */
display: 'none',
},
'-ms-overflow-style': 'none', /* IE and Edge */
'scrollbar-width': 'none', /* Firefox */
}}
>
{ tabsList.map((tab, index) => {
if (!tab.routeName) { if (!tab.routeName) {
return ( return (
<RoutedTabsMenu <RoutedTabsMenu
...@@ -77,6 +96,7 @@ const RoutedTabs = ({ tabs, defaultActiveTab }: Props) => { ...@@ -77,6 +96,7 @@ const RoutedTabs = ({ tabs, defaultActiveTab }: Props) => {
key={ tab.routeName } key={ tab.routeName }
ref={ tabsRefs[index] } ref={ tabsRefs[index] }
{ ...(index < tabsCut ? {} : hiddenItemStyles) } { ...(index < tabsCut ? {} : hiddenItemStyles) }
scrollSnapAlign="start"
> >
{ tab.title } { tab.title }
</Tab> </Tab>
...@@ -84,7 +104,7 @@ const RoutedTabs = ({ tabs, defaultActiveTab }: Props) => { ...@@ -84,7 +104,7 @@ const RoutedTabs = ({ tabs, defaultActiveTab }: Props) => {
}) } }) }
</TabList> </TabList>
<TabPanels> <TabPanels>
{ tabsWithMenu.map((tab) => <TabPanel padding={ 0 } key={ tab.routeName }>{ tab.component }</TabPanel>) } { tabsList.map((tab) => <TabPanel padding={ 0 } key={ tab.routeName }>{ tab.component }</TabPanel>) }
</TabPanels> </TabPanels>
</Tabs> </Tabs>
); );
......
...@@ -5,10 +5,10 @@ import type { RoutedTab } from './types'; ...@@ -5,10 +5,10 @@ import type { RoutedTab } from './types';
import { menuButton } from './utils'; import { menuButton } from './utils';
export default function useAdaptiveTabs(tabs: Array<RoutedTab>) { export default function useAdaptiveTabs(tabs: Array<RoutedTab>, disabled?: boolean) {
// to avoid flickering we set initial value to 0 // to avoid flickering we set initial value to 0
// so there will be no displayed tabs initially // so there will be no displayed tabs initially
const [ tabsCut, setTabsCut ] = React.useState(0); const [ tabsCut, setTabsCut ] = React.useState(disabled ? tabs.length : 0);
const [ tabsRefs, setTabsRefs ] = React.useState<Array<React.RefObject<HTMLButtonElement>>>([]); const [ tabsRefs, setTabsRefs ] = React.useState<Array<React.RefObject<HTMLButtonElement>>>([]);
const listRef = React.useRef<HTMLDivElement>(null); const listRef = React.useRef<HTMLDivElement>(null);
...@@ -40,12 +40,16 @@ export default function useAdaptiveTabs(tabs: Array<RoutedTab>) { ...@@ -40,12 +40,16 @@ export default function useAdaptiveTabs(tabs: Array<RoutedTab>) {
return visibleNum; return visibleNum;
}, [ tabs.length, tabsRefs ]); }, [ tabs.length, tabsRefs ]);
const tabsWithMenu = React.useMemo(() => { const tabsList = React.useMemo(() => {
if (disabled) {
return tabs;
}
return [ ...tabs, menuButton ]; return [ ...tabs, menuButton ];
}, [ tabs ]); }, [ tabs, disabled ]);
React.useEffect(() => { React.useEffect(() => {
setTabsRefs(tabsWithMenu.map((_, index) => tabsRefs[index] || React.createRef())); !disabled && setTabsRefs(tabsList.map((_, index) => tabsRefs[index] || React.createRef()));
// imitate componentDidMount // imitate componentDidMount
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
...@@ -75,9 +79,9 @@ export default function useAdaptiveTabs(tabs: Array<RoutedTab>) { ...@@ -75,9 +79,9 @@ export default function useAdaptiveTabs(tabs: Array<RoutedTab>) {
return React.useMemo(() => { return React.useMemo(() => {
return { return {
tabsCut, tabsCut,
tabsWithMenu, tabsList,
tabsRefs, tabsRefs,
listRef, listRef,
}; };
}, [ tabsWithMenu, tabsCut, tabsRefs, listRef ]); }, [ tabsList, tabsCut, tabsRefs, listRef ]);
} }
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