Commit ee3c848e authored by Max Alekseenko's avatar Max Alekseenko

move common logic to NavLinkBase

parent c43ea0d2
......@@ -122,8 +122,11 @@ const NavigationMobile = ({ onNavLinkClick, isMarketplaceAppPage }: Props) => {
>
{ item.map(subItem => <NavLink key={ subItem.text } item={ subItem } onClick={ onNavLinkClick } isCollapsed={ isCollapsed }/>) }
</Box>
) :
<NavLink key={ item.text } item={ item } mb={ 1 } onClick={ onNavLinkClick } isCollapsed={ isCollapsed }/>,
) : (
<Box key={ item.text } mb={ 1 }>
<NavLink item={ item } onClick={ onNavLinkClick } isCollapsed={ isCollapsed }/>
</Box>
),
) }
</Box>
</Box>
......
import { Link, Text, HStack, Tooltip, Box, useBreakpointValue, chakra, shouldForwardProp } from '@chakra-ui/react';
import NextLink from 'next/link';
import React from 'react';
import type { NavItem } from 'types/client/navigation';
import { route } from 'nextjs-routes';
import useIsMobile from 'lib/hooks/useIsMobile';
import { isInternalItem } from 'lib/hooks/useNavItems';
import IconSvg from 'ui/shared/IconSvg';
import LightningLabel, { LIGHTNING_LABEL_CLASS_NAME } from '../LightningLabel';
import NavLinkIcon from '../NavLinkIcon';
import useColors from '../useColors';
import useNavLinkStyleProps from '../useNavLinkStyleProps';
import { checkRouteHighlight } from '../utils';
import NavLinkBase from './NavLinkBase';
type Props = {
item: NavItem;
isCollapsed?: boolean;
px?: string | number;
className?: string;
onClick?: () => void;
disableActiveState?: boolean;
}
const NavLink = ({ item, isCollapsed, px, className, onClick, disableActiveState }: Props) => {
const isMobile = useIsMobile();
const colors = useColors();
const isExpanded = isCollapsed === false;
const NavLink = ({ item, isCollapsed, onClick }: Props) => {
const isInternalLink = isInternalItem(item);
const styleProps = useNavLinkStyleProps({ isCollapsed, isExpanded, isActive: isInternalLink && item.isActive && !disableActiveState });
const isXLScreen = useBreakpointValue({ base: false, xl: true });
const href = isInternalLink ? route(item.nextRoute) : item.url;
const isHighlighted = checkRouteHighlight(item);
const content = (
<Link
href={ href }
target={ isInternalLink ? '_self' : '_blank' }
{ ...styleProps.itemProps }
w={{ base: '100%', lg: isExpanded ? '100%' : '60px', xl: isCollapsed ? '60px' : '100%' }}
display="flex"
position="relative"
px={ px || { base: 2, lg: isExpanded ? 2 : '15px', xl: isCollapsed ? '15px' : 2 } }
aria-label={ `${ item.text } link` }
whiteSpace="nowrap"
onClick={ onClick }
_hover={{
[`& *:not(.${ LIGHTNING_LABEL_CLASS_NAME }, .${ LIGHTNING_LABEL_CLASS_NAME } *)`]: {
color: 'link_hovered',
},
}}
>
<Tooltip
label={ item.text }
hasArrow={ false }
isDisabled={ isMobile || isCollapsed === false || (isCollapsed === undefined && isXLScreen) }
placement="right"
variant="nav"
gutter={ 20 }
color={ isInternalLink && item.isActive ? colors.text.active : colors.text.hover }
margin={ 0 }
>
<HStack spacing={ 0 } overflow="hidden">
<NavLinkIcon item={ item }/>
<Text { ...styleProps.textProps } as="span" ml={ 3 }>
<span>{ item.text }</span>
{ !isInternalLink && <IconSvg name="link_external" boxSize={ 3 } color="icon_link_external" verticalAlign="middle"/> }
</Text>
{ isHighlighted && (
<LightningLabel iconColor={ styleProps.itemProps.bgColor } isCollapsed={ isCollapsed }/>
) }
</HStack>
</Tooltip>
</Link>
);
return (
<Box as="li" listStyleType="none" w="100%" className={ className }>
{ isInternalLink ? (
<NextLink href={ item.nextRoute } passHref legacyBehavior>
{ content }
</NextLink>
) : content }
</Box>
<NavLinkBase
item={ item }
nextRoute={ 'nextRoute' in item ? item.nextRoute : undefined }
onClick={ onClick }
target={ isInternalLink ? '_self' : '_blank' }
href={ isInternalLink ? route(item.nextRoute) : item.url }
isActive={ isInternalLink && item.isActive }
isExternal={ !isInternalLink }
isCollapsed={ isCollapsed }
/>
);
};
const NavLinkChakra = chakra(NavLink, {
shouldForwardProp: (prop) => {
const isChakraProp = !shouldForwardProp(prop);
if (isChakraProp && prop !== 'px') {
return false;
}
return true;
},
});
export default React.memo(NavLinkChakra);
export default React.memo(NavLink);
import { Link, Text, HStack, Tooltip, Box, useBreakpointValue } from '@chakra-ui/react';
import NextLink from 'next/link';
import React from 'react';
import type { NavItem, NavItemExternal, NavItemInternal } from 'types/client/navigation';
import useIsMobile from 'lib/hooks/useIsMobile';
import IconSvg from 'ui/shared/IconSvg';
import LightningLabel, { LIGHTNING_LABEL_CLASS_NAME } from '../LightningLabel';
import NavLinkIcon from '../NavLinkIcon';
import useColors from '../useColors';
import useNavLinkStyleProps from '../useNavLinkStyleProps';
import { checkRouteHighlight } from '../utils';
type Props = {
item: NavItem;
nextRoute?: NavItemInternal['nextRoute'];
isCollapsed?: boolean;
onClick?: () => void;
as?: 'a' | 'button';
target?: '_self' | '_blank';
href?: string;
isExternal?: boolean;
isActive?: boolean;
isDisabled?: boolean;
}
const NavLinkBase = ({ item, nextRoute, isCollapsed, onClick, isExternal, as = 'a', target = '_self', href, isActive, isDisabled }: Props) => {
const isMobile = useIsMobile();
const colors = useColors();
const isExpanded = isCollapsed === false;
const styleProps = useNavLinkStyleProps({ isCollapsed, isExpanded, isActive });
const isXLScreen = useBreakpointValue({ base: false, xl: true });
const isHighlighted = checkRouteHighlight(nextRoute ? { nextRoute } as NavItemInternal : {} as NavItemExternal);
const content = (
<Link
as={ as }
href={ href }
target={ target }
{ ...styleProps.itemProps }
w={{ base: '100%', lg: isExpanded ? '100%' : '60px', xl: isCollapsed ? '60px' : '100%' }}
display="flex"
position="relative"
px={{ base: 2, lg: isExpanded ? 2 : '15px', xl: isCollapsed ? '15px' : 2 }}
aria-label={ `${ item.text } link` }
whiteSpace="nowrap"
onClick={ onClick }
_hover={{
[`& *:not(.${ LIGHTNING_LABEL_CLASS_NAME }, .${ LIGHTNING_LABEL_CLASS_NAME } *)`]: {
color: isDisabled ? 'inherit' : 'link_hovered',
},
}}
>
<Tooltip
label={ item.text }
hasArrow={ false }
isDisabled={ isMobile || isCollapsed === false || (isCollapsed === undefined && isXLScreen) }
placement="right"
variant="nav"
gutter={ 20 }
color={ isActive ? colors.text.active : colors.text.hover }
margin={ 0 }
>
<HStack spacing={ 0 } overflow="hidden">
<NavLinkIcon item={ item }/>
<Text { ...styleProps.textProps } as="span" ml={ 3 }>
<span>{ item.text }</span>
{ isExternal && <IconSvg name="link_external" boxSize={ 3 } color="icon_link_external" verticalAlign="middle"/> }
</Text>
{ isHighlighted && (
<LightningLabel iconColor={ styleProps.itemProps.bgColor } isCollapsed={ isCollapsed }/>
) }
</HStack>
</Tooltip>
</Link>
);
return (
<Box as="li" listStyleType="none" w="100%">
{ nextRoute ? (
<NextLink href={ nextRoute } passHref legacyBehavior>
{ content }
</NextLink>
) : content }
</Box>
);
};
export default React.memo(NavLinkBase);
import { Link, Text, HStack, Tooltip, Box, useBreakpointValue } from '@chakra-ui/react';
import NextLink from 'next/link';
import { useRouter } from 'next/router';
import React, { useCallback } from 'react';
......@@ -10,12 +8,8 @@ import type { Route } from 'nextjs-routes';
import config from 'configs/app';
import { useRewardsContext } from 'lib/contexts/rewards';
import useIsMobile from 'lib/hooks/useIsMobile';
import LightningLabel, { LIGHTNING_LABEL_CLASS_NAME } from 'ui/snippets/navigation/LightningLabel';
import NavLinkIcon from 'ui/snippets/navigation/NavLinkIcon';
import useColors from 'ui/snippets/navigation/useColors';
import useNavLinkStyleProps from 'ui/snippets/navigation/useNavLinkStyleProps';
import { checkRouteHighlight } from 'ui/snippets/navigation/utils';
import NavLinkBase from './NavLinkBase';
type Props = {
isCollapsed?: boolean;
......@@ -23,19 +17,13 @@ type Props = {
}
const RewardsNavLink = ({ isCollapsed, onClick }: Props) => {
const isMobile = useIsMobile();
const colors = useColors();
const router = useRouter();
const { openLoginModal, dailyRewardQuery, apiToken, isInitialized } = useRewardsContext();
const pathname = '/account/rewards';
const nextRoute = { pathname } as Route;
const isActive = router.pathname === pathname;
const isExpanded = isCollapsed === false;
const styleProps = useNavLinkStyleProps({ isCollapsed, isExpanded, isActive });
const isXLScreen = useBreakpointValue({ base: false, xl: true });
const isHighlighted = checkRouteHighlight({ nextRoute } as NavItem);
const isLogedIn = isInitialized && apiToken;
const handleClick = useCallback(() => {
if (isInitialized && !apiToken) {
......@@ -48,55 +36,21 @@ const RewardsNavLink = ({ isCollapsed, onClick }: Props) => {
return null;
}
const content = (
<Link
href={ isInitialized && apiToken ? route(nextRoute) : undefined }
as={ isInitialized && apiToken ? 'a' : 'button' }
onClick={ handleClick }
{ ...styleProps.itemProps }
w={{ base: '100%', lg: isExpanded ? '100%' : '60px', xl: isCollapsed ? '60px' : '100%' }}
display="flex"
position="relative"
px={{ base: 2, lg: isExpanded ? 2 : '15px', xl: isCollapsed ? '15px' : 2 }}
aria-label="Merits link"
whiteSpace="nowrap"
_hover={{
[`& *:not(.${ LIGHTNING_LABEL_CLASS_NAME }, .${ LIGHTNING_LABEL_CLASS_NAME } *)`]: {
color: isInitialized ? 'link_hovered' : 'inherit',
},
}}
>
<Tooltip
label="Merits"
hasArrow={ false }
isDisabled={ isMobile || isCollapsed === false || (isCollapsed === undefined && isXLScreen) }
placement="right"
variant="nav"
gutter={ 20 }
color={ isActive ? colors.text.active : colors.text.hover }
margin={ 0 }
>
<HStack spacing={ 0 } overflow="hidden">
<NavLinkIcon item={{ icon: dailyRewardQuery.data?.available ? 'merits_with_dot' : 'merits' } as NavItem}/>
<Text { ...styleProps.textProps } as="span" ml={ 3 }>
Merits
</Text>
{ isHighlighted && (
<LightningLabel iconColor={ styleProps.itemProps.bgColor } isCollapsed={ isCollapsed }/>
) }
</HStack>
</Tooltip>
</Link>
);
return (
<Box as="li" listStyleType="none" w="100%">
{ isInitialized && apiToken ? (
<NextLink href={ nextRoute } passHref legacyBehavior>
{ content }
</NextLink>
) : content }
</Box>
<NavLinkBase
item={{
text: 'Merits',
icon: dailyRewardQuery.data?.available ? 'merits_with_dot' : 'merits',
} as NavItem}
nextRoute={ isLogedIn ? nextRoute : undefined }
onClick={ handleClick }
as={ isLogedIn ? 'a' : 'button' }
target="_self"
href={ isLogedIn ? route(nextRoute) : undefined }
isActive={ router.pathname === pathname }
isDisabled={ !isInitialized }
isCollapsed={ isCollapsed }
/>
);
};
......
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