mirror of
https://github.com/supabase/supabase.git
synced 2026-10-17 23:29:08 +03:00
www account dropdown in navbar
This commit is contained in:
1 parent
090b2478cd
commit
98f4cd7059
3 files changed
+201
-30
No files matched your search
@@ -0,0 +1,171 @@
|
||||
'use client'
|
||||
|
||||
import React, { Fragment } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { Home, LogOut, Menu, Search, Settings, User } from 'lucide-react'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuTrigger,
|
||||
Theme,
|
||||
buttonVariants,
|
||||
cn,
|
||||
themes,
|
||||
} from 'ui'
|
||||
import { useSetCommandMenuOpen } from 'ui-patterns/CommandMenu'
|
||||
import { logOut, useUser } from 'common'
|
||||
import { LucideIcon } from 'icons/src/createSupabaseIcon'
|
||||
|
||||
const AuthenticatedDropdownMenu = () => {
|
||||
const { theme, setTheme } = useTheme()
|
||||
const setCommandMenuOpen = useSetCommandMenuOpen()
|
||||
const user = useUser()
|
||||
|
||||
interface menuItem {
|
||||
label: string
|
||||
type?: 'link' | 'button' | 'text'
|
||||
icon?: LucideIcon
|
||||
href?: string
|
||||
shortcut?: string
|
||||
onClick?: VoidFunction
|
||||
otherProps?: {
|
||||
target?: '_blank'
|
||||
rel?: 'noreferrer noopener'
|
||||
}
|
||||
}
|
||||
|
||||
const menu: menuItem[][] = [
|
||||
[
|
||||
{
|
||||
label: user?.email ?? '',
|
||||
type: 'text',
|
||||
icon: User,
|
||||
},
|
||||
{
|
||||
label: 'Projects',
|
||||
icon: Home,
|
||||
href: 'https://supabase.com/dashboard/projects',
|
||||
},
|
||||
{
|
||||
label: 'Account Preferences',
|
||||
icon: Settings,
|
||||
href: 'https://supabase.com/dashboard/account/me',
|
||||
},
|
||||
{
|
||||
label: 'Logout',
|
||||
type: 'button',
|
||||
icon: LogOut,
|
||||
onClick: () => logOut(),
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
label: 'Search',
|
||||
type: 'button',
|
||||
icon: Search,
|
||||
onClick: () => setCommandMenuOpen(true),
|
||||
shortcut: '⌘K',
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
return (
|
||||
<DropdownMenu modal={false}>
|
||||
<DropdownMenuTrigger asChild className="flex">
|
||||
<button
|
||||
title="Menu dropdown button"
|
||||
className={cn(
|
||||
buttonVariants({ type: 'default' }),
|
||||
'text-foreground-light border-default w-[26px] min-w-[26px] h-[26px] data-[state=open]:bg-overlay-hover/30 hover:border-strong data-[state=open]:border-stronger hover:!bg-overlay-hover/50 bg-transparent'
|
||||
)}
|
||||
>
|
||||
<Menu size={16} strokeWidth={1} />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent side="bottom" align="end" className="w-52">
|
||||
{menu.map((menuSection, sectionIdx) => (
|
||||
<Fragment key={`topnav--${sectionIdx}`}>
|
||||
{sectionIdx !== 0 && <DropdownMenuSeparator key={`topnav--${sectionIdx}`} />}
|
||||
{menuSection.map(({ icon: Icon, ...sectionItem }, itemIdx) => {
|
||||
switch (sectionItem.type) {
|
||||
case 'text':
|
||||
return (
|
||||
<div
|
||||
key={`topnav-${sectionItem.label}-${sectionIdx}-${itemIdx}`}
|
||||
className="flex cursor-text items-center text-foreground rounded-sm px-2 py-1.5 text-xs outline-none space-x-2"
|
||||
{...sectionItem.otherProps}
|
||||
>
|
||||
{Icon && <Icon className="w-3 h-3" />}
|
||||
<span className="grow truncate">{sectionItem.label}</span>
|
||||
{sectionItem.shortcut && (
|
||||
<DropdownMenuShortcut>{sectionItem.shortcut}</DropdownMenuShortcut>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
case 'button':
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
key={`topnav-${sectionItem.label}-${sectionIdx}-${itemIdx}`}
|
||||
className="space-x-2"
|
||||
onClick={sectionItem.onClick!}
|
||||
{...sectionItem.otherProps}
|
||||
>
|
||||
{Icon && <Icon className="w-3 h-3" />}
|
||||
<span className="grow">{sectionItem.label}</span>
|
||||
{sectionItem.shortcut && (
|
||||
<DropdownMenuShortcut>{sectionItem.shortcut}</DropdownMenuShortcut>
|
||||
)}
|
||||
</DropdownMenuItem>
|
||||
)
|
||||
default:
|
||||
return (
|
||||
<Link
|
||||
key={`topnav-${sectionItem.label}-${sectionIdx}-${itemIdx}`}
|
||||
href={sectionItem.href!}
|
||||
{...sectionItem.otherProps}
|
||||
>
|
||||
<DropdownMenuItem className="space-x-2" onClick={() => {}}>
|
||||
{Icon && <Icon className="w-3 h-3" />}
|
||||
<span className="grow">{sectionItem.label}</span>
|
||||
{sectionItem.shortcut && (
|
||||
<DropdownMenuShortcut>{sectionItem.shortcut}</DropdownMenuShortcut>
|
||||
)}
|
||||
</DropdownMenuItem>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</Fragment>
|
||||
))}
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuLabel>Theme</DropdownMenuLabel>
|
||||
<DropdownMenuRadioGroup
|
||||
value={theme}
|
||||
onValueChange={(value) => {
|
||||
setTheme(value)
|
||||
}}
|
||||
>
|
||||
{themes
|
||||
.filter((x) => x.value === 'light' || x.value === 'dark' || x.value === 'system')
|
||||
.map((theme: Theme) => (
|
||||
<DropdownMenuRadioItem key={`topnav-theme-${theme.value}`} value={theme.value}>
|
||||
{theme.name}
|
||||
</DropdownMenuRadioItem>
|
||||
))}
|
||||
</DropdownMenuRadioGroup>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
|
||||
export default AuthenticatedDropdownMenu
|
||||
@@ -29,11 +29,7 @@ const GitHubButton = () => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Button
|
||||
className="hidden group lg:flex text-foreground-light hover:text-foreground"
|
||||
type="text"
|
||||
asChild
|
||||
>
|
||||
<Button className="group flex text-foreground-light hover:text-foreground" type="text" asChild>
|
||||
<a type={undefined} href="https://github.com/supabase/supabase" target="_blank">
|
||||
<span className="flex items-center gap-1">
|
||||
<svg
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
NavigationMenuList,
|
||||
NavigationMenuTrigger,
|
||||
} from 'ui/src/components/shadcn/ui/navigation-menu'
|
||||
import { logOut, useIsLoggedIn, useIsUserLoading } from 'common'
|
||||
import { isBrowser, STORAGE_KEY, useIsLoggedIn, useIsUserLoading } from 'common'
|
||||
import ScrollProgress from '~/components/ScrollProgress'
|
||||
import GitHubButton from './GitHubButton'
|
||||
import HamburgerButton from './HamburgerMenu'
|
||||
@@ -22,6 +22,7 @@ import MenuItem from './MenuItem'
|
||||
import { menu } from '~/data/nav'
|
||||
import RightClickBrandLogo from './RightClickBrandLogo'
|
||||
import LW12CountdownBanner from 'ui/src/layout/banners/LW12CountdownBanner/LW12CountdownBanner'
|
||||
import AuthenticatedDropdownMenu from './AuthenticatedDropdownMenu'
|
||||
|
||||
interface Props {
|
||||
hideNavbar: boolean
|
||||
@@ -29,11 +30,12 @@ interface Props {
|
||||
|
||||
const Nav = (props: Props) => {
|
||||
const { resolvedTheme } = useTheme()
|
||||
const [mounted, setMounted] = useState(false)
|
||||
const router = useRouter()
|
||||
const { width } = useWindowSize()
|
||||
const [open, setOpen] = useState(false)
|
||||
const isLoggedIn = useIsLoggedIn()
|
||||
const isUserLoading = useIsUserLoading()
|
||||
const isLoggedIn =
|
||||
(isBrowser && globalThis?.localStorage?.getItem(STORAGE_KEY)) || useIsLoggedIn()
|
||||
|
||||
const isHomePage = router.pathname === '/'
|
||||
const isLaunchWeekPage = router.pathname.includes('/launch-week')
|
||||
@@ -56,6 +58,10 @@ const Nav = (props: Props) => {
|
||||
if (width >= 1024) setOpen(false)
|
||||
}, [width])
|
||||
|
||||
React.useEffect(() => {
|
||||
setMounted(true)
|
||||
}, [])
|
||||
|
||||
if (props.hideNavbar) {
|
||||
return null
|
||||
}
|
||||
@@ -126,31 +132,29 @@ const Nav = (props: Props) => {
|
||||
</NavigationMenuList>
|
||||
</NavigationMenu>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 opacity-0 animate-fade-in !scale-100 delay-300">
|
||||
<div
|
||||
className={cn(
|
||||
'hidden lg:flex items-center gap-2 opacity-0 transition-opacity',
|
||||
mounted && 'animate-fade-in !scale-100 delay-100'
|
||||
)}
|
||||
>
|
||||
<GitHubButton />
|
||||
|
||||
{!isUserLoading && (
|
||||
{isLoggedIn ? (
|
||||
<>
|
||||
{isLoggedIn ? (
|
||||
<>
|
||||
<Button className="hidden lg:block" asChild>
|
||||
<Link href="/dashboard/projects">Dashboard</Link>
|
||||
</Button>
|
||||
{/* !Temporary! */}
|
||||
<Button className="hidden lg:block" onClick={logOut}>
|
||||
Log out
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Button type="default" className="hidden lg:block" asChild>
|
||||
<Link href="https://supabase.com/dashboard">Sign in</Link>
|
||||
</Button>
|
||||
<Button className="hidden lg:block" asChild>
|
||||
<Link href="https://supabase.com/dashboard">Start your project</Link>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<Button asChild>
|
||||
<Link href="/dashboard/projects">Dashboard</Link>
|
||||
</Button>
|
||||
<AuthenticatedDropdownMenu />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Button type="default" asChild>
|
||||
<Link href="https://supabase.com/sign-in">Sign in</Link>
|
||||
</Button>
|
||||
<Button asChild>
|
||||
<Link href="https://supabase.com/new">Start your project</Link>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user