add mobile nav
This commit is contained in:
parent
c4c8cb60f8
commit
12cb4c3666
|
@ -0,0 +1,171 @@
|
||||||
|
import { ReactNode, useState } from 'react'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { ChartBarIcon, HomeIcon, MenuIcon, XIcon } from '@heroicons/react/solid'
|
||||||
|
import TradeIcon from '../icons/TradeIcon'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
import { IconButton } from '../shared/Button'
|
||||||
|
import {
|
||||||
|
CashIcon,
|
||||||
|
ChevronRightIcon,
|
||||||
|
CurrencyDollarIcon as FeesIcon,
|
||||||
|
LightBulbIcon,
|
||||||
|
} from '@heroicons/react/solid'
|
||||||
|
|
||||||
|
const StyledBarItemLabel = ({
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: {
|
||||||
|
children: ReactNode
|
||||||
|
}) => (
|
||||||
|
<div style={{ fontSize: '0.6rem', lineHeight: 1 }} {...props}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
const BottomBar = () => {
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
const { asPath } = useRouter()
|
||||||
|
const [showPanel, setShowPanel] = useState(false)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="default-transition grid grid-cols-4 grid-rows-1 bg-th-bkg-2 py-2.5">
|
||||||
|
<Link
|
||||||
|
href={{
|
||||||
|
pathname: '/',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
className={`${
|
||||||
|
asPath === '/' ? 'text-th-primary' : 'text-th-fgd-3'
|
||||||
|
} default-transition col-span-1 flex cursor-pointer flex-col items-center`}
|
||||||
|
>
|
||||||
|
<HomeIcon className="mb-1 h-4 w-4" />
|
||||||
|
<StyledBarItemLabel>{t('portfolio')}</StyledBarItemLabel>
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href={{
|
||||||
|
pathname: '/trade',
|
||||||
|
}}
|
||||||
|
shallow={true}
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
className={`${
|
||||||
|
asPath === '/trade' ? 'text-th-primary' : 'text-th-fgd-3'
|
||||||
|
} default-transition col-span-1 flex cursor-pointer flex-col items-center`}
|
||||||
|
>
|
||||||
|
<TradeIcon className="mb-1 h-4 w-4" />
|
||||||
|
<StyledBarItemLabel>{t('trade')}</StyledBarItemLabel>
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
<Link href="/stats" shallow={true}>
|
||||||
|
<a
|
||||||
|
className={`${
|
||||||
|
asPath === '/stats' ? 'text-th-primary' : 'text-th-fgd-3'
|
||||||
|
} default-transition col-span-1 flex cursor-pointer flex-col items-center`}
|
||||||
|
>
|
||||||
|
<ChartBarIcon className="mb-1 h-4 w-4" />
|
||||||
|
<StyledBarItemLabel>{t('stats')}</StyledBarItemLabel>
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
<a
|
||||||
|
className={`${
|
||||||
|
showPanel ? 'text-th-primary' : 'text-th-fgd-3'
|
||||||
|
} default-transition col-span-1 flex cursor-pointer flex-col items-center`}
|
||||||
|
onClick={() => setShowPanel(!showPanel)}
|
||||||
|
>
|
||||||
|
<MenuIcon className="mb-1 h-4 w-4" />
|
||||||
|
<StyledBarItemLabel>{t('more')}</StyledBarItemLabel>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<MoreMenuPanel showPanel={showPanel} setShowPanel={setShowPanel} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BottomBar
|
||||||
|
|
||||||
|
const MoreMenuPanel = ({
|
||||||
|
showPanel,
|
||||||
|
setShowPanel,
|
||||||
|
}: {
|
||||||
|
showPanel: boolean
|
||||||
|
setShowPanel: (showPanel: boolean) => void
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`fixed bottom-0 z-30 h-96 w-full transform overflow-hidden bg-th-bkg-2 px-4 transition-all duration-700 ease-in-out ${
|
||||||
|
showPanel ? 'translate-y-0' : 'translate-y-full'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="flex justify-end py-4">
|
||||||
|
<IconButton onClick={() => setShowPanel(false)} hideBg>
|
||||||
|
<XIcon className="h-5 w-5" />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="border-b border-th-bkg-4"
|
||||||
|
onClick={() => setShowPanel(false)}
|
||||||
|
>
|
||||||
|
<MoreMenuItem
|
||||||
|
title={t('borrow')}
|
||||||
|
path="/borrow"
|
||||||
|
icon={<CashIcon className="h-5 w-5" />}
|
||||||
|
/>
|
||||||
|
<MoreMenuItem
|
||||||
|
title={t('fees')}
|
||||||
|
path="/fees"
|
||||||
|
icon={<FeesIcon className="h-5 w-5" />}
|
||||||
|
/>
|
||||||
|
<MoreMenuItem
|
||||||
|
title={t('learn')}
|
||||||
|
path="https://docs.mango.markets/"
|
||||||
|
icon={<LightBulbIcon className="h-5 w-5" />}
|
||||||
|
isExternal
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const MoreMenuItem = ({
|
||||||
|
title,
|
||||||
|
path,
|
||||||
|
icon,
|
||||||
|
isExternal,
|
||||||
|
}: {
|
||||||
|
title: string
|
||||||
|
path: string
|
||||||
|
icon: ReactNode
|
||||||
|
isExternal?: boolean
|
||||||
|
}) => {
|
||||||
|
const classNames =
|
||||||
|
'default-transition flex w-full items-center justify-between border-t border-th-bkg-4 px-2 py-3 text-th-fgd-2 hover:text-th-fgd-1'
|
||||||
|
return isExternal ? (
|
||||||
|
<a
|
||||||
|
className={classNames}
|
||||||
|
href={path}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<div className="flex items-center">
|
||||||
|
{icon}
|
||||||
|
<span className="ml-1.5">{title}</span>
|
||||||
|
</div>
|
||||||
|
<ChevronRightIcon className="h-5 w-5" />
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<Link href={path} shallow={true}>
|
||||||
|
<a className={classNames}>
|
||||||
|
<div className="flex items-center">
|
||||||
|
{icon}
|
||||||
|
<span className="ml-1.5">{title}</span>
|
||||||
|
</div>
|
||||||
|
<ChevronRightIcon className="h-5 w-5" />
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import MangoAccountSummary from '../account/MangoAccountSummary'
|
||||||
import { HealthType, MangoAccount } from '@blockworks-foundation/mango-v4'
|
import { HealthType, MangoAccount } from '@blockworks-foundation/mango-v4'
|
||||||
import mangoStore from '../../store/state'
|
import mangoStore from '../../store/state'
|
||||||
import HealthHeart from '../account/HealthHeart'
|
import HealthHeart from '../account/HealthHeart'
|
||||||
|
import BottomBar from '../mobile/BottomBar'
|
||||||
|
|
||||||
const Layout = ({ children }: { children: ReactNode }) => {
|
const Layout = ({ children }: { children: ReactNode }) => {
|
||||||
const mangoAccount = mangoStore((s) => s.mangoAccount)
|
const mangoAccount = mangoStore((s) => s.mangoAccount)
|
||||||
|
@ -26,9 +27,10 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
||||||
const { connected } = useWallet()
|
const { connected } = useWallet()
|
||||||
const [isCollapsed, setIsCollapsed] = useState(false)
|
const [isCollapsed, setIsCollapsed] = useState(false)
|
||||||
const { width } = useViewport()
|
const { width } = useViewport()
|
||||||
|
const isMobile = width ? width < breakpoints.md : false
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const collapsed = width ? width < breakpoints.lg : false
|
const collapsed = width ? width < breakpoints.xl : false
|
||||||
setIsCollapsed(collapsed)
|
setIsCollapsed(collapsed)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
@ -39,9 +41,16 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(width)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`flex-grow bg-th-bkg-1 text-th-fgd-1 transition-all`}>
|
<div className={`flex-grow bg-th-bkg-1 text-th-fgd-1 transition-all`}>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
|
{isMobile ? (
|
||||||
|
<div className="fixed bottom-0 left-0 z-20 w-full md:hidden">
|
||||||
|
<BottomBar />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<div className={`fixed z-20 h-screen`}>
|
<div className={`fixed z-20 h-screen`}>
|
||||||
<button
|
<button
|
||||||
|
@ -54,14 +63,17 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<div className={`h-full ${!isCollapsed ? 'overflow-y-auto' : ''}`}>
|
<div
|
||||||
|
className={`h-full ${!isCollapsed ? 'overflow-y-auto' : ''}`}
|
||||||
|
>
|
||||||
<SideNav collapsed={isCollapsed} />
|
<SideNav collapsed={isCollapsed} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<div
|
<div
|
||||||
className={`w-full overflow-hidden transition-all duration-500 ease-in-out ${
|
className={`w-full overflow-hidden transition-all duration-500 ease-in-out ${
|
||||||
isCollapsed ? 'pl-20' : 'pl-44 lg:pl-56'
|
isMobile ? '' : isCollapsed ? 'pl-[72px]' : 'pl-44 lg:pl-56'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="flex h-16 items-center justify-between border-b border-th-bkg-3 bg-th-bkg-1 px-6">
|
<div className="flex h-16 items-center justify-between border-b border-th-bkg-3 bg-th-bkg-1 px-6">
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { ThemeProvider } from 'next-themes'
|
||||||
import { TOKEN_LIST_URL } from '@jup-ag/core'
|
import { TOKEN_LIST_URL } from '@jup-ag/core'
|
||||||
import { appWithTranslation } from 'next-i18next'
|
import { appWithTranslation } from 'next-i18next'
|
||||||
import Layout from '../components/shared/Layout'
|
import Layout from '../components/shared/Layout'
|
||||||
|
import { ViewportProvider } from '../hooks/useViewport'
|
||||||
|
|
||||||
const hydrateStore = async () => {
|
const hydrateStore = async () => {
|
||||||
const actions = mangoStore.getState().actions
|
const actions = mangoStore.getState().actions
|
||||||
|
@ -79,9 +80,11 @@ function MyApp({ Component, pageProps }: AppProps) {
|
||||||
<WalletModalProvider>
|
<WalletModalProvider>
|
||||||
<WalletListener />
|
<WalletListener />
|
||||||
<ThemeProvider defaultTheme="Mango">
|
<ThemeProvider defaultTheme="Mango">
|
||||||
|
<ViewportProvider>
|
||||||
<Layout>
|
<Layout>
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
</Layout>
|
</Layout>
|
||||||
|
</ViewportProvider>
|
||||||
<Notifications />
|
<Notifications />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</WalletModalProvider>
|
</WalletModalProvider>
|
||||||
|
|
Loading…
Reference in New Issue