mirror of
https://github.com/r-freeman/portfolio.git
synced 2024-11-22 22:35:42 +00:00
Extracted navigation components
This commit is contained in:
parent
a9d7f5c7ce
commit
0524cbdaf4
@ -1,112 +1,10 @@
|
|||||||
import Link from 'next/link'
|
|
||||||
import {usePathname} from 'next/navigation'
|
import {usePathname} from 'next/navigation'
|
||||||
import {Fragment, useEffect, useRef} from 'react'
|
import {useEffect, useRef} from 'react'
|
||||||
import {Popover, Transition} from '@headlessui/react'
|
|
||||||
import clsx from 'clsx'
|
|
||||||
import {Container} from './Container'
|
import {Container} from './Container'
|
||||||
import {MobileNavItem} from './ui/MobileNavItem'
|
import {MobileNavigation, DesktopNavigation} from './ui/Navigation'
|
||||||
import {Avatar, AvatarContainer} from './ui/Avatar'
|
import {Avatar, AvatarContainer} from './ui/Avatar'
|
||||||
import {CloseIcon} from './icons/CloseIcon'
|
|
||||||
import {ChevronDownIcon} from './icons/ChevronDownIcon'
|
|
||||||
import {MoonIcon} from './icons/MoonIcon'
|
import {MoonIcon} from './icons/MoonIcon'
|
||||||
import {SunIcon} from './icons/SunIcon'
|
import {SunIcon} from './icons/SunIcon'
|
||||||
import type {Props} from 'types'
|
|
||||||
|
|
||||||
function MobileNavigation(props: Props) {
|
|
||||||
return (
|
|
||||||
<Popover {...props}>
|
|
||||||
<Popover.Button
|
|
||||||
className="group flex items-center rounded-full bg-white/90 px-4 py-2 text-sm font-medium text-zinc-800 shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur dark:bg-zinc-800/90 dark:text-zinc-200 dark:ring-white/10 dark:hover:ring-white/20">
|
|
||||||
Menu
|
|
||||||
<ChevronDownIcon
|
|
||||||
className="ml-3 h-auto w-2 stroke-zinc-500 group-hover:stroke-zinc-700 dark:group-hover:stroke-zinc-400"/>
|
|
||||||
</Popover.Button>
|
|
||||||
<Transition.Root>
|
|
||||||
<Transition.Child
|
|
||||||
as={Fragment}
|
|
||||||
enter="duration-150 ease-out"
|
|
||||||
enterFrom="opacity-0"
|
|
||||||
enterTo="opacity-100"
|
|
||||||
leave="duration-150 ease-in"
|
|
||||||
leaveFrom="opacity-100"
|
|
||||||
leaveTo="opacity-0"
|
|
||||||
>
|
|
||||||
<Popover.Overlay className="fixed inset-0 z-50 bg-zinc-800/40 backdrop-blur-sm dark:bg-black/80"/>
|
|
||||||
</Transition.Child>
|
|
||||||
<Transition.Child
|
|
||||||
as={Fragment}
|
|
||||||
enter="duration-150 ease-out"
|
|
||||||
enterFrom="opacity-0 scale-95"
|
|
||||||
enterTo="opacity-100 scale-100"
|
|
||||||
leave="duration-150 ease-in"
|
|
||||||
leaveFrom="opacity-100 scale-100"
|
|
||||||
leaveTo="opacity-0 scale-95"
|
|
||||||
>
|
|
||||||
<Popover.Panel
|
|
||||||
focus
|
|
||||||
className="fixed inset-x-4 top-8 z-50 origin-top rounded-3xl bg-white p-8 ring-1 ring-zinc-900/5 dark:bg-zinc-900 dark:ring-zinc-800"
|
|
||||||
>
|
|
||||||
<div className="flex flex-row-reverse items-center justify-between">
|
|
||||||
<Popover.Button aria-label="Close menu" className="-m-1 p-1">
|
|
||||||
<CloseIcon className="h-6 w-6 text-zinc-500 dark:text-zinc-400"/>
|
|
||||||
</Popover.Button>
|
|
||||||
<h2 className="text-sm font-medium text-zinc-600 dark:text-zinc-400">
|
|
||||||
Navigation
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
<nav className="mt-6">
|
|
||||||
<ul className="-my-2 divide-y divide-zinc-100 text-base text-zinc-800 dark:divide-zinc-100/5 dark:text-zinc-300">
|
|
||||||
<MobileNavItem href="/about">About</MobileNavItem>
|
|
||||||
<MobileNavItem href="/dashboard">Dashboard</MobileNavItem>
|
|
||||||
<MobileNavItem href="/writing">Writing</MobileNavItem>
|
|
||||||
<MobileNavItem href="/projects">Projects</MobileNavItem>
|
|
||||||
<MobileNavItem href="/uses">Uses</MobileNavItem>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</Popover.Panel>
|
|
||||||
</Transition.Child>
|
|
||||||
</Transition.Root>
|
|
||||||
</Popover>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function NavItem({href, children}: { href: string } & Props) {
|
|
||||||
let isActive = usePathname() === href
|
|
||||||
|
|
||||||
return (
|
|
||||||
<li>
|
|
||||||
<Link
|
|
||||||
href={href}
|
|
||||||
className={clsx(
|
|
||||||
'relative block px-3 py-2 transition',
|
|
||||||
isActive
|
|
||||||
? 'text-indigo-500 dark:text-indigo-400'
|
|
||||||
: 'hover:text-indigo-500 dark:hover:text-indigo-400'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
{isActive && (
|
|
||||||
<span
|
|
||||||
className="absolute inset-x-1 -bottom-px h-px bg-gradient-to-r from-indigo-500/0 via-indigo-500/40 to-indigo-500/0 dark:from-indigo-400/0 dark:via-indigo-400/40 dark:to-indigo-400/0"/>
|
|
||||||
)}
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DesktopNavigation(props: Props) {
|
|
||||||
return (
|
|
||||||
<nav {...props}>
|
|
||||||
<ul className="flex rounded-full bg-white/90 px-3 text-sm font-medium text-zinc-800 shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur dark:bg-zinc-800/90 dark:text-zinc-200 dark:ring-white/10">
|
|
||||||
<NavItem href="/about">About</NavItem>
|
|
||||||
<NavItem href="/dashboard">Dashboard</NavItem>
|
|
||||||
<NavItem href="/writing">Writing</NavItem>
|
|
||||||
<NavItem href="/projects">Projects</NavItem>
|
|
||||||
<NavItem href="/uses">Uses</NavItem>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ModeToggle() {
|
function ModeToggle() {
|
||||||
function disableTransitionsTemporarily() {
|
function disableTransitionsTemporarily() {
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
import {Props} from '@/types';
|
|
||||||
import {Popover} from '@headlessui/react'
|
|
||||||
import Link from 'next/link'
|
|
||||||
|
|
||||||
export function MobileNavItem({href, children}: { href: string } & Props) {
|
|
||||||
return (
|
|
||||||
<li>
|
|
||||||
<Popover.Button as={Link} href={href} className="block py-2">
|
|
||||||
{children}
|
|
||||||
</Popover.Button>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
}
|
|
115
components/ui/Navigation.tsx
Normal file
115
components/ui/Navigation.tsx
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import {Fragment} from 'react'
|
||||||
|
import {usePathname} from 'next/navigation'
|
||||||
|
import {Popover, Transition} from '@headlessui/react'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import {ChevronDownIcon} from '@/components/icons/ChevronDownIcon'
|
||||||
|
import {CloseIcon} from '@/components/icons/CloseIcon'
|
||||||
|
import {Props} from '@/types'
|
||||||
|
|
||||||
|
function MobileNavItem({href, children}: { href: string } & Props) {
|
||||||
|
return (
|
||||||
|
<li>
|
||||||
|
<Popover.Button as={Link} href={href} className="block py-2">
|
||||||
|
{children}
|
||||||
|
</Popover.Button>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MobileNavigation(props: Props) {
|
||||||
|
return (
|
||||||
|
<Popover {...props}>
|
||||||
|
<Popover.Button
|
||||||
|
className="group flex items-center rounded-full bg-white/90 px-4 py-2 text-sm font-medium text-zinc-800 shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur dark:bg-zinc-800/90 dark:text-zinc-200 dark:ring-white/10 dark:hover:ring-white/20">
|
||||||
|
Menu
|
||||||
|
<ChevronDownIcon
|
||||||
|
className="ml-3 h-auto w-2 stroke-zinc-500 group-hover:stroke-zinc-700 dark:group-hover:stroke-zinc-400"/>
|
||||||
|
</Popover.Button>
|
||||||
|
<Transition.Root>
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="duration-150 ease-out"
|
||||||
|
enterFrom="opacity-0"
|
||||||
|
enterTo="opacity-100"
|
||||||
|
leave="duration-150 ease-in"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
|
<Popover.Overlay className="fixed inset-0 z-50 bg-zinc-800/40 backdrop-blur-sm dark:bg-black/80"/>
|
||||||
|
</Transition.Child>
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="duration-150 ease-out"
|
||||||
|
enterFrom="opacity-0 scale-95"
|
||||||
|
enterTo="opacity-100 scale-100"
|
||||||
|
leave="duration-150 ease-in"
|
||||||
|
leaveFrom="opacity-100 scale-100"
|
||||||
|
leaveTo="opacity-0 scale-95"
|
||||||
|
>
|
||||||
|
<Popover.Panel
|
||||||
|
focus
|
||||||
|
className="fixed inset-x-4 top-8 z-50 origin-top rounded-3xl bg-white p-8 ring-1 ring-zinc-900/5 dark:bg-zinc-900 dark:ring-zinc-800"
|
||||||
|
>
|
||||||
|
<div className="flex flex-row-reverse items-center justify-between">
|
||||||
|
<Popover.Button aria-label="Close menu" className="-m-1 p-1">
|
||||||
|
<CloseIcon className="h-6 w-6 text-zinc-500 dark:text-zinc-400"/>
|
||||||
|
</Popover.Button>
|
||||||
|
<h2 className="text-sm font-medium text-zinc-600 dark:text-zinc-400">
|
||||||
|
Navigation
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<nav className="mt-6">
|
||||||
|
<ul className="-my-2 divide-y divide-zinc-100 text-base text-zinc-800 dark:divide-zinc-100/5 dark:text-zinc-300">
|
||||||
|
<MobileNavItem href="/about">About</MobileNavItem>
|
||||||
|
<MobileNavItem href="/dashboard">Dashboard</MobileNavItem>
|
||||||
|
<MobileNavItem href="/writing">Writing</MobileNavItem>
|
||||||
|
<MobileNavItem href="/projects">Projects</MobileNavItem>
|
||||||
|
<MobileNavItem href="/uses">Uses</MobileNavItem>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</Popover.Panel>
|
||||||
|
</Transition.Child>
|
||||||
|
</Transition.Root>
|
||||||
|
</Popover>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function NavItem({href, children}: { href: string } & Props) {
|
||||||
|
let isActive = usePathname() === href
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li>
|
||||||
|
<Link
|
||||||
|
href={href}
|
||||||
|
className={clsx(
|
||||||
|
'relative block px-3 py-2 transition',
|
||||||
|
isActive
|
||||||
|
? 'text-indigo-500 dark:text-indigo-400'
|
||||||
|
: 'hover:text-indigo-500 dark:hover:text-indigo-400'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
{isActive && (
|
||||||
|
<span
|
||||||
|
className="absolute inset-x-1 -bottom-px h-px bg-gradient-to-r from-indigo-500/0 via-indigo-500/40 to-indigo-500/0 dark:from-indigo-400/0 dark:via-indigo-400/40 dark:to-indigo-400/0"/>
|
||||||
|
)}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DesktopNavigation(props: Props) {
|
||||||
|
return (
|
||||||
|
<nav {...props}>
|
||||||
|
<ul className="flex rounded-full bg-white/90 px-3 text-sm font-medium text-zinc-800 shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur dark:bg-zinc-800/90 dark:text-zinc-200 dark:ring-white/10">
|
||||||
|
<NavItem href="/about">About</NavItem>
|
||||||
|
<NavItem href="/dashboard">Dashboard</NavItem>
|
||||||
|
<NavItem href="/writing">Writing</NavItem>
|
||||||
|
<NavItem href="/projects">Projects</NavItem>
|
||||||
|
<NavItem href="/uses">Uses</NavItem>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user