11import { PagePropsData } from '@/types' ;
22import { usePage } from '@inertiajs/react' ;
3- import { Container } from 'components/container' ;
4- import { Logo } from 'components/logo' ;
53import { useTheme } from 'components/theme-provider' ;
64import { ThemeSwitcher } from 'components/theme-switcher' ;
7- import { motion } from 'framer-motion' ;
8- import {
9- IconBrandJustd ,
10- IconBrandLaravel ,
11- IconChevronDown ,
12- IconColorSwatch ,
13- IconHamburger ,
14- IconSettings
15- } from 'justd-icons' ;
5+ import { IconBrandJustd , IconBrandLaravel , IconChevronDown , IconColorSwatch , IconSettings } from 'justd-icons' ;
166import React from 'react' ;
17- import { ListBox , ListBoxItem , ListBoxItemProps , Selection } from 'react-aria-components' ;
18- import { tv } from 'tailwind-variants' ;
19- import { Avatar , Button , Link , Menu , Sheet , useMediaQuery } from 'ui' ;
7+ import { Selection } from 'react-aria-components' ;
8+ import { Avatar , Button , Menu , Navbar , Separator } from 'ui' ;
209
2110const navigations = [
2211 {
@@ -55,80 +44,44 @@ const navigations = [
5544 }
5645] ;
5746
58- export function Navbar ( ) {
47+ export function AppNavbar ( { children, ...props } : React . ComponentProps < typeof Navbar > ) {
48+ const page = usePage ( ) ;
5949 const { auth } = usePage < PagePropsData > ( ) . props ;
6050 return (
61- < >
62- < ResponsiveNavbar />
63- < nav className = "relative bg-bg z-10 hidden border-b py-1 sm:block" >
64- < Container >
65- < div className = "flex items-center justify-between" >
66- < div className = "flex items-center" >
67- < Link href = "/" className = "mr-6" >
68- < Logo />
69- </ Link >
70- < NavContent />
71- </ div >
72- < div className = "gap-1 flex" >
73- { ! auth . user && < ThemeSwitcher /> }
74- { auth . user ? < UserMenu /> : < LoginMenu /> }
75- </ div >
76- </ div >
77- </ Container >
78- </ nav >
79- </ >
80- ) ;
81- }
82-
83- const navStyles = tv ( {
84- base : 'text-sm relative py-0 sm:py-4 inline-flex focus:outline-none focus-visible:text-fg font-medium' ,
85- variants : {
86- isCurrent : {
87- true : 'text-fg' ,
88- false : 'text-muted-fg hover:text-fg'
89- }
90- }
91- } ) ;
51+ < Navbar { ...props } >
52+ < Navbar . Nav >
53+ < Navbar . Logo aria-label = "Logo" >
54+ < IconBrandLaravel className = "size-6" />
55+ </ Navbar . Logo >
56+ < Navbar . Section >
57+ { navigations . map ( ( item ) => (
58+ < Navbar . Item isCurrent = { item . href === page . url } key = { item . href } href = { item . href } >
59+ { item . name }
60+ </ Navbar . Item >
61+ ) ) }
62+ </ Navbar . Section >
63+ < Navbar . Section className = "hidden ml-auto gap-x-1 lg:flex" >
64+ { ! auth . user && < ThemeSwitcher /> }
65+ { auth . user ? < UserMenu /> : < LoginMenu /> }
66+ </ Navbar . Section >
67+ </ Navbar . Nav >
9268
93- interface LinkProps extends ListBoxItemProps {
94- className ?: string ;
95- children : React . ReactNode ;
96- target ?: string ;
97- href ?: string ;
98- }
69+ < Navbar . Compact >
70+ < Navbar . Flex >
71+ < Navbar . Trigger />
72+ < Separator className = "h-6" orientation = "vertical" />
73+ < Navbar . Logo aria-label = "Logo" >
74+ < IconBrandLaravel />
75+ </ Navbar . Logo >
76+ </ Navbar . Flex >
77+ < Navbar . Flex className = "gap-x-1" >
78+ { ! auth . user && < ThemeSwitcher /> }
79+ { auth . user ? < UserMenu /> : < LoginMenu /> }
80+ </ Navbar . Flex >
81+ </ Navbar . Compact >
9982
100- function NavLink ( { children, className, ...props } : LinkProps ) {
101- const pathname = usePage ( ) . url ;
102- const isCurrent = pathname === props . href ;
103- return (
104- < ListBoxItem className = { navStyles ( { isCurrent, className } ) } { ...props } >
10583 { children }
106- { isCurrent && < CurrentIndicator /> }
107- </ ListBoxItem >
108- ) ;
109- }
110-
111- function CurrentIndicator ( ) {
112- return (
113- < motion . span
114- className = "h-full inset-y-0 sm:inset-auto sm:h-0.5 w-0.5 sm:w-full rounded-full bg-fg -left-4 sm:bottom-[-5px] sm:inset-x block absolute"
115- layoutId = "current"
116- />
117- ) ;
118- }
119-
120- function LoginMenu ( ) {
121- return (
122- < Menu >
123- < Button size = "small" appearance = "outline" >
124- Login
125- < IconChevronDown className = "ml-2" />
126- </ Button >
127- < Menu . Content showArrow placement = "bottom end" className = "w-40" >
128- < Menu . Item href = { route ( 'login' ) } > Login</ Menu . Item >
129- < Menu . Item href = { route ( 'register' ) } > Register</ Menu . Item >
130- </ Menu . Content >
131- </ Menu >
84+ </ Navbar >
13285 ) ;
13386}
13487
@@ -142,7 +95,7 @@ function UserMenu() {
14295 < Menu . Trigger aria-label = "Open menu" >
14396 < Avatar status = "online" size = "medium" src = { auth . user . gravatar } className = "size-8" />
14497 </ Menu . Trigger >
145- < Menu . Content showArrow placement = "bottom end" className = "min-w-56" >
98+ < Menu . Content showArrow placement = "bottom end" className = "sm: min-w-56" >
14699 < Menu . Section >
147100 < Menu . Header separator className = "relative" >
148101 < div > { auth . user . name } </ div >
@@ -201,62 +154,17 @@ function UserMenu() {
201154 ) ;
202155}
203156
204- function ResponsiveNavbar ( ) {
205- const { auth } = usePage < PagePropsData > ( ) . props ;
206- return (
207- < nav className = "block border-b px-4 py-2 sm:hidden" >
208- < div className = "flex items-center justify-between py-1" >
209- < div className = "gap-2 flex items-center" >
210- < Sheet >
211- < Button size = "small" appearance = "outline" >
212- < IconHamburger />
213- Menu
214- </ Button >
215- < Sheet . Content >
216- < Sheet . Header className = "text-left" >
217- < Sheet . Title className = "inline-flex items-center gap-x-2" >
218- < Logo />
219- { import . meta. env . VITE_APP_NAME }
220- </ Sheet . Title >
221- </ Sheet . Header >
222- < NavContent />
223- </ Sheet . Content >
224- </ Sheet >
225-
226- < Link href = "/" >
227- < Logo className = "w-8 fill-red-600" />
228- </ Link >
229- </ div >
230- < div className = "flex gap-1" >
231- { ! auth . user && < ThemeSwitcher /> }
232- { auth . user ? < UserMenu /> : < LoginMenu /> }
233- </ div >
234- </ div >
235- </ nav >
236- ) ;
237- }
238-
239- function NavContent ( ) {
240- const isMobile = useMediaQuery ( '(max-width: 640px)' ) ;
157+ function LoginMenu ( ) {
241158 return (
242- < ListBox
243- aria-label = "Navigation"
244- orientation = { isMobile ? 'vertical' : 'horizontal' }
245- layout = { isMobile ? 'stack' : 'grid' }
246- className = "flex sm:flex-row flex-col sm:items-center gap-y-4 sm:gap-x-6"
247- items = { navigations }
248- >
249- { ( item ) => (
250- < NavLink
251- id = { item . textValue }
252- textValue = { item . textValue }
253- href = { item . href }
254- target = { [ 'Github' , 'Components' , 'Colors' , 'Templates' ] . includes ( item . name ) ? '_blank' : undefined }
255- className = { item . className }
256- >
257- { item . name }
258- </ NavLink >
259- ) }
260- </ ListBox >
159+ < Menu >
160+ < Button size = "small" appearance = "outline" >
161+ Login
162+ < IconChevronDown className = "ml-2" />
163+ </ Button >
164+ < Menu . Content showArrow placement = "bottom end" className = "sm:min-w-40" >
165+ < Menu . Item href = { route ( 'login' ) } > Login</ Menu . Item >
166+ < Menu . Item href = { route ( 'register' ) } > Register</ Menu . Item >
167+ </ Menu . Content >
168+ </ Menu >
261169 ) ;
262170}
0 commit comments