www account dropdown in navbar

This commit is contained in:
Francesco Sansalvadore committed 2024-08-20 13:24:56 +02:00
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
+1 -5
View File
@@ -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
+29 -25
View File
@@ -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>