mirror of
https://github.com/supabase/supabase.git
synced 2026-10-09 03:15:06 +03:00
179 lines
5.9 KiB
TypeScript
179 lines
5.9 KiB
TypeScript
import * as Tooltip from '@radix-ui/react-tooltip'
|
|
import { useParams, useTheme } from 'common'
|
|
import { isUndefined } from 'lodash'
|
|
import Link from 'next/link'
|
|
import { useRouter } from 'next/router'
|
|
|
|
import { useFlag } from 'hooks'
|
|
import { IS_PLATFORM } from 'lib/constants'
|
|
import { detectOS } from 'lib/helpers'
|
|
import {
|
|
Button,
|
|
Dropdown,
|
|
IconCommand,
|
|
IconHome,
|
|
IconSearch,
|
|
IconSettings,
|
|
IconUser,
|
|
useCommandMenu,
|
|
} from 'ui'
|
|
import { useProjectContext } from '../ProjectContext'
|
|
import {
|
|
generateOtherRoutes,
|
|
generateProductRoutes,
|
|
generateToolRoutes,
|
|
} from './NavigationBar.utils'
|
|
import NavigationIconButton from './NavigationIconButton'
|
|
|
|
const NavigationBar = () => {
|
|
const router = useRouter()
|
|
const { isDarkMode, toggleTheme } = useTheme()
|
|
const { ref: projectRef } = useParams()
|
|
|
|
const os = detectOS()
|
|
const { setIsOpen } = useCommandMenu()
|
|
|
|
const { project } = useProjectContext()
|
|
const navLayoutV2 = useFlag('navigationLayoutV2')
|
|
const supabaseAIEnabled = useFlag('sqlEditorSupabaseAI')
|
|
|
|
const activeRoute = router.pathname.split('/')[3]
|
|
const toolRoutes = generateToolRoutes(projectRef, project, supabaseAIEnabled)
|
|
const productRoutes = generateProductRoutes(projectRef, project)
|
|
const otherRoutes = generateOtherRoutes(projectRef, project)
|
|
return (
|
|
<div
|
|
className={[
|
|
'flex w-14 flex-col justify-between overflow-y-hidden p-2',
|
|
'border-r bg-body border-scale-500',
|
|
].join(' ')}
|
|
>
|
|
<ul className="flex flex-col space-y-2">
|
|
{(!navLayoutV2 || !IS_PLATFORM) && (
|
|
<Link href={IS_PLATFORM ? '/projects' : `/project/${projectRef}`}>
|
|
<a className="block">
|
|
<img
|
|
src={`${router.basePath}/img/supabase-logo.svg`}
|
|
alt="Supabase"
|
|
className="mx-auto h-[40px] w-6 cursor-pointer rounded"
|
|
/>
|
|
</a>
|
|
</Link>
|
|
)}
|
|
<NavigationIconButton
|
|
isActive={isUndefined(activeRoute) && !isUndefined(router.query.ref)}
|
|
route={{
|
|
key: 'HOME',
|
|
label: 'Home',
|
|
icon: <IconHome size={18} strokeWidth={2} />,
|
|
link: `/project/${projectRef}`,
|
|
}}
|
|
/>
|
|
<div className="bg-scale-500 h-px w-full" />
|
|
{toolRoutes.map((route) => (
|
|
<NavigationIconButton
|
|
key={route.key}
|
|
route={route}
|
|
isActive={activeRoute === route.key}
|
|
/>
|
|
))}
|
|
<div className="bg-scale-500 h-px w-full"></div>
|
|
|
|
{productRoutes.map((route) => (
|
|
<NavigationIconButton
|
|
key={route.key}
|
|
route={route}
|
|
isActive={activeRoute === route.key}
|
|
/>
|
|
))}
|
|
<div className="h-px w-full bg-scale-500"></div>
|
|
{otherRoutes.map((route) => (
|
|
<NavigationIconButton
|
|
key={route.key}
|
|
route={route}
|
|
isActive={activeRoute === route.key}
|
|
/>
|
|
))}
|
|
</ul>
|
|
{!navLayoutV2 && (
|
|
<ul className="flex flex-col space-y-4 items-center">
|
|
{IS_PLATFORM && (
|
|
<Tooltip.Root delayDuration={0}>
|
|
<Tooltip.Trigger asChild>
|
|
<Button
|
|
type="text"
|
|
size="tiny"
|
|
onClick={() => setIsOpen(true)}
|
|
className="border-none"
|
|
>
|
|
<div className="py-1">
|
|
<IconSearch size={18} strokeWidth={2} className="text-scale-900" />
|
|
</div>
|
|
</Button>
|
|
</Tooltip.Trigger>
|
|
<Tooltip.Portal>
|
|
<Tooltip.Content side="right">
|
|
<Tooltip.Arrow className="radix-tooltip-arrow" />
|
|
<div
|
|
className={[
|
|
'rounded py-1 px-2 leading-none shadow',
|
|
'border border-scale-200 flex items-center space-x-1',
|
|
].join(' ')}
|
|
>
|
|
{os === 'macos' ? (
|
|
<IconCommand size={11.5} strokeWidth={1.5} className="text-scale-1200" />
|
|
) : (
|
|
<p className="text-xs">CTRL</p>
|
|
)}
|
|
<p className="text-xs">K</p>
|
|
</div>
|
|
</Tooltip.Content>
|
|
</Tooltip.Portal>
|
|
</Tooltip.Root>
|
|
)}
|
|
<Dropdown
|
|
side="right"
|
|
align="start"
|
|
overlay={
|
|
<>
|
|
{IS_PLATFORM && (
|
|
<>
|
|
<Link href="/account/me">
|
|
<Dropdown.Item
|
|
key="header"
|
|
icon={<IconSettings size={14} strokeWidth={1.5} />}
|
|
>
|
|
Account Preferences
|
|
</Dropdown.Item>
|
|
</Link>
|
|
<Dropdown.Separator />
|
|
</>
|
|
)}
|
|
<Dropdown.Label>Theme</Dropdown.Label>
|
|
<Dropdown.RadioGroup
|
|
key="theme"
|
|
value={isDarkMode ? 'dark' : 'light'}
|
|
onChange={(e: any) => toggleTheme(e === 'dark')}
|
|
>
|
|
{/* [Joshen] Removing system default for now, needs to be supported in useTheme from common packages */}
|
|
{/* <Dropdown.Radio value="system">System default</Dropdown.Radio> */}
|
|
<Dropdown.Radio value="dark">Dark</Dropdown.Radio>
|
|
<Dropdown.Radio value="light">Light</Dropdown.Radio>
|
|
</Dropdown.RadioGroup>
|
|
</>
|
|
}
|
|
>
|
|
<Button asChild type="text" size="tiny">
|
|
<span className="py-1 h-10 border-none">
|
|
<IconUser size={18} strokeWidth={2} className="text-scale-900" />
|
|
</span>
|
|
</Button>
|
|
</Dropdown>
|
|
</ul>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default NavigationBar
|