feat: shadcn-style mobile menu

This commit is contained in:
enscribe 2024-09-12 19:59:13 -07:00
parent 2211c4bbf3
commit 72655a8317
No known key found for this signature in database
GPG key ID: 9BBD5C4114E25322
5 changed files with 70 additions and 8 deletions

View file

@ -16,7 +16,7 @@ const { name, avatar, bio, pronouns, github, twitter, linkedin, website } =
--- ---
<div <div
class="rounded-xl border p-4 transition-colors duration-300 ease-in-out has-[a:hover]:bg-secondary/50" class="overflow-hidden rounded-xl border p-4 transition-colors duration-300 ease-in-out has-[a:hover]:bg-secondary/50"
> >
<div class="flex flex-wrap gap-4"> <div class="flex flex-wrap gap-4">
<Link <Link
@ -35,7 +35,7 @@ const { name, avatar, bio, pronouns, github, twitter, linkedin, website } =
)} )}
/> />
</Link> </Link>
<div class="flex flex-grow flex-col justify-between"> <div class="flex flex-grow flex-col justify-between gap-y-4">
<div> <div>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<h3 class="text-lg font-semibold">{name}</h3> <h3 class="text-lg font-semibold">{name}</h3>

View file

@ -2,6 +2,7 @@
import { ModeToggle } from '@/components/ui/mode-toggle' import { ModeToggle } from '@/components/ui/mode-toggle'
import Container from '@components/Container.astro' import Container from '@components/Container.astro'
import Link from '@components/Link.astro' import Link from '@components/Link.astro'
import MobileMenu from '@components/ui/mobile-menu'
import { NAV_LINKS, SITE } from '@consts' import { NAV_LINKS, SITE } from '@consts'
import { Image } from 'astro:assets' import { Image } from 'astro:assets'
import logo from '../../public/static/logo.svg' import logo from '../../public/static/logo.svg'
@ -20,8 +21,8 @@ import logo from '../../public/static/logo.svg'
<Image src={logo} alt="Logo" class="size-8 rounded-sm" /> <Image src={logo} alt="Logo" class="size-8 rounded-sm" />
{SITE.TITLE} {SITE.TITLE}
</Link> </Link>
<div class="flex items-center gap-4"> <div class="flex items-center gap-2 md:gap-4">
<nav class="flex items-center gap-4 text-sm sm:gap-6"> <nav class="hidden items-center gap-4 text-sm sm:gap-6 md:flex">
{ {
NAV_LINKS.map((item) => ( NAV_LINKS.map((item) => (
<Link <Link
@ -33,7 +34,8 @@ import logo from '../../public/static/logo.svg'
)) ))
} }
</nav> </nav>
<ModeToggle client:load /> <MobileMenu client:load transition:persist />
<ModeToggle client:load transition:persist />
</div> </div>
</div> </div>
</Container> </Container>

View file

@ -23,7 +23,7 @@ const AvatarImage = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<AvatarPrimitive.Image <AvatarPrimitive.Image
ref={ref} ref={ref}
className={cn('aspect-square h-full w-full', className)} className={cn('aspect-square size-full', className)}
{...props} {...props}
/> />
)) ))
@ -36,7 +36,7 @@ const AvatarFallback = React.forwardRef<
<AvatarPrimitive.Fallback <AvatarPrimitive.Fallback
ref={ref} ref={ref}
className={cn( className={cn(
'flex h-full w-full items-center justify-center bg-muted', 'flex size-full items-center justify-center bg-muted',
className, className,
)} )}
{...props} {...props}

View file

@ -0,0 +1,60 @@
import React, { useState, useEffect } from 'react'
import { Button } from '@/components/ui/button'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { NAV_LINKS } from '@consts'
import { Menu } from 'lucide-react'
const MobileMenu = () => {
const [isOpen, setIsOpen] = useState(false)
useEffect(() => {
const handleViewTransitionStart = () => {
setIsOpen(false)
}
document.addEventListener('astro:before-swap', handleViewTransitionStart)
return () => {
document.removeEventListener(
'astro:before-swap',
handleViewTransitionStart,
)
}
}, [])
return (
<DropdownMenu open={isOpen} onOpenChange={setIsOpen} modal={false}>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
size="icon"
className="md:hidden"
title="Menu"
>
<Menu className="h-5 w-5" />
<span className="sr-only">Toggle menu</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="mr-4 bg-background">
{NAV_LINKS.map((item) => (
<DropdownMenuItem key={item.href} asChild>
<a
href={item.href}
className="w-full text-lg font-medium capitalize"
onClick={() => setIsOpen(false)}
>
{item.label}
</a>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
)
}
export default MobileMenu

View file

@ -40,7 +40,7 @@ export function ModeToggle() {
<span className="sr-only">Toggle theme</span> <span className="sr-only">Toggle theme</span>
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end" className="bg-background"> <DropdownMenuContent align="end" className="mr-4 bg-background">
<DropdownMenuItem onClick={() => setThemeState('theme-light')}> <DropdownMenuItem onClick={() => setThemeState('theme-light')}>
<Sun className="mr-2 size-4" /> <Sun className="mr-2 size-4" />
<span>Light</span> <span>Light</span>