Compare commits

...

7 Commits

Author SHA1 Message Date
Linkie Link
51916683ac
feat: added ChartLoading component 2023-11-24 10:32:54 +01:00
Linkie Link
160165aa22
Merge branch 'develop' of https://github.com/mars-protocol/mars-v2-frontend into stats-page
# Conflicts:
#	src/components/Routes.tsx
#	src/utils/route.ts
2023-11-24 09:40:57 +01:00
Linkie Link
e3d3d30700
feat: added a first Chart component 2023-11-22 17:01:25 +01:00
Linkie Link
ca9e608952
fix: fixed the build 2023-11-22 15:54:44 +01:00
Linkie Link
d414e38b88
fix: color adjustments 2023-11-22 15:11:17 +01:00
Linkie Link
31eceeb9fb
feat: added additional metric cards 2023-11-22 15:10:25 +01:00
Linkie Link
61c64aa724
feat: first preparations for stats 2023-11-22 12:13:32 +01:00
28 changed files with 496 additions and 25 deletions

View File

@ -37,7 +37,7 @@ import {
export default function AccountDetailsController() {
const address = useStore((s) => s.address)
const isHLS = useStore((s) => s.isHLS)
const currentAppSection = useStore((s) => s.currentAppSection)
const { data: accounts, isLoading } = useAccounts('default', address)
const { data: accountIds } = useAccountIds(address, false)
const accountId = useAccountId()
@ -46,7 +46,7 @@ export default function AccountDetailsController() {
const focusComponent = useStore((s) => s.focusComponent)
const isOwnAccount = accountId && accountIds?.includes(accountId)
if (!address || focusComponent || !isOwnAccount || isHLS) return null
if (!address || focusComponent || !isOwnAccount || currentAppSection !== 'app') return null
if ((isLoading && accountId && !focusComponent) || !account) return <Skeleton />

View File

@ -1,6 +1,6 @@
import classNames from 'classnames'
import { useEffect, useMemo, useState } from 'react'
import { useLocation } from 'react-router-dom'
import { useEffect, useMemo } from 'react'
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
import { LocalStorageKeys } from 'constants/localStorageKeys'
@ -13,13 +13,41 @@ export default function Background() {
LocalStorageKeys.REDUCE_MOTION,
DEFAULT_SETTINGS.reduceMotion,
)
const [backgroundClasses, setBackgroundClasses] = useState<string[]>([
'bg-body',
'bg-orb-primary',
'bg-orb-secondary',
'bg-orb-tertiary',
])
const { pathname } = useLocation()
const page = getPage(pathname)
const isHLS = useMemo(() => page.split('-')[0] === 'hls', [page])
const currentAppSection = useMemo(() => {
switch (page.split('-')[0]) {
case 'hls':
setBackgroundClasses([
'bg-body-hls',
'bg-orb-primary-hls',
'bg-orb-secondary-hls',
'bg-orb-tertiary-hls',
])
return 'hls'
case 'stats':
setBackgroundClasses([
'bg-body',
'bg-orb-primary-stats',
'bg-orb-secondary-stats',
'bg-orb-tertiary-stats',
])
return 'stats'
default:
setBackgroundClasses(['bg-body', 'bg-orb-primary', 'bg-orb-secondary', 'bg-orb-tertiary'])
return 'app'
}
}, [page])
useEffect(() => {
useStore.setState({ isHLS })
}, [isHLS])
useStore.setState({ currentAppSection })
}, [currentAppSection])
return (
<div
@ -27,7 +55,7 @@ export default function Background() {
'fixed inset-0',
'w-full h-full',
'overflow-hidden pointer-events-none background ',
isHLS ? 'bg-body-hls' : 'bg-body',
backgroundClasses[0],
!reduceMotion && 'transition-bg duration-1000 delay-300',
)}
>
@ -39,7 +67,7 @@ export default function Background() {
'max-h-[500px] max-w-[500px]',
'left-[-10vw] top-[-10vw]',
'blur-orb-primary',
isHLS ? ' bg-orb-primary-hls' : 'bg-orb-primary',
backgroundClasses[1],
'translate-x-0 translate-y-0 rounded-full opacity-20',
!reduceMotion && 'animate-[float_120s_ease-in-out_infinite_2s]',
!reduceMotion && 'transition-bg duration-1000 delay-300',
@ -53,7 +81,7 @@ export default function Background() {
'max-h-[1000px] max-w-[1000px]',
'bottom-[-20vw] right-[-10vw]',
'blur-orb-secondary',
isHLS ? ' bg-orb-secondary-hls' : 'bg-orb-secondary',
backgroundClasses[2],
'translate-x-0 translate-y-0 rounded-full opacity-30',
!reduceMotion && 'transition-bg duration-1000 delay-300',
)}
@ -66,7 +94,7 @@ export default function Background() {
'max-h-[600px] max-w-[600px]',
'right-[-4vw] top-[-10vw]',
'blur-orb-tertiary ',
isHLS ? ' bg-orb-tertiary-hls' : 'bg-orb-tertiary',
backgroundClasses[3],
'translate-x-0 translate-y-0 rounded-full opacity-20',
!reduceMotion && 'animate-[float_180s_ease-in_infinite]',
!reduceMotion && 'transition-bg duration-1000 delay-300',

View File

@ -0,0 +1,117 @@
import classNames from 'classnames'
import moment from 'moment'
import {
Area,
AreaChart,
CartesianGrid,
ResponsiveContainer,
Tooltip,
XAxis,
YAxis,
} from 'recharts'
import Text from 'components/Text'
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
import { LocalStorageKeys } from 'constants/localStorageKeys'
import useLocalStorage from 'hooks/useLocalStorage'
import { formatValue } from 'utils/formatters'
interface Props {
data: ChartData
height?: number
}
export default function ChartBody(props: Props) {
const [reduceMotion] = useLocalStorage<boolean>(
LocalStorageKeys.REDUCE_MOTION,
DEFAULT_SETTINGS.reduceMotion,
)
const height = props.height ?? 400
return (
<div className={`-ml-6 h-[${height}px] w-full`}>
<ResponsiveContainer width='100%' height='100%'>
<AreaChart
data={props.data}
margin={{
top: 0,
right: 0,
left: 0,
bottom: 0,
}}
>
<defs>
<linearGradient id='chartGradient' x1='0' y1='0' x2='0' y2='1'>
<stop offset='0%' stopColor={'#AB47BC'} stopOpacity={0.3} />
<stop offset='100%' stopColor={'#AB47BC'} stopOpacity={0.02} />
</linearGradient>
</defs>
<CartesianGrid
horizontal={false}
stroke='rgba(255,255,255,0.1)'
strokeDasharray='6 3'
syncWithTicks={true}
/>
<XAxis
stroke='rgba(255, 255, 255, 0.4)'
tickFormatter={(value) => {
return moment(value).format('DD MMM')
}}
padding={{ left: 10, right: 20 }}
axisLine={false}
tickLine={false}
fontSize={12}
dataKey='date'
dy={10}
/>
<YAxis
axisLine={false}
tickLine={false}
fontSize={12}
stroke='rgba(255, 255, 255, 0.4)'
tickFormatter={(value) => {
return formatValue(value, {
minDecimals: 0,
maxDecimals: 0,
prefix: '$',
abbreviated: true,
})
}}
/>
<Tooltip
cursor={false}
isAnimationActive={!reduceMotion}
wrapperStyle={{ outline: 'none' }}
content={({ payload, label }) => {
if (payload && payload.length) {
const value = Number(payload[0].value) ?? 0
return (
<div
className={classNames(
'max-w-[320px] rounded-lg px-4 py-2 isolate bg-black/5 backdrop-blur',
'before:content-[" "] before:absolute before:inset-0 before:-z-1 before:rounded-sm before:p-[1px] before:border-glas',
)}
>
<Text size='sm' className='text-white/60'>
{moment(label).format('DD MMM YYYY')}
</Text>
<Text size='sm'>
{formatValue(value, { minDecimals: 0, maxDecimals: 0, prefix: '$' })}
</Text>
</div>
)
}
}}
/>
<Area
type='monotone'
dataKey='value'
stroke='#AB47BC'
fill='url(#chartGradient)'
isAnimationActive={!reduceMotion}
/>
</AreaChart>
</ResponsiveContainer>
</div>
)
}

View File

@ -0,0 +1,93 @@
import moment from 'moment'
import { Area, AreaChart, CartesianGrid, ResponsiveContainer, XAxis, YAxis } from 'recharts'
import classNames from 'classnames'
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
import { LocalStorageKeys } from 'constants/localStorageKeys'
import useLocalStorage from 'hooks/useLocalStorage'
interface Props {
height?: number
}
function createLoadingData() {
const data = []
const dataValues = [0, 20, 40, 30, 60, 50, 100]
const startDate = moment().subtract(7, 'days')
const endDate = moment()
const days = endDate.diff(startDate, 'days')
for (let i = 0; i < days; i++) {
const date = moment(startDate).add(i, 'days')
data.push({
date: date.format('YYYY-MM-DD'),
value: dataValues[i],
})
}
return data
}
export default function Chart(props: Props) {
const [reduceMotion] = useLocalStorage<boolean>(
LocalStorageKeys.REDUCE_MOTION,
DEFAULT_SETTINGS.reduceMotion,
)
const height = props.height ?? 400
const loadingData = createLoadingData()
return (
<div className={classNames(`-ml-6 h-[${height}px] w-full`, !reduceMotion && 'animate-pulse')}>
<ResponsiveContainer width='100%' height='100%'>
<AreaChart
data={loadingData}
margin={{
top: 0,
right: 0,
left: 0,
bottom: 0,
}}
>
<defs>
<linearGradient id='chartGradient' x1='0' y1='0' x2='0' y2='1'>
<stop offset='0%' stopColor={'#FFF'} stopOpacity={0.3} />
<stop offset='100%' stopColor={'#FFF'} stopOpacity={0.02} />
</linearGradient>
</defs>
<CartesianGrid
horizontal={false}
stroke='rgba(255,255,255,0.2)'
strokeDasharray='6 3'
syncWithTicks={true}
/>
<XAxis
stroke='rgba(255, 255, 255, 0.3)'
tickFormatter={() => {
return '...'
}}
padding={{ left: 10, right: 20 }}
axisLine={false}
tickLine={false}
fontSize={12}
dataKey='date'
dy={10}
/>
<YAxis
axisLine={false}
tickLine={false}
fontSize={12}
stroke='rgba(255, 255, 255, 0.5)'
tickFormatter={() => {
return '...'
}}
/>
<Area
type='monotone'
dataKey='value'
stroke='rgba(255, 255, 255, 0.3)'
fill='url(#chartGradient)'
isAnimationActive={!reduceMotion}
/>
</AreaChart>
</ResponsiveContainer>
</div>
)
}

View File

@ -0,0 +1,16 @@
import Card from 'components/Card'
import ChartBody from 'components/Chart/ChartBody'
import ChartLoading from 'components/Chart/ChartLoading'
interface Props {
data: ChartData | null
title: string
}
export default function Chart(props: Props) {
return (
<Card className='w-full' title={props.title} contentClassName='p-4 pr-0'>
{props.data === null ? <ChartLoading /> : <ChartBody data={props.data} />}
</Card>
)
}

View File

@ -18,6 +18,7 @@ interface Props {
isApproximation?: boolean
parentheses?: boolean
showZero?: boolean
abbreviated?: boolean
}
export default function DisplayCurrency(props: Props) {
@ -70,7 +71,7 @@ export default function DisplayCurrency(props: Props) {
options={{
minDecimals: isUSD ? 2 : 0,
maxDecimals: 2,
abbreviated: true,
abbreviated: props.abbreviated ?? true,
prefix,
suffix,
}}

View File

@ -10,6 +10,7 @@ const underlineClasses =
interface Props {
tabs: Tab[]
activeTabIdx: number
className?: string
}
export default function Tab(props: Props) {
@ -17,7 +18,7 @@ export default function Tab(props: Props) {
const { address } = useParams()
return (
<div className='relative w-full'>
<div className={classNames(props.className, 'relative w-full')}>
{props.tabs.map((tab, index) => (
<NavLink
key={tab.page}

View File

@ -21,6 +21,7 @@ export const menuTree = (walletId: WalletID): MenuTreeEntry[] => [
{ pages: ['borrow'], label: 'Borrow' },
...(ENABLE_HLS ? [{ pages: ['hls-staking'] as Page[], label: 'High Leverage' }] : []),
{ pages: ['portfolio'], label: 'Portfolio' },
{ pages: ['stats'], label: 'Statistics' },
{ pages: ['governance'], label: 'Governance', externalUrl: getGovernanceUrl(walletId) },
]
@ -28,7 +29,7 @@ export default function DesktopHeader() {
const address = useStore((s) => s.address)
const focusComponent = useStore((s) => s.focusComponent)
const isOracleStale = useStore((s) => s.isOracleStale)
const isHLS = useStore((s) => s.isHLS)
const currentAppSection = useStore((s) => s.currentAppSection)
const accountId = useAccountId()
function handleCloseFocusMode() {
@ -63,7 +64,7 @@ export default function DesktopHeader() {
<div className='flex gap-4'>
{isOracleStale && <OracleResyncButton />}
{accountId && <RewardsCenter />}
{address && !isHLS && <AccountMenu />}
{address && currentAppSection === 'app' && <AccountMenu />}
<Wallet />
<Settings />
</div>

View File

@ -32,13 +32,13 @@ function IntroBackground(props: { bg: Props['bg'] }) {
export default function Intro(props: Props) {
const showTutorial = useStore((s) => s.tutorial)
const isHLS = useStore((s) => s.isHLS)
const currentAppSection = useStore((s) => s.currentAppSection)
if (!showTutorial) return null
return (
<Card
className={classNames(
'relative w-full p-8 bg-cover h-55',
isHLS ? 'bg-intro-hls' : 'bg-intro',
currentAppSection === 'hls' ? 'bg-intro-hls' : 'bg-intro',
)}
contentClassName='flex w-full h-full flex-col justify-between'
>

View File

@ -81,6 +81,8 @@ export default function RewardsCenter() {
}
}, [accountId, claimTx])
if (totalRewardsCoin.amount.isZero()) return null
return (
<div className={'relative'}>
<Button

View File

@ -1,6 +1,5 @@
import { Navigate, Outlet, Route, Routes as RoutesWrapper } from 'react-router-dom'
import Layout from 'pages/_layout'
import BorrowPage from 'pages/BorrowPage'
import FarmPage from 'pages/FarmPage'
import HLSFarmPage from 'pages/HLSFarmPage'
@ -10,9 +9,10 @@ import MobilePage from 'pages/MobilePage'
import PerpsPage from 'pages/PerpsPage'
import PortfolioAccountPage from 'pages/PortfolioAccountPage'
import PortfolioPage from 'pages/PortfolioPage'
import StatsPage from 'pages/StatsPage'
import TradePage from 'pages/TradePage'
import { ENABLE_PERPS } from 'utils/constants'
import { ENABLE_HLS } from 'utils/constants'
import Layout from 'pages/_layout'
import { ENABLE_HLS, ENABLE_PERPS } from 'utils/constants'
export default function Routes() {
return (
@ -33,6 +33,10 @@ export default function Routes() {
<Route path='/mobile' element={<MobilePage />} />
{ENABLE_HLS && <Route path='/hls-staking' element={<HLSStakingPage />} />}
{ENABLE_HLS && <Route path='/hls-farm' element={<HLSFarmPage />} />}
<Route path='/stats' element={<StatsPage />} />
<Route path='/stats-farm' element={<StatsPage />} />
<Route path='/stats-lend-borrow' element={<StatsPage />} />
<Route path='/stats-additional' element={<StatsPage />} />
<Route path='/' element={<TradePage />} />
<Route path='/wallets/:address'>
<Route path='trade' element={<TradePage />} />
@ -43,6 +47,10 @@ export default function Routes() {
<Route path='portfolio' element={<PortfolioPage />} />
{ENABLE_HLS && <Route path='hls-staking' element={<HLSStakingPage />} />}
{ENABLE_HLS && <Route path='hls-farm' element={<HLSFarmPage />} />}
<Route path='stats' element={<StatsPage />} />
<Route path='stats-farm' element={<StatsPage />} />
<Route path='stats-lend-borrow' element={<StatsPage />} />
<Route path='stats-additional' element={<StatsPage />} />
<Route path='portfolio/:accountId'>
<Route path='' element={<PortfolioAccountPage />} />
</Route>

View File

@ -0,0 +1,41 @@
import { useMemo } from 'react'
import DisplayCurrency from 'components/DisplayCurrency'
import { FormattedNumber } from 'components/FormattedNumber'
import StatsCardsSkeleton from 'components/Stats/StatsCardsSkeleton'
import { ORACLE_DENOM } from 'constants/oracle'
import { BNCoin } from 'types/classes/BNCoin'
import { DEFAULT_ADDITIONAL_STATS } from 'utils/constants'
export default function StatsAdditional() {
const stats = useMemo(() => {
const totalTvl = new BNCoin({ denom: ORACLE_DENOM, amount: '121345123.67' })
const totalAccounts = 52134
const totalFees = new BNCoin({ denom: ORACLE_DENOM, amount: '321230.34' })
return [
{
head: DEFAULT_ADDITIONAL_STATS[0].head,
title: <DisplayCurrency className='text-xl' coin={totalTvl} abbreviated={false} />,
sub: DEFAULT_ADDITIONAL_STATS[0].sub,
},
{
head: DEFAULT_ADDITIONAL_STATS[1].head,
title: (
<FormattedNumber
className='text-xl'
amount={totalAccounts}
options={{ maxDecimals: 0, minDecimals: 0, abbreviated: false }}
/>
),
sub: DEFAULT_ADDITIONAL_STATS[1].sub,
},
{
head: DEFAULT_ADDITIONAL_STATS[2].head,
title: <DisplayCurrency className='text-xl' coin={totalFees} abbreviated={false} />,
sub: DEFAULT_ADDITIONAL_STATS[2].sub,
},
]
}, [])
return <StatsCardsSkeleton stats={stats} />
}

View File

@ -0,0 +1,38 @@
import React from 'react'
import Card from 'components/Card'
import Loading from 'components/Loading'
import Text from 'components/Text'
import TitleAndSubCell from 'components/TitleAndSubCell'
import { DEFAULT_ADDITIONAL_STATS } from 'utils/constants'
interface Props {
stats?: Stat[]
}
interface Stat {
head: string
title: React.ReactNode | null
sub: string
}
export default function StatsCardsSkeleton(props: Props) {
const stats = props.stats || DEFAULT_ADDITIONAL_STATS
return (
<div className='grid w-full grid-cols-3 gap-4'>
{stats.map((stat) => (
<Card key={stat.sub} className='p-6 bg-white/5 flex-grow-1'>
<Text size='sm' className='mb-2 text-white/60'>
{stat.head}
</Text>
<TitleAndSubCell
title={stat.title || <Loading className='w-20 h-6 mx-auto mb-2' />}
sub={stat.sub}
className='mb-1'
/>
</Card>
))}
</div>
)
}

View File

@ -0,0 +1,3 @@
export default function StatsFarm() {
return <div className='flex-1'>Stats Farm</div>
}

View File

@ -0,0 +1,3 @@
export default function StatsLendAndBorrow() {
return <div className='flex-1'>Stats Lend &amp; Borrow</div>
}

View File

@ -0,0 +1,44 @@
import { useEffect, useState } from 'react'
import Chart from 'components/Chart'
export default function StatsTrading() {
const [totalSwapVolume, setTotalSwapVolume] = useState<ChartData | null>(null)
useEffect(() => {
setTimeout(() => {
setTotalSwapVolume([
{
date: '2023-11-15',
value: 2501271,
},
{
date: '2023-11-16',
value: 2804718,
},
{
date: '2023-11-17',
value: 4901520,
},
{
date: '2023-11-18',
value: 6500000,
},
{
date: '2023-11-19',
value: 7486720,
},
{
date: '2023-11-20',
value: 8412721,
},
{
date: '2023-11-21',
value: 10432321,
},
])
}, 6000)
})
return <Chart title='Total Swap Volume' data={totalSwapVolume} />
}

View File

@ -7,3 +7,10 @@ export const HLS_TABS: Tab[] = [
{ page: 'hls-staking', name: 'Staking' },
{ page: 'hls-farm', name: 'Farm' },
]
export const STATS_TABS: Tab[] = [
{ page: 'stats', name: 'Trading' },
{ page: 'stats-farm', name: 'Farm' },
{ page: 'stats-lend-borrow', name: 'Lend & Borrow' },
{ page: 'stats-additional', name: 'Additional' },
]

37
src/pages/StatsPage.tsx Normal file
View File

@ -0,0 +1,37 @@
import { useLocation } from 'react-router-dom'
import Tab from 'components/Earn/Tab'
import MigrationBanner from 'components/MigrationBanner'
import StatsAccounts from 'components/Stats/StatsAdditional'
import StatsFarm from 'components/Stats/StatsFarm'
import StatsLendAndBorrow from 'components/Stats/StatsLendAndBorrow'
import StatsTrading from 'components/Stats/StatsTrading'
import { STATS_TABS } from 'constants/pages'
import { getPage } from 'utils/route'
function getStatsComponent(page: Page) {
switch (page) {
case 'stats-farm':
return <StatsFarm />
case 'stats-lend-borrow':
return <StatsLendAndBorrow />
case 'stats-additional':
return <StatsAccounts />
default:
return <StatsTrading />
}
}
export default function StatsPage() {
const { pathname } = useLocation()
const page = getPage(pathname)
const activeIndex = STATS_TABS.findIndex((tab) => tab.page === page)
return (
<div className='flex flex-wrap w-full'>
<MigrationBanner />
<Tab tabs={STATS_TABS} activeTabIdx={activeIndex === -1 ? 0 : activeIndex} className='mb-8' />
{getStatsComponent(page)}
</div>
)
}

View File

@ -15,6 +15,6 @@ export default function createCommonSlice(set: SetState<CommonSlice>, get: GetSt
useMargin: true,
useAutoRepay: true,
isOracleStale: false,
isHLS: false,
currentAppSection: 'app',
}
}

View File

@ -61,3 +61,9 @@
table tr:last-child td {
border-bottom-width: 0;
}
.recharts-dot {
stroke: theme('colors.body');
fill: theme('colors.martian-red');
r: 5px;
}

View File

@ -0,0 +1,3 @@
type ChartDataItem = { date: string; value: number }
type ChartData = ChartDataItem[]

View File

@ -9,3 +9,7 @@ type Page =
| 'hls-farm'
| 'hls-staking'
| 'governance'
| 'stats'
| 'stats-farm'
| 'stats-lend-borrow'
| 'stats-additional'

View File

@ -18,7 +18,7 @@ interface CommonSlice {
useMargin: boolean
useAutoRepay: boolean
isOracleStale: boolean
isHLS: boolean
currentAppSection: string
}
interface FocusComponent {

View File

@ -19,7 +19,12 @@ export const DEFAULT_PORTFOLIO_STATS = [
{ title: null, sub: 'APR' },
{ title: null, sub: 'Account Leverage' },
]
export const DEFAULT_ADDITIONAL_STATS = [
{ head: 'Total TVL', title: null, sub: 'Last Observed on 28 Jan 2023' },
{ head: 'Total Credit Accounts', title: null, sub: '494 new credit accounts this week' },
{ head: 'Total Fees Generated', title: null, sub: 'Includes liquidation, swap and borrow fees' },
]
export const ENABLE_HLS = false
export const ENABLE_HLS = true
export const ENABLE_PERPS = false
export const ENABLE_AUTO_REPAY = false

View File

@ -1,4 +1,4 @@
import { BN } from './helpers'
import { BN } from 'utils/helpers'
export const devideByPotentiallyZero = (numerator: number, denominator: number): number => {
if (denominator === 0) return 0

View File

@ -1,4 +1,4 @@
import { formatAmountWithSymbol } from './formatters'
import { formatAmountWithSymbol } from 'utils/formatters'
export function getNoBalanceMessage(symbol: string) {
return `You don't have an ${symbol} balance in your account.`

View File

@ -28,6 +28,10 @@ export function getPage(pathname: string): Page {
'portfolio',
'hls-farm',
'hls-staking',
'stats',
'stats-farm',
'stats-lend-borrow',
'stats-additional',
]
const segments = pathname.split('/')

View File

@ -41,12 +41,16 @@ module.exports = {
'@nav-3/navigation:inline-block',
'@nav-4/navigation:inline-block',
'@nav-5/navigation:inline-block',
'@nav-6/navigation:inline-block',
'@nav-7/navigation:inline-block',
'@nav-0/navigation:hidden',
'@nav-1/navigation:hidden',
'@nav-2/navigation:hidden',
'@nav-3/navigation:hidden',
'@nav-4/navigation:hidden',
'@nav-5/navigation:hidden',
'@nav-6/navigation:hidden',
'@nav-7/navigation:hidden',
],
theme: {
extend: {
@ -119,10 +123,13 @@ module.exports = {
osmo: '#9f1ab9',
'orb-primary': '#b12f25',
'orb-primary-hls': '#FF645F',
'orb-primary-stats': '#597DFC',
'orb-secondary': '#530781',
'orb-secondary-hls': '#a03b45',
'orb-tertiary': '#ff00c7',
'orb-secondary-stats': '#00144e',
'orb-tertiary': '#FF00C7',
'orb-tertiary-hls': '#FB9562',
'orb-tertiary-stats': '#6677FF',
profit: '#41a4a9',
primary: '#FF625E',
secondary: '#FB9562',
@ -141,6 +148,8 @@ module.exports = {
'nav-3': '400px',
'nav-4': '500px',
'nav-5': '600px',
'nav-6': '700px',
'nav-7': '800px',
},
fontFamily: {
sans: ['Inter', 'sans-serif'],