Commit 1a268894 authored by Max Alekseenko's avatar Max Alekseenko

rebuild dropdown

parent c1de6710
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.339 1.271a4.518 4.518 0 0 1 7.66 3.214 4.524 4.524 0 0 1-1.269 3.18l-.012.013-2.111 2.114a4.402 4.402 0 0 1-.115.11c.325-.488.508-1.112.508-1.9 0-.473-.065-.886-.188-1.246l.485-.485a2.524 2.524 0 0 0-1.796-4.27 2.518 2.518 0 0 0-1.767.704L8.528 3.904a1 1 0 1 1-1.41-1.418l1.21-1.205.01-.01Zm-4.825 4.82a4.524 4.524 0 0 0-.122.117L1.281 8.322l-.013.012a4.524 4.524 0 0 0 3.212 7.664 4.518 4.518 0 0 0 3.18-1.27l.012-.011 1.204-1.205a1 1 0 0 0-1.415-1.414l-1.197 1.198A2.518 2.518 0 0 1 2 11.498a2.524 2.524 0 0 1 .702-1.77l.485-.484A3.859 3.859 0 0 1 3 8c0-.793.185-1.42.514-1.91Z" fill="currentColor" fill-opacity=".8"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M8.339 1.271a4.518 4.518 0 0 1 7.66 3.214 4.524 4.524 0 0 1-1.269 3.18l-.012.013-2.111 2.114a4.402 4.402 0 0 1-.115.11c.325-.488.508-1.112.508-1.9 0-.473-.065-.886-.188-1.246l.485-.485a2.524 2.524 0 0 0-1.796-4.27 2.518 2.518 0 0 0-1.767.704L8.528 3.904a1 1 0 1 1-1.41-1.418l1.21-1.205.01-.01Zm-4.825 4.82a4.524 4.524 0 0 0-.122.117L1.281 8.322l-.013.012a4.524 4.524 0 0 0 3.212 7.664 4.518 4.518 0 0 0 3.18-1.27l.012-.011 1.204-1.205a1 1 0 0 0-1.415-1.414l-1.197 1.198A2.518 2.518 0 0 1 2 11.498a2.524 2.524 0 0 1 .702-1.77l.485-.484A3.859 3.859 0 0 1 3 8c0-.793.185-1.42.514-1.91Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.45 10.064V9.051h2.474c.06 0 .116-.026.159-.074a.27.27 0 0 0 .065-.179.27.27 0 0 0-.065-.179.213.213 0 0 0-.16-.074H7.125c-.298 0-.584-.133-.795-.37C6.12 7.936 6 7.614 6 7.278c0-.336.118-.658.33-.895.21-.238.496-.371.794-.371h.45V5h.9v1.013h1.124v1.013H7.124a.213.213 0 0 0-.159.074.27.27 0 0 0-.065.179.27.27 0 0 0 .065.179c.043.047.1.074.16.074h1.799c.298 0 .584.133.795.37.21.238.329.56.329.896 0 .336-.119.658-.33.895-.21.238-.496.371-.794.371h-.45v1.013h-.9v-1.013H6.45Z" fill="currentColor" fill-opacity=".8"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M6.45 10.064V9.051h2.474c.06 0 .116-.026.159-.074a.27.27 0 0 0 .065-.179.27.27 0 0 0-.065-.179.213.213 0 0 0-.16-.074H7.125c-.298 0-.584-.133-.795-.37A1.364 1.364 0 0 1 6 7.278c0-.336.118-.658.33-.895a1.06 1.06 0 0 1 .794-.371h.45V5h.9v1.013h1.124v1.013H7.124a.213.213 0 0 0-.159.074.27.27 0 0 0-.065.179.27.27 0 0 0 .065.179c.043.047.1.074.16.074h1.799c.298 0 .584.133.795.37.21.238.329.56.329.896 0 .336-.119.658-.33.895a1.06 1.06 0 0 1-.794.371h-.45v1.013h-.9v-1.013H6.45Z" fill="currentColor"/>
</svg> </svg>
import { Button, Box, Menu, MenuButton, MenuList, MenuItem, Flex } from '@chakra-ui/react'; import { Button, Box, Flex, Popover, PopoverTrigger, PopoverContent, PopoverBody, useDisclosure } from '@chakra-ui/react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { Route } from 'nextjs-routes';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
...@@ -10,15 +11,14 @@ import getPageType from 'lib/mixpanel/getPageType'; ...@@ -10,15 +11,14 @@ import getPageType from 'lib/mixpanel/getPageType';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
import DeFiDropdownItem from './DeFiDropdownItem';
const feature = config.features.deFi; const feature = config.features.deFi;
function getHrefAndTarget(feature: { url: string } | { dappId: string }) { function getUrl(feature: { url: string } | { dappId: string }): { url?: string; nextRoute?: Route } {
return 'url' in feature ? { return {
href: feature.url, url: 'url' in feature ? feature.url : undefined,
target: '_blank', nextRoute: 'dappId' in feature ? { pathname: '/apps/[id]', query: { id: feature.dappId, action: 'connect' } } : undefined,
} : {
href: route({ pathname: '/apps/[id]', query: { id: feature.dappId, action: 'connect' } }),
target: '_self',
}; };
} }
...@@ -26,6 +26,7 @@ const DeFiDropdown = () => { ...@@ -26,6 +26,7 @@ const DeFiDropdown = () => {
const router = useRouter(); const router = useRouter();
const source = getPageType(router.pathname); const source = getPageType(router.pathname);
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const { isOpen, onToggle, onClose } = useDisclosure();
const handleClick = React.useCallback((content: 'Swap button' | 'Payment link') => { const handleClick = React.useCallback((content: 'Swap button' | 'Payment link') => {
mixpanel.logEvent(mixpanel.EventTypes.BUTTON_CLICK, { Content: content, Source: source }); mixpanel.logEvent(mixpanel.EventTypes.BUTTON_CLICK, { Content: content, Source: source });
...@@ -39,24 +40,20 @@ const DeFiDropdown = () => { ...@@ -39,24 +40,20 @@ const DeFiDropdown = () => {
const items = []; const items = [];
if (feature.swapButton) { if (feature.swapButton) {
const { href, target } = getHrefAndTarget(feature.swapButton);
items.push({ items.push({
icon: 'swap' as const, icon: 'swap' as const,
text: 'Swap', text: 'Swap',
href,
target,
onClick: () => handleClick('Swap button'), onClick: () => handleClick('Swap button'),
...getUrl(feature.swapButton),
}); });
} }
if (feature.paymentLink) { if (feature.paymentLink) {
const { href, target } = getHrefAndTarget(feature.paymentLink);
items.push({ items.push({
icon: 'payment_link' as const, icon: 'payment_link' as const,
text: 'Payment link', text: 'Payment link',
href,
target,
onClick: () => handleClick('Payment link'), onClick: () => handleClick('Payment link'),
...getUrl(feature.paymentLink),
}); });
} }
...@@ -77,37 +74,33 @@ const DeFiDropdown = () => { ...@@ -77,37 +74,33 @@ const DeFiDropdown = () => {
}; };
return items.length > 1 ? ( return items.length > 1 ? (
<Menu> <Popover isOpen={ isOpen } onClose={ onClose } placement="bottom-start" isLazy>
<MenuButton as={ Button } { ...buttonStyles }> <PopoverTrigger>
<Flex alignItems="center"> <Button
onClick={ onToggle }
{ ...buttonStyles }
bgColor={ isOpen ? 'blue.400' : undefined }
_active={{ bgColor: 'blue.400' }}
>
{ !isMobile && 'Blockscout' } DeFi { !isMobile && 'Blockscout' } DeFi
<IconSvg name="arrows/south-mini" boxSize={ 4 } ml={ 1 }/> <IconSvg name="arrows/south-mini" boxSize={ 4 } ml={ 1 }/>
</Flex> </Button>
</MenuButton> </PopoverTrigger>
<MenuList minWidth="160px" zIndex="popover" overflow="hidden" py={ 4 }> <PopoverContent w="auto">
{ items.map((item, index) => ( <PopoverBody >
<MenuItem <Flex flexDirection="column" gap={ 1 }>
key={ index } { items.map((item, index) => (
as="a" <DeFiDropdownItem key={ index } item={ item }/>
href={ item.href } )) }
target={ item.target } </Flex>
onClick={ item.onClick } </PopoverBody>
height="48px" </PopoverContent>
px={ 4 } </Popover>
fontSize="sm"
fontWeight="500"
>
<IconSvg name={ item.icon } boxSize={ 5 } mr={ 3 }/>
<span>{ item.text }</span>
</MenuItem>
)) }
</MenuList>
</Menu>
) : ( ) : (
<Button <Button
as="a" as="a"
href={ items[0].href } href={ items[0].nextRoute ? route(items[0].nextRoute) : items[0].url }
target={ items[0].target } target={ items[0].nextRoute ? '_self' : '_blank' }
onClick={ items[0].onClick } onClick={ items[0].onClick }
{ ...buttonStyles } { ...buttonStyles }
> >
......
import { Link, Text, HStack, chakra, shouldForwardProp, useColorModeValue } from '@chakra-ui/react';
import NextLink from 'next/link';
import React from 'react';
import type { Route } from 'nextjs-routes';
import { route } from 'nextjs-routes';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
type Props = {
item: {
icon: IconName;
text: string;
nextRoute?: Route;
url?: string;
onClick: () => void;
};
}
const DeFiDropdownItem = ({ item }: Props) => {
const href = item.nextRoute ? route(item.nextRoute) : item.url;
const content = (
<Link
href={ href }
target={ item.nextRoute ? '_self' : '_blank' }
w="100%"
h="34px"
display="flex"
aria-label={ `${ item.text } link` }
whiteSpace="nowrap"
color={ useColorModeValue('blackAlpha.800', 'gray.400') }
onClick={ item.onClick }
_hover={{
'& *': {
color: 'link_hovered',
},
}}
>
<HStack spacing={ 2 } overflow="hidden">
<IconSvg name={ item.icon } boxSize={ 5 }/>
<Text as="span" fontSize="sm">
<span>{ item.text }</span>
{ !item.nextRoute && <IconSvg name="arrows/north-east" boxSize={ 4 } color="text_secondary" verticalAlign="middle"/> }
</Text>
</HStack>
</Link>
);
return item.nextRoute ? (
<NextLink href={ item.nextRoute } passHref legacyBehavior>
{ content }
</NextLink>
) : content;
};
const DeFiDropdownItemChakra = chakra(DeFiDropdownItem, {
shouldForwardProp: (prop) => {
const isChakraProp = !shouldForwardProp(prop);
if (isChakraProp && prop !== 'px') {
return false;
}
return true;
},
});
export default React.memo(DeFiDropdownItemChakra);
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