diff --git a/apps/aptos/components/Menu/footerConfig.ts b/apps/aptos/components/Menu/footerConfig.ts index f487b07a33c72..fe3500f22e016 100644 --- a/apps/aptos/components/Menu/footerConfig.ts +++ b/apps/aptos/components/Menu/footerConfig.ts @@ -18,16 +18,12 @@ export const footerLinks: (t: ContextApi['t']) => FooterLinkType[] = (t) => [ href: 'https://pancakeswap.games/', }, { - label: t('NFT'), - href: 'https://pancakeswap.finance/nfts', + label: t('Play'), + href: 'https://pancakeswap.finance/prediction', }, { - label: t('Tokenomics'), - href: 'https://docs.pancakeswap.finance/governance-and-tokenomics/cake-tokenomics', - }, - { - label: t('CAKE Emission Projection'), - href: 'https://analytics.pancakeswap.finance/', + label: t('veCAKE'), + href: 'https://pancakeswap.finance/cake-staking', }, { label: t('Merchandise'), @@ -39,16 +35,20 @@ export const footerLinks: (t: ContextApi['t']) => FooterLinkType[] = (t) => [ label: 'Business', items: [ { - label: t('Farms and Syrup Pools'), + label: t('CAKE Incentives'), href: 'https://docs.pancakeswap.finance/ecosystem-and-partnerships/business-partnerships/syrup-pools-and-farms', }, { - label: t('IFO'), + label: t('Staking Pools'), + href: 'https://pancakeswap.finance/pools', + }, + { + label: t('Token Launches'), href: 'https://docs.pancakeswap.finance/ecosystem-and-partnerships/business-partnerships/initial-farm-offerings-ifos', }, { - label: t('NFT Marketplace'), - href: 'https://docs.pancakeswap.finance/ecosystem-and-partnerships/business-partnerships/nft-market-applications', + label: t('Brand Assets'), + href: 'https://docs.pancakeswap.finance/ecosystem-and-partnerships/brand', }, ], }, @@ -68,7 +68,7 @@ export const footerLinks: (t: ContextApi['t']) => FooterLinkType[] = (t) => [ href: 'https://docs.pancakeswap.finance/developers/bug-bounty', }, { - label: t('v4'), + label: t('V4'), href: 'https://pancakeswap.finance/v4', }, ], @@ -77,7 +77,7 @@ export const footerLinks: (t: ContextApi['t']) => FooterLinkType[] = (t) => [ label: t('Support'), items: [ { - label: t('Contact'), + label: t('Get Help'), href: 'https://docs.pancakeswap.finance/contact-us/customer-support', }, { @@ -88,27 +88,39 @@ export const footerLinks: (t: ContextApi['t']) => FooterLinkType[] = (t) => [ label: t('Documentation'), href: 'https://docs.pancakeswap.finance/', }, + { + label: t('Audits'), + href: 'https://docs.pancakeswap.finance/readme/audits', + }, + { + label: t('Legacy products'), + href: 'https://docs.pancakeswap.finance/products/legacy-products', + }, ], }, { label: t('About'), items: [ { - label: t('Terms Of Service'), - href: 'https://pancakeswap.finance/terms-of-service', + label: t('Tokenomics'), + href: 'https://docs.pancakeswap.finance/governance-and-tokenomics/cake-tokenomics', }, { - label: t('Blog'), - href: 'https://blog.pancakeswap.finance/', + label: t('CAKE Emission Projection'), + href: 'https://analytics.pancakeswap.finance/', }, { - label: t('Brand Assets'), - href: 'https://docs.pancakeswap.finance/ecosystem-and-partnerships/brand', + label: t('Blog'), + href: 'https://blog.pancakeswap.finance/', }, { label: t('Careers'), href: 'https://docs.pancakeswap.finance/team/become-a-chef', }, + { + label: t('Terms Of Service'), + href: 'https://pancakeswap.finance/terms-of-service', + }, ], }, ] diff --git a/apps/web/src/__tests__/utils/utils.test.ts b/apps/web/src/__tests__/utils/utils.test.ts index ee73423448be8..1d5611a78189d 100644 --- a/apps/web/src/__tests__/utils/utils.test.ts +++ b/apps/web/src/__tests__/utils/utils.test.ts @@ -17,13 +17,13 @@ describe('getActiveMenuItem', () => { it('should return an active item if pathname found in subitems', () => { // Given - const pathname = '/pools' + const pathname = '/liquidity/pools' // When const result = getActiveMenuItem({ pathname, menuConfig: menuConfig(mockT, false, undefined) }) // Then - expect(result).toEqual(menuConfig(mockT, false, undefined)[2]) + expect(result).toEqual(menuConfig(mockT, false, undefined)[1]) }) it('should not return an item that only includes pathname but not starts with', () => { @@ -34,7 +34,7 @@ describe('getActiveMenuItem', () => { const result = getActiveMenuItem({ pathname, menuConfig: menuConfig(mockT, false, undefined) }) // Then - expect(result).toEqual(menuConfig(mockT, false, undefined)[6]) + expect(result).toEqual(menuConfig(mockT, false, undefined)[4]) }) it('should return undefined if item is not found', () => { @@ -63,24 +63,13 @@ describe('getActiveSubMenuItem', () => { it('should return an active sub item', () => { // Given - const pathname = '/pools' + const pathname = '/liquidity/pools' // When const result = getActiveSubMenuItem({ pathname, menuItem: menuConfig(mockT, false, undefined)[1] }) // Then - expect(result).toEqual(menuConfig(mockT, false, undefined)[1].items?.[2]) - }) - - it('should return the item with the longest href when multiple items are found', () => { - // Given - const pathname = '/nfts/collections/0xDf7952B35f24aCF7fC0487D01c8d5690a60DBa07' - - // When - const result = getActiveSubMenuItem({ pathname, menuItem: menuConfig(mockT, false, undefined)[4] }) - - // Then - expect(result).toEqual(menuConfig(mockT, false, undefined)[4].items?.[1]) + expect(result).toEqual(menuConfig(mockT, false, undefined)[1].items?.[0]) }) it('should return undefined if item is not found', () => { @@ -94,16 +83,5 @@ describe('getActiveSubMenuItem', () => { expect(result).toEqual(undefined) }) - it('should return the item with the longest href when multiple items are found', () => { - // Given - const pathname = '/nfts/collections/0xDf7952B35f24aCF7fC0487D01c8d5690a60DBa07' - - // When - const result = getActiveSubMenuItem({ pathname, menuItem: menuConfig(mockT, false, undefined)[4] }) - - // Then - expect(result).toEqual(menuConfig(mockT, false, undefined)[4].items?.[1]) - }) - it.todo('should return items with supportChainId') }) diff --git a/apps/web/src/components/Menu/config/config.ts b/apps/web/src/components/Menu/config/config.ts index 2e105fd825cac..432371d4adef7 100644 --- a/apps/web/src/components/Menu/config/config.ts +++ b/apps/web/src/components/Menu/config/config.ts @@ -3,37 +3,27 @@ import { SUPPORTED_CHAIN_IDS as POOL_SUPPORTED_CHAINS } from '@pancakeswap/pools import { SUPPORTED_CHAIN_IDS as POSITION_MANAGERS_SUPPORTED_CHAINS } from '@pancakeswap/position-managers' import { SUPPORTED_CHAIN_IDS as PREDICTION_SUPPORTED_CHAINS } from '@pancakeswap/prediction' import { + BridgeIcon, DropdownMenuItems, DropdownMenuItemType, EarnFillIcon, EarnIcon, + GameIcon, MenuItemsType, MoreIcon, - NftFillIcon, - NftIcon, - PancakeProtectorIcon, - ShoppingBasketFilledIcon, - ShoppingBasketIcon, SwapFillIcon, SwapIcon, } from '@pancakeswap/uikit' -import { - FIXED_STAKING_SUPPORTED_CHAINS, - LIQUID_STAKING_SUPPORTED_CHAINS, - SUPPORT_CAKE_STAKING, - SUPPORT_FARMS, - SUPPORT_ONLY_BSC, -} from 'config/constants/supportChains' +import { SUPPORT_CAKE_STAKING, SUPPORT_FARMS, SUPPORT_ONLY_BSC } from 'config/constants/supportChains' import { getOptionsUrl } from 'utils/getOptionsUrl' import { getPerpetualUrl } from 'utils/getPerpetualUrl' -import { nftsBaseUrl } from 'views/Nft/market/constants' export type ConfigMenuDropDownItemsType = DropdownMenuItems & { hideSubNav?: boolean } export type ConfigMenuItemsType = Omit & { hideSubNav?: boolean; image?: string } & { items?: ConfigMenuDropDownItemsType[] } -const addMenuItemSupported = (item, chainId) => { +export const addMenuItemSupported = (item, chainId) => { if (!chainId || !item.supportChainIds) { return item } @@ -65,11 +55,7 @@ const config: ( href: '/swap', }, { - label: t('Liquidity'), - href: '/liquidity/positions', - }, - { - label: t('Perpetual'), + label: t('Perps'), href: getPerpetualUrl({ chainId, languageCode, @@ -85,31 +71,11 @@ const config: ( type: DropdownMenuItemType.EXTERNAL_LINK, }, { - label: t('Bridge'), - href: 'https://bridge.pancakeswap.finance/', - type: DropdownMenuItemType.EXTERNAL_LINK, - }, - { - label: `${t('Limit')} (Deprecated)`, - href: '/limit-orders', - supportChainIds: SUPPORT_ONLY_BSC, - image: '/images/decorations/3d-coin.png', - }, - { - label: t('Trading Reward'), - href: '/trading-reward', - hideSubNav: true, + label: t('Buy Crypto'), + href: '/buy-crypto', }, ].map((item) => addMenuItemSupported(item, chainId)), }, - { - label: t('Buy'), - href: '/buy-crypto', - icon: ShoppingBasketIcon, - fillIcon: ShoppingBasketFilledIcon, - showItemsOnMobile: false, - items: [], - }, { label: t('Earn'), href: '/liquidity/pools', @@ -117,6 +83,7 @@ const config: ( fillIcon: EarnFillIcon, image: '/images/decorations/pe2.png', supportChainIds: SUPPORT_FARMS, + hideSubNav: true, items: [ { label: t('Farms'), @@ -124,43 +91,68 @@ const config: ( supportChainIds: SUPPORT_FARMS, }, { - label: t('CAKE Staking'), - href: '/cake-staking', + label: t('Position Manager'), + href: '/position-managers', + supportChainIds: POSITION_MANAGERS_SUPPORTED_CHAINS, + }, + { + label: t('Staking'), supportChainIds: SUPPORT_CAKE_STAKING, + items: [ + { + label: t('CAKE Staking'), + href: '/cake-staking', + supportChainIds: SUPPORT_CAKE_STAKING, + }, + { + label: t('Syrup Pools'), + href: '/pools', + supportChainIds: POOL_SUPPORTED_CHAINS, + }, + ].map((item) => addMenuItemSupported(item, chainId)), }, + ].map((item) => addMenuItemSupported(item, chainId)), + }, + { + label: t('Bridge'), + href: 'https://bridge.pancakeswap.finance', + icon: BridgeIcon, + type: DropdownMenuItemType.EXTERNAL_LINK, + image: '/images/decorations/pe2.png', + items: [ { - label: t('Syrup Pools'), - href: '/pools', - supportChainIds: POOL_SUPPORTED_CHAINS, + label: t('Stargate'), + href: 'https://bridge.pancakeswap.finance/stargate', + type: DropdownMenuItemType.EXTERNAL_LINK, }, { - label: t('Position Manager'), - href: '/position-managers', - supportChainIds: POSITION_MANAGERS_SUPPORTED_CHAINS, + label: t('Axelar'), + href: 'https://bridge.pancakeswap.finance/axelar', + type: DropdownMenuItemType.EXTERNAL_LINK, + }, + { + label: t('Celer'), + href: 'https://cbridge.celer.network/1/12360001/', + type: DropdownMenuItemType.EXTERNAL_LINK, }, { - label: t('Liquid Staking'), - href: '/liquid-staking', - supportChainIds: LIQUID_STAKING_SUPPORTED_CHAINS, + label: t('Wormhole'), + href: 'https://bridge.pancakeswap.finance/wormhole', + type: DropdownMenuItemType.EXTERNAL_LINK, }, { - label: t('Simple Staking'), - href: '/simple-staking', - supportChainIds: FIXED_STAKING_SUPPORTED_CHAINS, + label: t('Aptos'), + href: 'https://docs.pancakeswap.finance/readme/get-started-aptos/aptos-coin-guide', + type: DropdownMenuItemType.EXTERNAL_LINK, }, ].map((item) => addMenuItemSupported(item, chainId)), }, { - label: t('Game'), - icon: PancakeProtectorIcon, + label: t('Play'), + icon: GameIcon, hideSubNav: true, - href: 'https://pancakeswap.games/', + href: '/prediction', items: [ - { - label: t('Gaming Marketplace'), - href: 'https://pancakeswap.games/', - type: DropdownMenuItemType.EXTERNAL_LINK, - }, { label: t('Prediction (BETA)'), href: '/prediction', @@ -178,41 +170,8 @@ const config: ( status: { text: t('New'), color: 'success' }, type: DropdownMenuItemType.EXTERNAL_LINK, }, - { - label: t('Pottery (BETA)'), - href: '/pottery', - image: '/images/decorations/lottery.png', - }, ].map((item) => addMenuItemSupported(item, chainId)), }, - { - label: t('NFT'), - href: `${nftsBaseUrl}`, - icon: NftIcon, - fillIcon: NftFillIcon, - supportChainIds: SUPPORT_ONLY_BSC, - image: '/images/decorations/nft.png', - items: [ - { - label: t('Overview'), - href: `${nftsBaseUrl}`, - }, - { - label: t('Collections'), - href: `${nftsBaseUrl}/collections`, - }, - { - label: t('Activity'), - href: `${nftsBaseUrl}/activity`, - }, - ], - }, - { - label: t('v4'), - href: '/v4', - showOnMobile: false, - items: [], - }, { label: '', href: '/info', @@ -228,24 +187,21 @@ const config: ( href: '/ifo', image: '/images/ifos/ifo-bunny.png', }, - { - label: t('Affiliate Program'), - href: '/affiliates-program', - }, { label: t('Voting'), - href: '/voting', - supportChainIds: SUPPORT_ONLY_BSC, image: '/images/voting/voting-bunny.png', - }, - { - type: DropdownMenuItemType.DIVIDER, - }, - { - label: t('Leaderboard'), - href: '/teams', - supportChainIds: SUPPORT_ONLY_BSC, - image: '/images/decorations/leaderboard.png', + items: [ + { + label: t('Proposals'), + href: '/voting', + supportChainIds: SUPPORT_ONLY_BSC, + }, + { + label: t('Gauges'), + href: '/gauges-voting', + supportChainIds: SUPPORT_CAKE_STAKING, + }, + ].map((item) => addMenuItemSupported(item, chainId)), }, { type: DropdownMenuItemType.DIVIDER, diff --git a/apps/web/src/components/Menu/hooks/useMenuItems.ts b/apps/web/src/components/Menu/hooks/useMenuItems.ts index 4174ece1bad22..b11bb423cba5c 100644 --- a/apps/web/src/components/Menu/hooks/useMenuItems.ts +++ b/apps/web/src/components/Menu/hooks/useMenuItems.ts @@ -22,13 +22,14 @@ export const useMenuItems = ({ onClick }: UseMenuItemsParams = {}): ConfigMenuIt const { chainId } = useActiveChainId() const { isDark } = useTheme() const menuItemsStatus = useMenuItemsStatus() - const { isMobile } = useMatchBreakpoints() + const { isDesktop } = useMatchBreakpoints() const menuItems = useMemo(() => { const mobileConfig = [...config(t, isDark, languageCode, chainId)] - mobileConfig.push(mobileConfig.splice(3, 1)[0]) - return isMobile ? mobileConfig : config(t, isDark, languageCode, chainId) - }, [t, isDark, languageCode, chainId, isMobile]) + mobileConfig.splice(3, 0, mobileConfig.splice(2, 1)[0]) + + return isDesktop ? config(t, isDark, languageCode, chainId) : mobileConfig + }, [t, isDark, languageCode, chainId, isDesktop]) return useMemo(() => { if (menuItemsStatus && Object.keys(menuItemsStatus).length) { diff --git a/apps/web/src/components/Menu/index.tsx b/apps/web/src/components/Menu/index.tsx index 0dd69a6816157..ae2191dbaa020 100644 --- a/apps/web/src/components/Menu/index.tsx +++ b/apps/web/src/components/Menu/index.tsx @@ -19,7 +19,7 @@ import GlobalSettings from './GlobalSettings' import { SettingsMode } from './GlobalSettings/types' import UserMenu from './UserMenu' import { UseMenuItemsParams, useMenuItems } from './hooks/useMenuItems' -import { getActiveMenuItem, getActiveSubMenuItem } from './utils' +import { getActiveMenuItem, getActiveSubMenuChildItem, getActiveSubMenuItem } from './utils' const Notifications = lazy(() => import('views/Notifications')) @@ -87,6 +87,7 @@ const Menu = (props) => { const activeMenuItem = getActiveMenuItem({ menuConfig: menuItems, pathname }) const activeSubMenuItem = getActiveSubMenuItem({ menuItem: activeMenuItem, pathname }) + const activeSubChildMenuItem = getActiveSubMenuChildItem({ menuItem: activeMenuItem, pathname }) const toggleTheme = useMemo(() => { return () => setTheme(isDark ? 'light' : 'dark') @@ -125,6 +126,7 @@ const Menu = (props) => { footerLinks={getFooterLinks} activeItem={activeMenuItem?.href} activeSubItem={activeSubMenuItem?.href} + activeSubItemChildItem={activeSubChildMenuItem?.href} buyCakeLabel={t('Buy CAKE')} buyCakeLink="https://pancakeswap.finance/swap?outputCurrency=0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82&chainId=56" {...props} diff --git a/apps/web/src/components/Menu/utils.ts b/apps/web/src/components/Menu/utils.ts index 257276c4e3e1a..65d2096d60ed2 100644 --- a/apps/web/src/components/Menu/utils.ts +++ b/apps/web/src/components/Menu/utils.ts @@ -2,7 +2,12 @@ import orderBy from 'lodash/orderBy' import { ConfigMenuItemsType } from './config/config' export const getActiveMenuItem = ({ pathname, menuConfig }: { pathname: string; menuConfig: ConfigMenuItemsType[] }) => - menuConfig.find((menuItem) => pathname.startsWith(menuItem.href) || getActiveSubMenuItem({ menuItem, pathname })) + menuConfig.find( + (menuItem) => + pathname.startsWith(menuItem.href) || + getActiveSubMenuItem({ menuItem, pathname }) || + getActiveSubMenuChildItem({ menuItem, pathname }), + ) export const getActiveSubMenuItem = ({ pathname, menuItem }: { pathname: string; menuItem?: ConfigMenuItemsType }) => { const activeSubMenuItems = @@ -23,3 +28,34 @@ export const getActiveSubMenuItem = ({ pathname, menuItem }: { pathname: string; return mostSpecificMatch } + +export const getActiveSubMenuChildItem = ({ + pathname, + menuItem, +}: { + pathname: string + menuItem?: ConfigMenuItemsType +}) => { + const getChildItems = menuItem?.items + ?.map((i) => i.items) + ?.filter((i) => Boolean(i)) + .flat() + + const activeSubMenuItems = + getChildItems?.filter((subMenuItem) => subMenuItem?.href && pathname.startsWith(subMenuItem?.href)) ?? [] + + // Pathname doesn't include any submenu item href - return undefined + if (!activeSubMenuItems || activeSubMenuItems.length === 0) { + return undefined + } + + // Pathname includes one sub menu item href - return it + if (activeSubMenuItems.length === 1) { + return activeSubMenuItems[0] + } + + // Pathname includes multiple sub menu item hrefs - find the most specific match + const mostSpecificMatch = orderBy(activeSubMenuItems, (subMenuItem) => subMenuItem?.href?.length, 'desc')[0] + + return mostSpecificMatch +} diff --git a/apps/web/src/views/CakeStaking/index.tsx b/apps/web/src/views/CakeStaking/index.tsx index b61846f5cac14..cbefbd400c374 100644 --- a/apps/web/src/views/CakeStaking/index.tsx +++ b/apps/web/src/views/CakeStaking/index.tsx @@ -10,6 +10,7 @@ import useTheme from 'hooks/useTheme' import { useCallback, useState } from 'react' import styled from 'styled-components' import { useGauges } from 'views/GaugesVoting/hooks/useGauges' +import { SubMenu } from 'views/PositionManagers/components/SubMenu' import { BenefitCard } from './components/BenefitCard' import { CakeRewardsCard } from './components/CakeRewardsCard' import { LockCake } from './components/LockCake' @@ -35,6 +36,7 @@ const CakeStaking = () => { + diff --git a/apps/web/src/views/Farms/index.tsx b/apps/web/src/views/Farms/index.tsx index 1ca6334470f78..c6147dcc8f5c3 100644 --- a/apps/web/src/views/Farms/index.tsx +++ b/apps/web/src/views/Farms/index.tsx @@ -1,5 +1,6 @@ import { ConnectorNames } from 'config/wallet' import { ExtendEthereum } from 'global' +import { SubMenu } from 'views/PositionManagers/components/SubMenu' import { useAccount } from 'wagmi' import { mainnet } from 'wagmi/chains' import FarmsV3 from './FarmsV3' @@ -18,7 +19,12 @@ export function useIsBloctoETH() { } export const FarmsV3PageLayout: React.FC> = ({ children }) => { - return {children} + return ( + <> + + {children} + + ) } export { FarmsContext, FarmsV3Context } diff --git a/apps/web/src/views/Lottery/components/SubMenu/index.tsx b/apps/web/src/views/Lottery/components/SubMenu/index.tsx new file mode 100644 index 0000000000000..20c1c27d5dd9c --- /dev/null +++ b/apps/web/src/views/Lottery/components/SubMenu/index.tsx @@ -0,0 +1,22 @@ +import { useTranslation } from '@pancakeswap/localization' +import { SubMenuItems } from '@pancakeswap/uikit' +import { useRouter } from 'next/router' +import React, { useMemo } from 'react' + +export const SubMenu: React.FC = () => { + const { pathname } = useRouter() + const { t } = useTranslation() + + const subMenuItems = useMemo(() => { + return [ + { label: t('Prediction'), href: '/prediction' }, + { label: t('Lottery'), href: '/lottery' }, + ] + }, [t]) + + const activeSubItem = useMemo(() => { + return subMenuItems.find((subMenuItem) => subMenuItem.href === pathname)?.href + }, [subMenuItems, pathname]) + + return +} diff --git a/apps/web/src/views/Lottery/index.tsx b/apps/web/src/views/Lottery/index.tsx index f0cdb148342d3..71e607966bbcc 100644 --- a/apps/web/src/views/Lottery/index.tsx +++ b/apps/web/src/views/Lottery/index.tsx @@ -6,6 +6,7 @@ import useTheme from 'hooks/useTheme' import { useState } from 'react' import { useFetchLottery, useLottery } from 'state/lottery/hooks' import { styled } from 'styled-components' +import { SubMenu } from 'views/Lottery/components/SubMenu' import AllHistoryCard from './components/AllHistoryCard' import CheckPrizesSection from './components/CheckPrizesSection' import Countdown from './components/Countdown' @@ -44,6 +45,7 @@ const Lottery = () => { return ( <> + diff --git a/apps/web/src/views/Pools/index.tsx b/apps/web/src/views/Pools/index.tsx index 773a15e9dbdaf..c8be54ac3c1af 100644 --- a/apps/web/src/views/Pools/index.tsx +++ b/apps/web/src/views/Pools/index.tsx @@ -1,18 +1,18 @@ import { styled } from 'styled-components' -import { checkIsBoostedPool } from '@pancakeswap/pools' -import { Flex, FlexLayout, Heading, Image, Link, Loading, PageHeader, Text, ViewMode } from '@pancakeswap/uikit' -import { Pool } from '@pancakeswap/widgets-internal' -import { useAccount } from 'wagmi' - import { ChainId } from '@pancakeswap/chains' import { useTranslation } from '@pancakeswap/localization' +import { checkIsBoostedPool } from '@pancakeswap/pools' import { Token } from '@pancakeswap/sdk' +import { Flex, FlexLayout, Heading, Image, Link, Loading, PageHeader, Text, ViewMode } from '@pancakeswap/uikit' +import { Pool } from '@pancakeswap/widgets-internal' import ConnectWalletButton from 'components/ConnectWalletButton' import Page from 'components/Layout/Page' import { TokenPairImage } from 'components/TokenImage' import { useActiveChainId } from 'hooks/useActiveChainId' import { usePoolsPageFetch, usePoolsWithVault } from 'state/pools/hooks' +import { SubMenu } from 'views/PositionManagers/components/SubMenu' +import { useAccount } from 'wagmi' import CakeVaultCard from './components/CakeVaultCard' import AprRow from './components/PoolCard/AprRow' @@ -50,6 +50,7 @@ const Pools: React.FC = () => { return ( <> + diff --git a/apps/web/src/views/PositionManagers/components/SubMenu/index.tsx b/apps/web/src/views/PositionManagers/components/SubMenu/index.tsx new file mode 100644 index 0000000000000..fa92a8936732c --- /dev/null +++ b/apps/web/src/views/PositionManagers/components/SubMenu/index.tsx @@ -0,0 +1,50 @@ +import { useTranslation } from '@pancakeswap/localization' +import { SUPPORTED_CHAIN_IDS as POOL_SUPPORTED_CHAINS } from '@pancakeswap/pools' +import { SUPPORTED_CHAIN_IDS as POSITION_MANAGERS_SUPPORTED_CHAINS } from '@pancakeswap/position-managers' +import { SubMenuItems } from '@pancakeswap/uikit' +import { addMenuItemSupported } from 'components/Menu/config/config' +import { SUPPORT_CAKE_STAKING, SUPPORT_FARMS } from 'config/constants/supportChains' +import { useActiveChainId } from 'hooks/useActiveChainId' +import { useRouter } from 'next/router' +import React, { useMemo } from 'react' + +export const SubMenu: React.FC = () => { + const { pathname } = useRouter() + const { t } = useTranslation() + const { chainId } = useActiveChainId() + + const subMenuItems = useMemo(() => { + return [ + { + label: t('Farm / Liquidity'), + href: '/farms', + supportChainIds: SUPPORT_FARMS, + }, + { + label: t('Position Manager'), + href: '/position-managers', + supportChainIds: POSITION_MANAGERS_SUPPORTED_CHAINS, + }, + { + label: t('CAKE Staking'), + href: '/cake-staking', + supportChainIds: SUPPORT_CAKE_STAKING, + }, + { + label: t('Syrup Pools'), + href: '/pools', + supportChainIds: POOL_SUPPORTED_CHAINS, + }, + ].map((item) => addMenuItemSupported(item, chainId)) + }, [chainId, t]) + + const activeSubItem = useMemo(() => { + if (pathname === '/pools/history') { + return subMenuItems[3].href // pools + } + + return subMenuItems.find((subMenuItem) => subMenuItem.href === pathname)?.href + }, [subMenuItems, pathname]) + + return +} diff --git a/apps/web/src/views/PositionManagers/index.tsx b/apps/web/src/views/PositionManagers/index.tsx index 5449e35c2487b..c509906ae9696 100644 --- a/apps/web/src/views/PositionManagers/index.tsx +++ b/apps/web/src/views/PositionManagers/index.tsx @@ -1,11 +1,12 @@ import Page from 'components/Layout/Page' - +import { SubMenu } from 'views/PositionManagers/components/SubMenu' import { Header } from './components' import { Controls, VaultContent } from './containers' export function PositionManagers() { return ( <> +
diff --git a/apps/web/src/views/Predictions/components/InPageBanner.tsx b/apps/web/src/views/Predictions/components/InPageBanner.tsx index efec62e8c0acf..a8314fa09ed4a 100644 --- a/apps/web/src/views/Predictions/components/InPageBanner.tsx +++ b/apps/web/src/views/Predictions/components/InPageBanner.tsx @@ -23,7 +23,7 @@ const Container = styled(Flex).withConfig({ shouldForwardProp: (prop) => !['$bac ${({ theme }) => theme.mediaQueries.lg} { position: absolute; - top: 0; + top: 42px; left: 0; right: 0; } diff --git a/apps/web/src/views/Predictions/index.tsx b/apps/web/src/views/Predictions/index.tsx index 87adcebab54ae..037ec96e8e5f7 100644 --- a/apps/web/src/views/Predictions/index.tsx +++ b/apps/web/src/views/Predictions/index.tsx @@ -4,7 +4,7 @@ import { useAccountLocalEventListener } from 'hooks/useAccountLocalEventListener import { useEffect, useRef } from 'react' import { useChartView, useIsChartPaneOpen } from 'state/predictions/hooks' import { useUserPredictionChainlinkChartDisclaimerShow, useUserPredictionChartDisclaimerShow } from 'state/user/hooks' - +import { SubMenu } from 'views/Lottery/components/SubMenu' import Desktop from './Desktop' import Mobile from './Mobile' import ChainlinkChartDisclaimer from './components/ChainlinkChartDisclaimer' @@ -67,6 +67,7 @@ const Predictions = () => { return ( + diff --git a/packages/localization/src/config/translations.json b/packages/localization/src/config/translations.json index 2741fe91f286b..17091fe6f0ba7 100644 --- a/packages/localization/src/config/translations.json +++ b/packages/localization/src/config/translations.json @@ -570,7 +570,6 @@ "You can now start prediction": "You can now start prediction", "Leaderboard": "Leaderboard", "Tokens": "Tokens", - "Contact": "Contact", "The higher your team’s rank, the better your prizes!": "The higher your team’s rank, the better your prizes!", "Get Ready": "Get Ready", "Trading Battle": "Trading Battle", @@ -1744,7 +1743,6 @@ "In the Public Sale, everyone with an active PancakeSwap profile can commit. However the maximum amount of CAKE users can commit, is equal to the number of iCAKE they have.": "In the Public Sale, everyone with an active PancakeSwap profile can commit. However the maximum amount of CAKE users can commit, is equal to the number of iCAKE they have.", "And there’s a fee for participation: see below.": "And there’s a fee for participation: see below.", "You have successfully claimed your rewards.": "You have successfully claimed your rewards.", - "Pottery (BETA)": "Pottery (BETA)", "This IFO has token vesting. Purchased tokens are released over a period of time.": "This IFO has token vesting. Purchased tokens are released over a period of time.", "What is the difference between an IFO and a cIFO?": "What is the difference between an IFO and a cIFO?", "If you don’t commit enough CAKE, you may not receive a meaningful amount of IFO tokens, or you may not receive any IFO tokens at all.": "If you don’t commit enough CAKE, you may not receive a meaningful amount of IFO tokens, or you may not receive any IFO tokens at all.", @@ -2093,7 +2091,6 @@ "Your referrals will be listed in your affiliate dashboard, along with the date they were made, their status, and the commission amount earned": "Your referrals will be listed in your affiliate dashboard, along with the date they were made, their status, and the commission amount earned", "Join Now!": "Join Now!", "Swap & StableSwap": "Swap & StableSwap", - "Affiliate Program": "Affiliate Program", "Login": "Login", "Referral Link Created": "Referral Link Created", "create a new link": "create a new link", @@ -2582,7 +2579,6 @@ "News": "News", "Figures": "Figures", "Tokenomics": "Tokenomics", - "Farms and Syrup Pools": "Farms and Syrup Pools", "Contributing": "Contributing", "Github": "Github", "Support": "Support", @@ -3535,5 +3531,21 @@ "Please exercise due caution when trading / providing liquidity for the PNP token. The protocol recently encountered a": "Please exercise due caution when trading / providing liquidity for the PNP token. The protocol recently encountered a", "For more information, please refer to %org%’s": "For more information, please refer to %org%’s", "Please exercise due caution when trading / providing liquidity for the uniBTC token. The protocol recently encountered a security compromise.": "Please exercise due caution when trading / providing liquidity for the uniBTC token. The protocol recently encountered a security compromise.", - "Caution - %token% Token": "Caution - %token% Token" + "Caution - %token% Token": "Caution - %token% Token", + "Gauges": "Gauges", + "V4": "V4", + "CAKE Incentives": "CAKE Incentives", + "Staking Pools": "Staking Pools", + "Token Launches": "Token Launches", + "Get Help": "Get Help", + "Audits": "Audits", + "Perps": "Perps", + "Farm / Liquidity": "Farm / Liquidity", + "Stargate": "Stargate", + "Axelar": "Axelar", + "Celer": "Celer", + "Wormhole": "Wormhole", + "Aptos": "Aptos", + "Play": "Play", + "Legacy products": "Legacy products" } diff --git a/packages/uikit/src/__tests__/widgets/__snapshots__/menu.test.tsx.snap b/packages/uikit/src/__tests__/widgets/__snapshots__/menu.test.tsx.snap index 3b0d7d62129a5..edb7e4bd074b5 100644 --- a/packages/uikit/src/__tests__/widgets/__snapshots__/menu.test.tsx.snap +++ b/packages/uikit/src/__tests__/widgets/__snapshots__/menu.test.tsx.snap @@ -9,14 +9,14 @@ exports[`renders correctly 1`] = ` flex-shrink: 0; } -.c19 { +.c20 { align-self: center; fill: var(--colors-textSubtle); color: var(--colors-textSubtle); flex-shrink: 0; } -.c27 { +.c28 { align-self: center; fill: var(--colors-text); color: var(--colors-text); @@ -24,7 +24,7 @@ exports[`renders correctly 1`] = ` margin-right: 8px; } -.c32 { +.c33 { align-self: center; fill: var(--colors-textSubtle); color: var(--colors-textSubtle); @@ -32,7 +32,7 @@ exports[`renders correctly 1`] = ` margin-right: 0.5rem; } -.c16 { +.c17 { color: var(--colors-failure); font-weight: 400; line-height: 1.5; @@ -40,7 +40,7 @@ exports[`renders correctly 1`] = ` font-size: 14px; } -.c20 { +.c21 { color: var(--colors-warning); font-weight: 400; line-height: 1.5; @@ -48,14 +48,14 @@ exports[`renders correctly 1`] = ` font-size: 14px; } -.c28 { +.c29 { color: var(--colors-textSubtle); font-weight: 600; line-height: 1.5; font-size: 16px; } -.c31 { +.c32 { position: relative; align-items: center; border: 0; @@ -80,19 +80,19 @@ exports[`renders correctly 1`] = ` box-shadow: none; } -.c31:focus-visible { +.c32:focus-visible { outline: none; box-shadow: var(--shadows-focus); } -.c31:active:not(:disabled):not(.pancake-button--disabled):not(.pancake-button--disabled) { +.c32:active:not(:disabled):not(.pancake-button--disabled):not(.pancake-button--disabled) { opacity: 0.85; transform: translateY(1px); box-shadow: none; } -.c31:disabled, -.c31.pancake-button--disabled { +.c32:disabled, +.c32.pancake-button--disabled { background-color: var(--colors-backgroundDisabled); border-color: var(--colors-backgroundDisabled); box-shadow: none; @@ -100,7 +100,7 @@ exports[`renders correctly 1`] = ` cursor: not-allowed; } -.c35 { +.c36 { position: relative; align-items: center; border: 0; @@ -126,19 +126,19 @@ exports[`renders correctly 1`] = ` height: sm; } -.c35:focus-visible { +.c36:focus-visible { outline: none; box-shadow: var(--shadows-focus); } -.c35:active:not(:disabled):not(.pancake-button--disabled):not(.pancake-button--disabled) { +.c36:active:not(:disabled):not(.pancake-button--disabled):not(.pancake-button--disabled) { opacity: 0.85; transform: translateY(1px); box-shadow: none; } -.c35:disabled, -.c35.pancake-button--disabled { +.c36:disabled, +.c36.pancake-button--disabled { background-color: var(--colors-backgroundDisabled); border-color: var(--colors-backgroundDisabled); box-shadow: none; @@ -155,35 +155,39 @@ exports[`renders correctly 1`] = ` padding-bottom: 4px; } -.c23 { +.c15 { + margin-left: 0px; +} + +.c24 { width: 100%; } -.c25 { +.c26 { height: 100%; } -.c29 { +.c30 { margin-top: 4px; } -.c37 { +.c38 { overflow: hidden; } -.c39 { +.c40 { margin-top: 57px; } -.c43 { +.c44 { padding-left: 0px; } -.c46 { +.c47 { margin-right: 20px; } -.c51 { +.c52 { margin-top: 0; } @@ -196,23 +200,23 @@ exports[`renders correctly 1`] = ` align-items: center; } -.c24 { +.c25 { display: flex; align-items: center; justify-content: space-between; } -.c38 { +.c39 { display: flex; justify-content: space-around; } -.c44 { +.c45 { display: flex; justify-content: center; } -.c49 { +.c50 { gap: 10px; } @@ -257,7 +261,7 @@ exports[`renders correctly 1`] = ` border-bottom-right-radius: 8px; } -.c22 { +.c23 { border-color: var(--colors-cardBorder); border-style: solid; border-width: 1px 0 0; @@ -279,7 +283,7 @@ exports[`renders correctly 1`] = ` visibility: hidden; } -.c17 { +.c18 { border-radius: var(--radii-default); padding: 0 8px; border: 2px solid; @@ -289,7 +293,7 @@ exports[`renders correctly 1`] = ` margin-left: 8px; } -.c21 { +.c22 { border-radius: var(--radii-default); padding: 0 8px; border: 2px solid; @@ -299,20 +303,20 @@ exports[`renders correctly 1`] = ` margin-left: 8px; } -.c26 { +.c27 { display: flex; align-items: center; } -.c26 svg { +.c27 svg { transition: transform 0.3s; } -.c26:hover svg { +.c27:hover svg { transform: scale(1.2); } -.c34 { +.c35 { width: max-content; display: flex; flex-direction: column; @@ -333,12 +337,12 @@ exports[`renders correctly 1`] = ` pointer-events: none; } -.c30 { +.c31 { position: relative; } -.c30:hover .c33, -.c30:focus-within .c33 { +.c31:hover .c34, +.c31:focus-within .c34 { opacity: 1; max-height: 400px; overflow-y: auto; @@ -346,7 +350,7 @@ exports[`renders correctly 1`] = ` pointer-events: auto; } -.c36 { +.c37 { color: var(--colors-text); padding: 0 8px; border-radius: 8px; @@ -374,7 +378,7 @@ exports[`renders correctly 1`] = ` border-radius: 16px; } -.c15 { +.c16 { position: relative; display: flex; align-items: center; @@ -387,7 +391,7 @@ exports[`renders correctly 1`] = ` height: 48px; } -.c15:after { +.c16:after { content: ""; border-radius: 100%; background: var(--colors-failure); @@ -396,12 +400,12 @@ exports[`renders correctly 1`] = ` margin-left: 12px; } -.c15:hover { +.c16:hover { background: var(--colors-tertiary); border-radius: 16px; } -.c18 { +.c19 { position: relative; display: flex; align-items: center; @@ -414,7 +418,7 @@ exports[`renders correctly 1`] = ` height: 48px; } -.c18:after { +.c19:after { content: ""; border-radius: 100%; background: var(--colors-warning); @@ -423,12 +427,12 @@ exports[`renders correctly 1`] = ` margin-left: 12px; } -.c18:hover { +.c19:hover { background: var(--colors-tertiary); border-radius: 16px; } -.c48 { +.c49 { position: relative; display: flex; align-items: center; @@ -442,23 +446,23 @@ exports[`renders correctly 1`] = ` height: 42px; } -.c48:hover { +.c49:hover { background: var(--colors-tertiary); } -.c40 { +.c41 { width: 100%; overflow: hidden; position: relative; } -.c50 { +.c51 { width: 100%; overflow: hidden; position: relative; } -.c45 { +.c46 { position: relative; z-index: 1; width: 100%; @@ -473,11 +477,11 @@ exports[`renders correctly 1`] = ` -ms-overflow-style: none; } -.c45::-webkit-scrollbar { +.c46::-webkit-scrollbar { display: none; } -.c41 { +.c42 { position: absolute; z-index: 2; width: 48px; @@ -493,13 +497,13 @@ exports[`renders correctly 1`] = ` background: linear-gradient(90deg, #ffffff 29.76%, rgba(255, 255, 255, 0) 100%); } -.c41.show { +.c42.show { pointer-events: auto; opacity: 1; transition: 0.25s ease-in opacity; } -.c42 { +.c43 { position: absolute; z-index: 2; width: 48px; @@ -515,13 +519,13 @@ exports[`renders correctly 1`] = ` background: linear-gradient(270deg, #ffffff 0%, rgba(255, 255, 255, 0) 87.5%); } -.c42.show { +.c43.show { pointer-events: auto; opacity: 1; transition: 0.25s ease-in opacity; } -.c47 { +.c48 { display: inline-block; vertical-align: top; scroll-snap-align: start; @@ -581,13 +585,13 @@ exports[`renders correctly 1`] = ` z-index: 20; } -.c52 { +.c53 { position: relative; display: flex; max-width: 100vw; } -.c53 { +.c54 { flex-grow: 1; transition: margin-top 0.2s,margin-left 0.2s cubic-bezier(0.4, 0, 0.2, 1); transform: translate3d(0, 0, 0); @@ -601,19 +605,19 @@ exports[`renders correctly 1`] = ` } @supports (-webkit-text-size-adjust: none) and (not (-ms-accelerator: true)) and (not (-moz-appearance: none)) { - .c19 { + .c20 { filter: none!important; } } @supports (-webkit-text-size-adjust: none) and (not (-ms-accelerator: true)) and (not (-moz-appearance: none)) { - .c27 { + .c28 { filter: none!important; } } @supports (-webkit-text-size-adjust: none) and (not (-ms-accelerator: true)) and (not (-moz-appearance: none)) { - .c32 { + .c33 { filter: none!important; } } @@ -639,13 +643,13 @@ exports[`renders correctly 1`] = ` } @media (hover: hover) { - .c31:hover:not(:disabled):not(.pancake-button--disabled):not(.pancake-button--disabled):not(:active) { + .c32:hover:not(:disabled):not(.pancake-button--disabled):not(.pancake-button--disabled):not(:active) { opacity: 0.65; } } @media (hover: hover) { - .c35:hover:not(:disabled):not(.pancake-button--disabled):not(.pancake-button--disabled):not(:active) { + .c36:hover:not(:disabled):not(.pancake-button--disabled):not(.pancake-button--disabled):not(:active) { opacity: 0.65; } } @@ -727,7 +731,7 @@ exports[`renders correctly 1`] = ` } @media screen and (min-width: 576px) { - .c50 { + .c51 { display: none; } } @@ -860,7 +864,7 @@ exports[`renders correctly 1`] = ` href="/swap" >
Exchange
@@ -874,7 +878,7 @@ exports[`renders correctly 1`] = ` href="/liquidity" >
Liquidity
@@ -911,7 +915,7 @@ exports[`renders correctly 1`] = ` href="/earn" >
Earn
@@ -925,7 +929,7 @@ exports[`renders correctly 1`] = ` href="/farms" >
Yield Farms
@@ -939,7 +943,7 @@ exports[`renders correctly 1`] = ` href="/pools" >
Syrup pools
@@ -957,7 +961,7 @@ exports[`renders correctly 1`] = ` class="c9" > Win @@ -976,7 +980,7 @@ exports[`renders correctly 1`] = ` href="/" >
Win
@@ -990,11 +994,11 @@ exports[`renders correctly 1`] = ` href="/" >
body
@@ -2320,6 +2324,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="https://docs.pancakeswap.finance/contact-us" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > Contact @@ -2333,6 +2338,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="https://blog.pancakeswap.finance/" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > Blog @@ -2346,6 +2352,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="https://docs.pancakeswap.finance/contact-us/telegram" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > Community @@ -2359,6 +2366,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="https://docs.pancakeswap.finance/tokenomics/cake" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > CAKE @@ -2381,6 +2389,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="https://pancakeswap.creator-spring.com/" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > Online Store @@ -2403,6 +2412,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="Support https://docs.pancakeswap.finance/contact-us/customer-support" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > Customer @@ -2416,6 +2426,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="https://docs.pancakeswap.finance/help/troubleshooting" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > Troubleshooting @@ -2429,6 +2440,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="https://docs.pancakeswap.finance/get-started" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > Guides @@ -2451,6 +2463,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="https://github.com/pancakeswap" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > Github @@ -2464,6 +2477,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="https://docs.pancakeswap.finance" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > Documentation @@ -2477,6 +2491,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="https://app.gitbook.com/@pancakeswap-1/s/pancakeswap/code/bug-bounty" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > Bug Bounty @@ -2490,6 +2505,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="https://docs.pancakeswap.finance/help/faq#is-pancakeswap-safe-has-pancakeswap-been-audited" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > Audits @@ -2503,6 +2519,7 @@ exports[`renders correctly 1`] = ` data-theme="dark" href="https://docs.pancakeswap.finance/hiring/become-a-chef" rel="noreferrer noopener" + style="text-transform: none;" target="_blank" > Careers @@ -3278,7 +3295,7 @@ exports[`renders correctly 1`] = ` flex-shrink: 0; } -.c19 { +.c20 { color: var(--colors-failure); font-weight: 400; line-height: 1.5; @@ -3286,7 +3303,7 @@ exports[`renders correctly 1`] = ` font-size: 14px; } -.c23 { +.c24 { color: var(--colors-warning); font-weight: 400; line-height: 1.5; @@ -3302,7 +3319,11 @@ exports[`renders correctly 1`] = ` font-size: 10px; } -.c26 { +.c17 { + margin-left: 0px; +} + +.c27 { width: 100%; } @@ -3310,12 +3331,12 @@ exports[`renders correctly 1`] = ` height: 100%; } -.c17 { +.c18 { display: flex; align-items: center; } -.c27 { +.c28 { display: flex; align-items: center; justify-content: space-between; @@ -3363,13 +3384,13 @@ exports[`renders correctly 1`] = ` transition: height 0.25s ease; } -.c21 { +.c22 { position: relative; height: 22px; width: 21px; } -.c21 div:first-child { +.c22 div:first-child { height: 22px; width: 21px; z-index: 0; @@ -3459,7 +3480,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { border-bottom-right-radius: 8px; } -.c25 { +.c26 { border-color: var(--colors-cardBorder); border-style: solid; border-width: 1px 0 0; @@ -3481,7 +3502,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { visibility: hidden; } -.c20 { +.c21 { border-radius: var(--radii-default); padding: 0 8px; border: 2px solid; @@ -3491,7 +3512,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { margin-left: 8px; } -.c24 { +.c25 { border-radius: var(--radii-default); padding: 0 8px; border: 2px solid; @@ -3520,7 +3541,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { background-color: var(--colors-failure); } -.c18 { +.c19 { display: inline-flex; position: absolute; top: 0; @@ -3533,7 +3554,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { background-color: var(--colors-failure); } -.c22 { +.c23 { display: inline-flex; position: absolute; top: 0; @@ -3781,7 +3802,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { href="/swap" >
Exchange
@@ -3795,7 +3816,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { href="/liquidity" >
Liquidity
@@ -3904,7 +3925,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { href="/earn" >
Earn
@@ -3918,7 +3939,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { href="/farms" >
Yield Farms
@@ -3932,7 +3953,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { href="/pools" >
Syrup pools
@@ -4006,7 +4027,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 {
@@ -4024,7 +4045,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { href="/" >
Win
@@ -4038,11 +4059,11 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { href="/" >
Predictions
LIVE
@@ -4057,7 +4078,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { href="/" >
Lottery
@@ -4086,7 +4107,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { class="c4 c5" >
@@ -4112,7 +4133,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 {
@@ -4130,7 +4151,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { href="/" >
Info & Analytics
@@ -4144,11 +4165,11 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { href="/" >
IFO Token Sales
SOON
@@ -4159,7 +4180,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { class="c14" >
NFT Collectibles
@@ -4184,7 +4205,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { href="/" >
Team Leaderboard
@@ -4194,7 +4215,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { class="c14" >
Blog
@@ -4220,10 +4241,10 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { target="_blank" >
Docs & Guides
@@ -4235,7 +4256,7 @@ html[data-useragent*="TokenPocket_iOS"] .c1 { xmlns="http://www.w3.org/2000/svg" >
diff --git a/packages/uikit/src/components/DropdownMenu/DropdownMenu.tsx b/packages/uikit/src/components/DropdownMenu/DropdownMenu.tsx index bbde8fb636f06..f6e249516662c 100644 --- a/packages/uikit/src/components/DropdownMenu/DropdownMenu.tsx +++ b/packages/uikit/src/components/DropdownMenu/DropdownMenu.tsx @@ -1,12 +1,11 @@ -/* eslint-disable react/no-array-index-key */ import debounce from "lodash/debounce"; -import React, { useCallback, useContext, useEffect, useState } from "react"; +import React, { useCallback, useContext, useEffect, useMemo, useState } from "react"; import { usePopper } from "react-popper"; import useMatchBreakpoints from "../../contexts/MatchBreakpoints/useMatchBreakpoints"; import { useOnClickOutside } from "../../hooks"; import { MenuContext } from "../../widgets/Menu/context"; import { Box, Flex } from "../Box"; -import { LogoutIcon } from "../Svg"; +import { ChevronDownIcon, ChevronUpIcon, OpenNewIcon } from "../Svg"; import { DropdownMenuDivider, DropdownMenuItem, @@ -14,13 +13,144 @@ import { StyledDropdownMenu, StyledDropdownMenuItemContainer, } from "./styles"; -import { DropdownMenuItemType, DropdownMenuProps } from "./types"; +import { DropdownMenuItems, DropdownMenuItemType, DropdownMenuProps, LinkStatus as LinkStatusType } from "./types"; + +const MenuItemComponent: React.FC<{ + label: React.ReactNode; + status: LinkStatusType | undefined; + isChildItems: boolean | undefined; +}> = ({ label, status, isChildItems }) => { + return ( + + {label} + {status && ( + + {status.text} + + )} + + ); +}; + +const MenuItem: React.FC<{ + item: DropdownMenuItems; + activeItem?: string; + activeSubItemChildItem?: string; + isChildItems?: boolean; + isDisabled?: boolean; + linkComponent: any; + setIsOpen: (open: boolean) => void; +}> = ({ item, isChildItems, isDisabled, linkComponent, activeItem, activeSubItemChildItem, setIsOpen }) => { + const [isSubMenuOpen, setIsSubMenuOpen] = useState(true); + const { isMobile, isMd } = useMatchBreakpoints(); + const { type = DropdownMenuItemType.INTERNAL_LINK, label, href = "/", status, disabled, items, ...itemProps } = item; + const hasChildItems = useMemo(() => Boolean(items && items.length > 0), [items]); + + const isActive = useMemo(() => { + return Boolean(isChildItems ? item.href === activeSubItemChildItem : item.href === activeItem); + }, [item, isChildItems, activeSubItemChildItem, activeItem]); + + const MenuItemContent = ; + + const handleToggleSubMenu = useCallback( + (e: React.MouseEvent) => { + e.stopPropagation(); + e.preventDefault(); + setIsSubMenuOpen(!isSubMenuOpen); + }, + [isSubMenuOpen] + ); + + const chevronIconColor = useMemo(() => { + const isActiveChevron = hasChildItems && item.items?.find((i) => i.href === activeSubItemChildItem); + if (isActiveChevron) { + return "secondary"; + } + + return disabled || isDisabled ? "disabled" : "textSubtle"; + }, [activeSubItemChildItem, disabled, hasChildItems, isDisabled, item]); + + return ( + + {type === DropdownMenuItemType.BUTTON && ( + + {MenuItemContent} + + )} + {type === DropdownMenuItemType.INTERNAL_LINK && ( + ) => { + if (hasChildItems) { + handleToggleSubMenu(e); + } else { + setIsOpen(false); + itemProps.onClick?.(e); + } + }} + > + {MenuItemContent} + {hasChildItems && ( + <> + {isSubMenuOpen ? ( + + ) : ( + + )} + + )} + + )} + {type === DropdownMenuItemType.EXTERNAL_LINK && ( + { + setIsOpen(false); + itemProps.onClick?.(e); + }} + > + + {MenuItemContent} + + + + )} + + {type === DropdownMenuItemType.DIVIDER && } + + {isSubMenuOpen && + hasChildItems && + items + ?.filter((childItem) => ((isMobile || isMd) && childItem.isMobileOnly) || !childItem.isMobileOnly) + ?.map((childItem) => ( + + ))} + + ); +}; const DropdownMenu: React.FC> = ({ children, isBottomNav = false, showItemsOnMobile = false, activeItem = "", + activeSubItemChildItem = "", items = [], index, setMenuOpenByIndex, @@ -54,7 +184,6 @@ const DropdownMenu: React.FC> = ({ isBottomNav ? 100 : 10 ); - // added this to remove the ugly 4 lines [targetRef, tooltipRef].forEach((ref) => { ref?.addEventListener("mouseenter", showDropdownMenu); ref?.addEventListener("mouseleave", hideDropdownMenu); @@ -93,81 +222,25 @@ const DropdownMenu: React.FC> = ({ {hasItems && ( {items .filter((item) => ((isMobile || isMd) && item.isMobileOnly) || !item.isMobileOnly) - .map( - ( - { type = DropdownMenuItemType.INTERNAL_LINK, label, href = "/", status, disabled, ...itemProps }, - itemItem - ) => { - const MenuItemContent = ( - - {label} - {status && ( - - {status.text} - - )} - - ); - const isActive = href === activeItem; - return ( - - {type === DropdownMenuItemType.BUTTON && ( - - {MenuItemContent} - - )} - {type === DropdownMenuItemType.INTERNAL_LINK && ( - ) => { - setIsOpen(false); - itemProps.onClick?.(e); - }} - > - {MenuItemContent} - - )} - {type === DropdownMenuItemType.EXTERNAL_LINK && ( - { - setIsOpen(false); - itemProps.onClick?.(e); - }} - > - - {MenuItemContent} - - - - )} - {type === DropdownMenuItemType.DIVIDER && } - - ); - } - )} + .map((item) => ( + + ))} )} diff --git a/packages/uikit/src/components/DropdownMenu/types.ts b/packages/uikit/src/components/DropdownMenu/types.ts index df3a08ce68bf2..e284ae5a2af68 100644 --- a/packages/uikit/src/components/DropdownMenu/types.ts +++ b/packages/uikit/src/components/DropdownMenu/types.ts @@ -6,6 +6,7 @@ export interface DropdownMenuProps extends BoxProps { items?: DropdownMenuItems[]; isDisabled?: boolean; activeItem?: string; + activeSubItemChildItem?: string; /** * As BottomNav styles */ @@ -35,7 +36,7 @@ export interface LinkStatus { color: keyof Colors; } -export interface DropdownMenuItems { +export interface DropdownMenuItemsDetails { label?: string | React.ReactNode; href?: string; onClick?: (e: React.MouseEvent) => void; @@ -47,3 +48,7 @@ export interface DropdownMenuItems { isMobileOnly?: boolean; confirmModalId?: string; } + +export interface DropdownMenuItems extends DropdownMenuItemsDetails { + items?: DropdownMenuItemsDetails[]; +} diff --git a/packages/uikit/src/components/Footer/Footer.tsx b/packages/uikit/src/components/Footer/Footer.tsx index 741cfda5a4193..7256662566c46 100644 --- a/packages/uikit/src/components/Footer/Footer.tsx +++ b/packages/uikit/src/components/Footer/Footer.tsx @@ -68,6 +68,7 @@ const MenuItem: React.FC> = ({ rel="noreferrer noopener" color={isHighlighted ? vars.colors.warning : "text"} bold={false} + style={{ textTransform: "none" }} > {label} diff --git a/packages/uikit/src/components/MenuItems/MenuItems.tsx b/packages/uikit/src/components/MenuItems/MenuItems.tsx index a83f7f29c3c7b..a5e69b87c7d12 100644 --- a/packages/uikit/src/components/MenuItems/MenuItems.tsx +++ b/packages/uikit/src/components/MenuItems/MenuItems.tsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { createElement, memo } from "react"; -import { Flex } from "../Box"; import isTouchDevice from "../../util/isTouchDevice"; +import { Flex } from "../Box"; import DropdownMenu from "../DropdownMenu/DropdownMenu"; import MenuItem from "../MenuItem/MenuItem"; import { MenuItemsProps } from "./types"; @@ -10,6 +10,7 @@ const MenuItems: React.FC> = ({ items = [], activeItem, activeSubItem, + activeSubItemChildItem, ...props }) => { return ( @@ -25,6 +26,7 @@ const MenuItems: React.FC> = ({ items={menuItems} py={1} activeItem={activeSubItem} + activeSubItemChildItem={activeSubItemChildItem} isDisabled={disabled} > > = (props) => { + return ( + + + + + + + + + ); +}; + +export default Icon; diff --git a/packages/uikit/src/components/Svg/index.tsx b/packages/uikit/src/components/Svg/index.tsx index 223bec7c61ff5..5b9765f0ee441 100644 --- a/packages/uikit/src/components/Svg/index.tsx +++ b/packages/uikit/src/components/Svg/index.tsx @@ -78,6 +78,7 @@ export { default as EthChainIcon } from "./Icons/EthChain"; export { default as ExpandIcon } from "./Icons/Expand"; export { default as FarmIcon } from "./Icons/Farm"; export { default as FavoriteBorderIcon } from "./Icons/FavoriteBorder"; +export { default as GameIcon } from "./Icons/Game"; export { default as GithubIcon } from "./Icons/Github"; export { default as GlassGlobeIcon } from "./Icons/GlassGlobe"; export { default as GovernanceIcon } from "./Icons/Governance"; diff --git a/packages/uikit/src/widgets/Menu/Menu.tsx b/packages/uikit/src/widgets/Menu/Menu.tsx index 98c365a881c3b..da256912640c7 100644 --- a/packages/uikit/src/widgets/Menu/Menu.tsx +++ b/packages/uikit/src/widgets/Menu/Menu.tsx @@ -84,6 +84,7 @@ const Menu: React.FC> = ({ footerLinks, activeItem, activeSubItem, + activeSubItemChildItem, langs, buyCakeLabel, buyCakeLink, @@ -151,7 +152,13 @@ const Menu: React.FC> = ({ {logoComponent ?? } - + diff --git a/packages/uikit/src/widgets/Menu/components/footerConfig.ts b/packages/uikit/src/widgets/Menu/components/footerConfig.ts index 494c5565bacb3..08c49ea86a00e 100644 --- a/packages/uikit/src/widgets/Menu/components/footerConfig.ts +++ b/packages/uikit/src/widgets/Menu/components/footerConfig.ts @@ -14,20 +14,12 @@ export const footerLinks: (t: ContextApi["t"]) => FooterLinkType[] = (t) => [ href: "https://pancakeswap.finance/liquidity/pools", }, { - label: t("Game"), - href: "https://pancakeswap.games/", + label: t("Play"), + href: "https://pancakeswap.finance/prediction", }, { - label: t("NFT"), - href: "https://pancakeswap.finance/nfts", - }, - { - label: t("Tokenomics"), - href: "https://docs.pancakeswap.finance/governance-and-tokenomics/cake-tokenomics", - }, - { - label: t("CAKE Emission Projection"), - href: "https://analytics.pancakeswap.finance/", + label: t("veCAKE"), + href: "https://pancakeswap.finance/cake-staking", }, { label: t("Merchandise"), @@ -39,16 +31,20 @@ export const footerLinks: (t: ContextApi["t"]) => FooterLinkType[] = (t) => [ label: "Business", items: [ { - label: t("Farms and Syrup Pools"), + label: t("CAKE Incentives"), href: "https://docs.pancakeswap.finance/ecosystem-and-partnerships/business-partnerships/syrup-pools-and-farms", }, { - label: t("IFO"), + label: t("Staking Pools"), + href: "https://pancakeswap.finance/pools", + }, + { + label: t("Token Launches"), href: "https://docs.pancakeswap.finance/ecosystem-and-partnerships/business-partnerships/initial-farm-offerings-ifos", }, { - label: t("NFT Marketplace"), - href: "https://docs.pancakeswap.finance/ecosystem-and-partnerships/business-partnerships/nft-market-applications", + label: t("Brand Assets"), + href: "https://docs.pancakeswap.finance/ecosystem-and-partnerships/brand", }, ], }, @@ -68,7 +64,7 @@ export const footerLinks: (t: ContextApi["t"]) => FooterLinkType[] = (t) => [ href: "https://docs.pancakeswap.finance/developers/bug-bounty", }, { - label: t("v4"), + label: t("V4"), href: "https://pancakeswap.finance/v4", }, ], @@ -77,7 +73,7 @@ export const footerLinks: (t: ContextApi["t"]) => FooterLinkType[] = (t) => [ label: t("Support"), items: [ { - label: t("Contact"), + label: t("Get Help"), href: "https://docs.pancakeswap.finance/contact-us/customer-support", }, { @@ -88,27 +84,39 @@ export const footerLinks: (t: ContextApi["t"]) => FooterLinkType[] = (t) => [ label: t("Documentation"), href: "https://docs.pancakeswap.finance/", }, + { + label: t("Audits"), + href: "https://docs.pancakeswap.finance/readme/audits", + }, + { + label: t("Legacy products"), + href: "https://docs.pancakeswap.finance/products/legacy-products", + }, ], }, { label: t("About"), items: [ { - label: t("Terms Of Service"), - href: "https://pancakeswap.finance/terms-of-service", + label: t("Tokenomics"), + href: "https://docs.pancakeswap.finance/governance-and-tokenomics/cake-tokenomics", }, { - label: t("Blog"), - href: "https://blog.pancakeswap.finance/", + label: t("CAKE Emission Projection"), + href: "https://analytics.pancakeswap.finance/", }, { - label: t("Brand Assets"), - href: "https://docs.pancakeswap.finance/ecosystem-and-partnerships/brand", + label: t("Blog"), + href: "https://blog.pancakeswap.finance/", }, { label: t("Careers"), href: "https://docs.pancakeswap.finance/team/become-a-chef", }, + { + label: t("Terms Of Service"), + href: "https://pancakeswap.finance/terms-of-service", + }, ], }, ]; diff --git a/packages/uikit/src/widgets/Menu/types.ts b/packages/uikit/src/widgets/Menu/types.ts index 14d777e81fb35..c2be5c77fa0db 100644 --- a/packages/uikit/src/widgets/Menu/types.ts +++ b/packages/uikit/src/widgets/Menu/types.ts @@ -19,6 +19,7 @@ export interface NavProps { footerLinks: Array; activeItem?: string; activeSubItem?: string; + activeSubItemChildItem?: string; isDark: boolean; toggleTheme: (isDark: boolean) => void; cakePriceUsd?: number;