mango-v4-ui/components/SideNav.tsx

477 lines
15 KiB
TypeScript
Raw Normal View History

2022-07-14 16:36:31 -07:00
import Link from 'next/link'
import {
2022-09-06 21:36:35 -07:00
EllipsisHorizontalIcon,
BuildingLibraryIcon,
2022-07-14 16:36:31 -07:00
LightBulbIcon,
2022-09-06 21:36:35 -07:00
ArrowTopRightOnSquareIcon,
2022-07-14 16:36:31 -07:00
ChevronDownIcon,
2022-08-15 18:59:15 -07:00
CurrencyDollarIcon,
2022-08-23 15:33:09 -07:00
ChartBarIcon,
2022-09-07 17:47:59 -07:00
Cog8ToothIcon,
2022-09-13 23:24:26 -07:00
ArrowsRightLeftIcon,
2022-12-18 04:30:49 -08:00
ArrowTrendingUpIcon,
2023-01-10 04:56:48 -08:00
MagnifyingGlassIcon,
2023-01-26 16:02:48 -08:00
BanknotesIcon,
2023-03-08 11:24:46 -08:00
NewspaperIcon,
PlusCircleIcon,
ArchiveBoxArrowDownIcon,
2022-09-06 21:36:35 -07:00
} from '@heroicons/react/20/solid'
2022-07-14 16:36:31 -07:00
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
import { Fragment, ReactNode } from 'react'
2022-07-14 16:36:31 -07:00
import { Disclosure, Popover, Transition } from '@headlessui/react'
2022-08-02 19:15:17 -07:00
import MangoAccountSummary from './account/MangoAccountSummary'
import Tooltip from './shared/Tooltip'
2022-09-11 04:48:23 -07:00
import { HealthType } from '@blockworks-foundation/mango-v4'
2022-09-11 17:22:37 -07:00
import { useWallet } from '@solana/wallet-adapter-react'
2022-09-14 07:52:18 -07:00
import mangoStore from '@store/mangoStore'
import HealthHeart from './account/HealthHeart'
2022-11-18 09:09:39 -08:00
import useMangoAccount from 'hooks/useMangoAccount'
2022-12-02 03:28:46 -08:00
import { useTheme } from 'next-themes'
2023-03-15 01:35:29 -07:00
import LeaderboardIcon from './icons/LeaderboardIcon'
2022-07-14 16:36:31 -07:00
const SideNav = ({ collapsed }: { collapsed: boolean }) => {
2023-01-10 18:46:18 -08:00
const { t } = useTranslation(['common', 'search'])
2022-09-11 17:22:37 -07:00
const { connected } = useWallet()
const group = mangoStore.getState().group
2022-11-18 09:09:39 -08:00
const { mangoAccount } = useMangoAccount()
2022-07-14 16:36:31 -07:00
const router = useRouter()
const { pathname } = router
2023-05-30 20:03:53 -07:00
const { theme } = useTheme()
2022-07-14 16:36:31 -07:00
2023-06-05 19:49:51 -07:00
const playAnimation = () => {
const set = mangoStore.getState().set
set((s) => {
s.successAnimation.theme = true
})
}
2022-07-14 16:36:31 -07:00
return (
<div
2022-09-29 21:21:23 -07:00
className={`transition-all duration-300 ${
collapsed ? 'w-[64px]' : 'w-44 lg:w-48 xl:w-52'
2023-06-01 23:05:08 -07:00
} border-r border-th-bkg-3 ${
theme === 'Bonk'
2023-06-05 19:49:51 -07:00
? `bg-th-bkg-1 bg-[url('/images/themes/bonk/bonk-tile.png')] bg-repeat`
2023-06-01 23:05:08 -07:00
: 'bg-th-bkg-1'
}`}
2022-07-14 16:36:31 -07:00
>
2023-06-05 05:25:10 -07:00
{theme === 'Bonk' && !collapsed ? (
<img
className={`absolute bottom-16 h-auto w-full flex-shrink-0`}
2023-06-05 19:49:51 -07:00
onClick={() => playAnimation()}
src="/images/themes/bonk/sidenav-image.png"
2023-06-05 05:25:10 -07:00
alt="next"
/>
) : null}
<div className="flex min-h-screen flex-col justify-between">
2023-06-01 23:05:08 -07:00
<div className="mb-2">
2022-10-26 13:01:02 -07:00
<Link href={'/'} shallow={true} passHref legacyBehavior>
<div
2023-06-01 23:05:08 -07:00
className={`items-center transition-all duration-300 ease-in-out ${
collapsed ? '' : 'justify-start'
2023-06-01 23:05:08 -07:00
} pb-1 ${theme === 'Bonk' ? 'pl-3' : 'pl-4'}`}
>
2023-06-01 23:05:08 -07:00
<div
className={`flex h-16 flex-shrink-0 cursor-pointer items-center bg-th-bkg-1`}
>
2023-05-30 20:03:53 -07:00
{theme !== 'Bonk' ? (
<img
className={`h-8 w-8 flex-shrink-0`}
src="/logos/logo-mark.svg"
alt="next"
/>
) : (
<img
2023-06-01 23:05:08 -07:00
className={`h-10 w-10 flex-shrink-0`}
2023-06-05 19:49:51 -07:00
src="/images/themes/bonk/bonk-logo.png"
2023-05-30 20:03:53 -07:00
alt="next"
/>
)}
<Transition
show={!collapsed}
as={Fragment}
enter="transition ease-in duration-200"
enterFrom="opacity-50"
enterTo="opacity-100"
leave="transition ease-out duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
2023-06-01 23:05:08 -07:00
<span
className={`${
theme !== 'Bonk' ? 'ml-3' : 'ml-2'
} font-display text-lg text-th-fgd-1`}
>
{theme !== 'Bonk' ? 'Mango' : 'Bongo'}
</span>
</Transition>
</div>
2022-07-14 16:36:31 -07:00
</div>
</Link>
<div className="flex flex-col items-start">
<MenuItem
active={pathname === '/'}
collapsed={collapsed}
icon={<CurrencyDollarIcon className="h-5 w-5" />}
title={t('account')}
pagePath="/"
/>
<MenuItem
active={pathname === '/swap'}
collapsed={collapsed}
icon={<ArrowsRightLeftIcon className="h-5 w-5" />}
title={t('swap')}
pagePath="/swap"
/>
<MenuItem
active={pathname === '/trade'}
collapsed={collapsed}
2022-12-18 04:30:49 -08:00
icon={<ArrowTrendingUpIcon className="h-5 w-5" />}
title={t('trade')}
pagePath="/trade"
/>
2023-01-26 16:02:48 -08:00
<MenuItem
active={pathname === '/borrow'}
collapsed={collapsed}
icon={<BanknotesIcon className="h-5 w-5" />}
title={t('borrow')}
pagePath="/borrow"
/>
<MenuItem
active={pathname === '/stats'}
collapsed={collapsed}
icon={<ChartBarIcon className="h-5 w-5" />}
title={t('stats')}
pagePath="/stats"
/>
<MenuItem
active={pathname === '/settings'}
collapsed={collapsed}
icon={<Cog8ToothIcon className="h-5 w-5" />}
title={t('settings')}
pagePath="/settings"
/>
<ExpandableMenuItem
collapsed={collapsed}
icon={<EllipsisHorizontalIcon className="h-5 w-5" />}
title={t('more')}
>
2023-03-15 01:35:29 -07:00
<MenuItem
active={pathname === '/leaderboard'}
collapsed={false}
icon={<LeaderboardIcon className="h-5 w-5" />}
title={t('leaderboard')}
pagePath="/leaderboard"
hideIconBg
showTooltip={false}
/>
2023-01-10 04:56:48 -08:00
<MenuItem
active={pathname === '/search'}
collapsed={false}
icon={<MagnifyingGlassIcon className="h-5 w-5" />}
2023-01-10 18:46:18 -08:00
title={t('search:search-accounts')}
2023-01-10 04:56:48 -08:00
pagePath="/search"
hideIconBg
showTooltip={false}
/>
<MenuItem
2023-05-29 02:41:39 -07:00
active={pathname === '/governance/list'}
2023-01-10 04:56:48 -08:00
collapsed={false}
2023-04-05 15:48:06 -07:00
icon={<PlusCircleIcon className="h-5 w-5" />}
2023-05-28 23:02:16 -07:00
title={t('common:list-market-token')}
2023-05-29 02:41:39 -07:00
pagePath="/governance/list"
2023-01-10 04:56:48 -08:00
hideIconBg
showTooltip={false}
/>
<MenuItem
active={pathname === '/governance/vote'}
collapsed={false}
icon={<ArchiveBoxArrowDownIcon className="h-5 w-5" />}
title={t('common:vote')}
pagePath="/governance/vote"
hideIconBg
showTooltip={false}
/>
<MenuItem
collapsed={false}
icon={<LightBulbIcon className="h-5 w-5" />}
2023-03-08 11:24:46 -08:00
title={t('documentation')}
pagePath="https://docs.mango.markets"
hideIconBg
isExternal
showTooltip={false}
/>
<MenuItem
collapsed={false}
icon={<BuildingLibraryIcon className="h-5 w-5" />}
title={t('governance')}
pagePath="https://dao.mango.markets"
hideIconBg
isExternal
showTooltip={false}
/>
2023-03-08 11:24:46 -08:00
<MenuItem
collapsed={false}
icon={<NewspaperIcon className="h-5 w-5" />}
title={t('terms-of-use')}
pagePath="https://docs.mango.markets/legal"
hideIconBg
isExternal
showTooltip={false}
/>
</ExpandableMenuItem>
</div>
2022-07-14 16:36:31 -07:00
</div>
2023-06-05 05:25:10 -07:00
<div className="z-10 border-t border-th-bkg-3 bg-th-bkg-1">
<ExpandableMenuItem
collapsed={collapsed}
icon={
<HealthHeart
health={
group && mangoAccount
? mangoAccount.getHealthRatioUi(group, HealthType.maint)
: 0
}
size={32}
/>
}
2023-03-16 02:38:17 -07:00
panelTitle={mangoAccount?.name ? mangoAccount.name : t('account')}
title={
2022-10-08 01:53:47 -07:00
<div className="w-24 text-left">
<p className="mb-0.5 whitespace-nowrap text-xs">
{t('account')}
</p>
2022-10-08 01:53:47 -07:00
<p className="truncate whitespace-nowrap text-sm font-bold text-th-fgd-1">
{mangoAccount
? mangoAccount.name
: connected
? 'No Account'
: 'Connect'}
</p>
</div>
}
alignBottom
hideIconBg
>
<div className="px-4 py-2">
2022-10-05 17:04:16 -07:00
<MangoAccountSummary />
2022-08-02 19:15:17 -07:00
</div>
</ExpandableMenuItem>
</div>
2022-09-11 17:22:37 -07:00
</div>
2022-07-14 16:36:31 -07:00
</div>
2022-11-18 09:09:39 -08:00
)
2022-07-14 16:36:31 -07:00
}
export default SideNav
const MenuItem = ({
active,
collapsed,
icon,
title,
pagePath,
hideIconBg,
isExternal,
showTooltip = true,
2022-07-14 16:36:31 -07:00
}: {
active?: boolean
collapsed: boolean
2023-03-08 11:24:46 -08:00
icon?: ReactNode
2022-07-14 16:36:31 -07:00
title: string
pagePath: string
hideIconBg?: boolean
isExternal?: boolean
showTooltip?: boolean
2022-07-14 16:36:31 -07:00
}) => {
2022-12-02 03:28:46 -08:00
const { theme } = useTheme()
return (
2022-09-02 03:22:32 -07:00
<Tooltip content={title} placement="right" show={collapsed && showTooltip}>
2022-10-26 13:01:02 -07:00
<Link
href={pagePath}
shallow={true}
2023-04-19 18:12:45 -07:00
className={`flex cursor-pointer pl-4 focus:outline-none focus-visible:text-th-active md:hover:text-th-active ${
2022-12-02 03:28:46 -08:00
active
? 'text-th-active'
: theme === 'Light'
? 'text-th-fgd-3'
: 'text-th-fgd-2'
2022-11-18 09:09:39 -08:00
} ${hideIconBg ? 'py-1' : 'py-1.5 xl:py-2'}`}
2023-03-08 11:24:46 -08:00
target={isExternal ? '_blank' : ''}
rel={isExternal ? 'noopener noreferrer' : ''}
2022-11-18 09:09:39 -08:00
>
2023-03-08 11:24:46 -08:00
<div className="flex w-full items-center">
2022-10-26 13:01:02 -07:00
<div className="flex items-center">
2023-03-08 11:24:46 -08:00
{icon ? (
<div
className={
hideIconBg
? ''
: `flex h-8 w-8 items-center justify-center rounded-full ${
2023-06-01 23:05:08 -07:00
theme === 'Light'
? 'bg-th-bkg-2'
: theme === 'Bonk'
? 'bg-th-button'
: 'bg-th-bkg-3'
2023-03-08 11:24:46 -08:00
}`
}
>
{icon}
</div>
) : null}
2022-10-26 13:01:02 -07:00
<Transition
show={!collapsed}
as={Fragment}
enter="transition ease-in duration-300"
enterFrom="opacity-50"
enterTo="opacity-100"
leave="transition ease-out duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<span className="ml-3 xl:text-base">{title}</span>
</Transition>
2022-07-14 16:36:31 -07:00
</div>
2022-10-26 13:01:02 -07:00
{isExternal ? (
2023-03-08 11:24:46 -08:00
<ArrowTopRightOnSquareIcon className="ml-2 h-3 w-3" />
2022-10-26 13:01:02 -07:00
) : null}
</div>
</Link>
</Tooltip>
2022-11-18 09:09:39 -08:00
)
2022-07-14 16:36:31 -07:00
}
2022-09-12 08:53:57 -07:00
export const ExpandableMenuItem = ({
2022-07-14 16:36:31 -07:00
alignBottom,
children,
collapsed,
hideIconBg,
icon,
panelTitle,
2022-07-14 16:36:31 -07:00
title,
}: {
alignBottom?: boolean
children: ReactNode
collapsed: boolean
hideIconBg?: boolean
icon: ReactNode
panelTitle?: string
2022-07-14 16:36:31 -07:00
title: string | ReactNode
}) => {
2022-12-02 03:28:46 -08:00
const { theme } = useTheme()
2022-07-14 16:36:31 -07:00
return collapsed ? (
<Popover className={`relative z-30 ${alignBottom ? '' : 'py-2 pl-4'}`}>
<Popover.Button
className={`${theme === 'Light' ? 'text-th-fgd-3' : 'text-th-fgd-2'} ${
alignBottom
? 'focus-visible:bg-th-bkg-3'
: 'focus-visible:text-th-active'
} md:hover:text-th-active`}
2022-07-14 16:36:31 -07:00
>
<div
className={` ${
hideIconBg
? ''
: `flex h-8 w-8 items-center justify-center rounded-full ${
2023-06-01 23:05:08 -07:00
theme === 'Light'
? 'bg-th-bkg-2'
: theme === 'Bonk'
? 'bg-th-button'
: 'bg-th-bkg-3'
}`
} ${
alignBottom
2023-04-19 18:12:45 -07:00
? 'flex h-[64px] w-[64px] items-center justify-center hover:bg-th-bkg-2'
: ''
}`}
2022-07-14 16:36:31 -07:00
>
{icon}
</div>
</Popover.Button>
<Popover.Panel
className={`absolute left-[64px] z-20 w-56 rounded-md rounded-l-none bg-th-bkg-1 focus:outline-none ${
alignBottom
? 'bottom-0 rounded-b-none border-b-0 p-0'
: 'top-1/2 -translate-y-1/2'
}`}
>
<div
className={`rounded-md rounded-l-none bg-th-bkg-2 ${
alignBottom ? 'pt-4 pb-2' : 'py-2'
}`}
>
<div className="flex items-center justify-between pl-4 pr-2">
{panelTitle ? (
<h3 className="text-sm font-bold">{panelTitle}</h3>
) : null}
2022-07-14 16:36:31 -07:00
</div>
{children}
</div>
</Popover.Panel>
2022-07-14 16:36:31 -07:00
</Popover>
) : (
<Disclosure>
{({ open }) => (
<>
2023-03-27 21:30:04 -07:00
<Disclosure.Button
2023-04-19 18:12:45 -07:00
className={`flex h-full w-full items-center justify-between rounded-none px-4 py-2 focus-visible:text-th-active md:hover:text-th-active ${
2022-11-20 15:35:59 -08:00
alignBottom
? 'h-[64px] focus-visible:bg-th-bkg-3 md:hover:bg-th-bkg-2'
2023-03-27 21:30:04 -07:00
: ''
}`}
>
2023-03-27 21:30:04 -07:00
<div className="flex items-center">
<div
className={
hideIconBg
? ''
2023-06-01 23:05:08 -07:00
: `flex h-8 w-8 items-center justify-center rounded-full ${
theme === 'Bonk' ? 'bg-th-button' : 'bg-th-bkg-3'
}`
2023-03-27 21:30:04 -07:00
}
>
{icon}
</div>
2023-03-27 21:30:04 -07:00
<Transition
appear={true}
show={!collapsed}
as={Fragment}
enter="transition ease-in duration-300"
enterFrom="opacity-50"
enterTo="opacity-100"
leave="transition ease-out duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<span className="ml-3 truncate xl:text-base">{title}</span>
</Transition>
2022-07-14 16:36:31 -07:00
</div>
2023-03-27 21:30:04 -07:00
<ChevronDownIcon
className={`${
open ? 'rotate-180' : 'rotate-360'
} h-5 w-5 flex-shrink-0`}
/>
</Disclosure.Button>
<Transition
as={Fragment}
enter="transition-all ease-in duration-300"
enterFrom="opacity-100 max-h-0"
enterTo="opacity-100 max-h-80"
leave="transition-all ease-out duration-300"
leaveFrom="opacity-100 max-h-80"
leaveTo="opacity-0 max-h-0"
>
<Disclosure.Panel className="w-full overflow-hidden">
<div className={`${!alignBottom ? 'ml-1.5' : ''}`}>
{children}
</div>
</Disclosure.Panel>
</Transition>
</>
)}
2022-07-14 16:36:31 -07:00
</Disclosure>
)
}