11import DarkModeSwitch from "./DarkModeSwitch" ;
22import GitHub from "./ui/GitHubMark" ;
33import { Link , useLocation } from "@tanstack/react-router" ;
4- import { Popover } from "radix-ui" ;
5- import { MenuIcon , HomeIcon } from "lucide-react" ;
4+ import { Accordion , Popover } from "radix-ui" ;
5+ import { ChevronDown , MenuIcon } from "lucide-react" ;
66import { Route as ProjectsRoute } from "~/routes/projects.index" ;
77import { Route as BlogRoute } from "~/routes/blog.index" ;
88import { Route as AboutRoute } from "~/routes/about" ;
@@ -18,26 +18,151 @@ const navStyles = {
1818 font-bold
1919 text-lg
2020 h-[3rem]
21- rounded-full
21+ rounded
2222 w-30
2323 min-w-30
2424 transition-all
25- dark:hover:bg-gray-600/20
26- hover:bg-gray- 300/50
25+ dark:hover:bg-night-sky-700
26+ hover:bg-night-sky- 300
2727 focus-visible:ring-blue-500
2828 outline-0
2929 focus-visible:ring-1
3030 flex
3131 items-center
3232 justify-center
3333 ` ,
34- active : "font-bold text-lg" ,
34+ active : "font-bold text-lg bg-night-sky-200 dark:bg-night-sky-900 " ,
3535 inactive : "font-normal text-lg" ,
3636 container : "w-full sticky top-0 bg-dawn-pink-100 dark:bg-night-sky-950 z-50" ,
3737 nav : "h-[4rem] p-0 items-center m-auto" ,
3838} ;
3939
40- export default function Navbar ( ) {
40+ function BlogLinkButton ( { categories } : { categories ?: string [ ] } ) {
41+ const [ isOpen , setIsOpen ] = useState ( false ) ;
42+ const pathname = useLocation ( ) . pathname ;
43+ const isActive = pathname . startsWith ( "/blog" ) ;
44+
45+ useEffect ( ( ) => {
46+ setIsOpen ( false ) ;
47+ } , [ pathname ] ) ;
48+
49+ return categories && categories . length > 0 ? (
50+ < Popover . Root open = { isOpen } onOpenChange = { setIsOpen } >
51+ < Popover . Trigger className = "flex items-center justify-center h-full cursor-pointer outline-0 focus-visible:ring-1 focus-visible:ring-blue-500" >
52+ < div className = "flex items-center justify-center h-full cursor-pointer outline-0 focus-visible:ring-1 focus-visible:ring-blue-500" >
53+ < div
54+ className = { `${ navStyles . button } ${ isActive ? navStyles . active : navStyles . inactive } ` }
55+ >
56+ Blog
57+ </ div >
58+ < span className = "sr-only" > Toggle menu</ span >
59+ </ div >
60+ </ Popover . Trigger >
61+ < Popover . Portal >
62+ < Popover . Content
63+ className = "w-64 bg-dawn-pink-100 dark:bg-night-sky-950 p-2 rounded-lg shadow-xl z-50 border-night-sky-950 dark:border-dawn-pink-100 border-2"
64+ sideOffset = { 5 }
65+ >
66+ < div className = "flex items-center justify-center h-full cursor-pointer outline-0 focus-visible:ring-1 focus-visible:ring-blue-500" >
67+ < div className = "flex flex-col space-y-1 w-full" >
68+ { categories . map ( ( category ) => (
69+ < Link
70+ to = { BlogRoute . to + `/${ category . toLowerCase ( ) } ` }
71+ className = "px-4 py-2 rounded-md text-center capitalize hover:bg-night-sky-300 dark:hover:bg-night-sky-700"
72+ activeProps = { { className : navStyles . active } }
73+ key = { category }
74+ resetScroll
75+ >
76+ { category }
77+ </ Link >
78+ ) ) }
79+ < Link
80+ to = { BlogRoute . to }
81+ className = "px-4 py-2 hover:bg-night-sky-300 dark:hover:bg-night-sky-700 rounded-md text-center"
82+ activeOptions = { { exact : true } }
83+ activeProps = { { className : navStyles . active } }
84+ resetScroll
85+ >
86+ See All Posts
87+ </ Link >
88+ </ div >
89+ </ div >
90+ < Popover . Arrow
91+ height = { 10 }
92+ className = "dark:fill-dawn-pink-100 fill-night-sky-950"
93+ />
94+ </ Popover . Content >
95+ </ Popover . Portal >
96+ </ Popover . Root >
97+ ) : (
98+ < Link
99+ to = { BlogRoute . to }
100+ className = { navStyles . button }
101+ resetScroll
102+ aria-label = "Blog link"
103+ activeProps = { { className : navStyles . active } }
104+ inactiveProps = { { className : navStyles . inactive } }
105+ >
106+ Blog
107+ </ Link >
108+ ) ;
109+ }
110+
111+ function BlogLinkDropdown ( { categories } : { categories ?: string [ ] } ) {
112+ const pathname = useLocation ( ) . pathname ;
113+ const isActive = pathname . startsWith ( "/blog" ) ;
114+
115+ return (
116+ < Accordion . Root type = "single" collapsible >
117+ < Accordion . Item value = "blog" className = "text-center" >
118+ < Accordion . Header >
119+ < Accordion . Trigger
120+ className = { cn (
121+ "w-full group" ,
122+ "px-4 py-2 rounded-md dark:hover:bg-night-sky-700 hover:bg-night-sky-300 relative" ,
123+ isActive ? navStyles . active : navStyles . inactive
124+ ) }
125+ >
126+ Blog
127+ < ChevronDown
128+ className = "absolute right-2 top-1/2 transform -translate-y-1/2 group-data-[state=open]:rotate-180 transition duration-200"
129+ size = { 24 }
130+ aria-hidden
131+ />
132+ </ Accordion . Trigger >
133+ </ Accordion . Header >
134+ < Accordion . Content className = "p-2 space-y-1" >
135+ < div className = "w-full bg-night-sky-950 dark:bg-dawn-pink-100 h-[1px] mx-auto mb-2" />
136+ { categories ?. map ( ( category ) => (
137+ < Link
138+ key = { category }
139+ to = { BlogRoute . to + `/${ category . toLowerCase ( ) } ` }
140+ className = "block text-sm px-4 py-2 rounded-md text-center capitalize hover:bg-night-sky-300 dark:hover:bg-night-sky-700"
141+ activeProps = { { className : navStyles . active } }
142+ resetScroll
143+ >
144+ { category }
145+ </ Link >
146+ ) ) }
147+ < Link
148+ to = { BlogRoute . to }
149+ className = "block text-sm px-4 py-2 rounded-md text-center hover:bg-night-sky-300 dark:hover:bg-night-sky-700"
150+ activeOptions = { { exact : true } }
151+ activeProps = { { className : navStyles . active } }
152+ resetScroll
153+ >
154+ See All Posts
155+ </ Link >
156+ < div className = "w-full bg-night-sky-950 dark:bg-dawn-pink-100 h-[1px] mx-auto mt-2" />
157+ </ Accordion . Content >
158+ </ Accordion . Item >
159+ </ Accordion . Root >
160+ ) ;
161+ }
162+
163+ export default function Navbar (
164+ { categories } : { categories ?: string [ ] } = { categories : [ ] }
165+ ) {
41166 const [ isOpen , setIsOpen ] = useState ( false ) ;
42167 const pathname = useLocation ( ) . pathname ;
43168
@@ -55,14 +180,12 @@ export default function Navbar() {
55180 >
56181 < Link
57182 to = "/"
58- activeProps = { { className : navStyles . active } }
59183 inactiveProps = { { className : navStyles . inactive } }
60184 activeOptions = { { exact : true } }
61- className = "flex cursor-pointer items-center justify-center px-1 py-0 m-0 size-[3rem] rounded-full bg-transparent shadow-none border-solid focus-visible:ring-1 focus-visible:ring-blue-500 hover:bg-gray-600/20 justify-self-start"
185+ className = "flex cursor-pointer items-center justify-center px-1 py-0 m-0 size-[3rem] rounded-full bg-transparent shadow-none border-solid focus-visible:ring-1 focus-visible:ring-blue-500 hover:bg-night-sky-300 dark:hover:bg-night-sky-700 justify-self-start"
62186 resetScroll
63187 aria-label = "Home page link"
64188 >
65- { /* <HomeIcon className="p-0" size={32} aria-label="Home icon" /> */ }
66189 < img src = "/static/logo.svg" alt = "Logo" className = "h-8 dark:hidden" />
67190 < img
68191 src = "/static/logo-light.svg"
@@ -71,16 +194,8 @@ export default function Navbar() {
71194 />
72195 < span className = "sr-only" > Home</ span >
73196 </ Link >
74- < div className = "align-middle grow-0 flex px-5 justify-self-stretch justify-center" >
75- < Link
76- to = { BlogRoute . to }
77- activeProps = { { className : navStyles . active } }
78- inactiveProps = { { className : navStyles . inactive } }
79- className = { navStyles . button }
80- resetScroll
81- >
82- Blog
83- </ Link >
197+ < div className = "align-middle grow-0 flex space-x-2 px-5 justify-self-stretch justify-center" >
198+ < BlogLinkButton categories = { categories } />
84199 < Link
85200 to = { ProjectsRoute . to }
86201 activeProps = { { className : navStyles . active } }
@@ -113,13 +228,22 @@ export default function Navbar() {
113228 < div className = "flex items-center justify-between w-full px-2" >
114229 < Link
115230 to = "/"
116- activeProps = { { className : navStyles . active } }
117231 inactiveProps = { { className : navStyles . inactive } }
118232 activeOptions = { { exact : true } }
119- className = "flex cursor-pointer items-center justify-center px-1 py-0 m-0 size-[3rem] rounded-full bg-transparent shadow-none border-solid focus-visible:ring-1 focus-visible:ring-blue-500 hover:bg-gray-600/20 "
233+ className = "flex cursor-pointer items-center justify-center px-1 py-0 m-0 size-[3rem] rounded-full bg-transparent shadow-none border-solid focus-visible:ring-1 focus-visible:ring-blue-500"
120234 resetScroll
121235 >
122- < HomeIcon className = "p-0" size = { 32 } />
236+ < img
237+ src = "/static/logo.svg"
238+ alt = "Logo"
239+ className = "h-8 dark:hidden"
240+ />
241+ < img
242+ src = "/static/logo-light.svg"
243+ alt = "Logo"
244+ className = "h-8 hidden dark:inline"
245+ />
246+ < span className = "sr-only" > Home</ span >
123247 </ Link >
124248
125249 < div className = "align-middle justify-center grow-0 px-4" >
@@ -136,34 +260,20 @@ export default function Navbar() {
136260 sideOffset = { 5 }
137261 >
138262 < div className = "flex flex-col space-y-1" >
139- < Link
140- to = { BlogRoute . to }
141- className = "px-4 py-2 hover:bg-muted rounded-md text-center"
142- activeProps = { {
143- className :
144- "font-bold bg-dawn-pink-300 dark:bg-night-sky-900" ,
145- } }
146- resetScroll
147- >
148- Blog
149- </ Link >
263+ < BlogLinkDropdown categories = { categories } />
150264 < Link
151265 to = { ProjectsRoute . to }
152- className = "px-4 py-2 hover:bg-muted rounded-md text-center"
153- activeProps = { {
154- className :
155- "font-bold bg-dawn-pink-300 dark:bg-night-sky-900" ,
156- } }
266+ className = "px-4 py-2 dark:hover:bg-night-sky-700 hover:bg-night-sky-300 rounded-md text-center"
267+ activeProps = { { className : navStyles . active } }
157268 resetScroll
158269 >
159270 Projects
160271 </ Link >
161272 < Link
162273 to = { AboutRoute . to }
163- className = "px-4 py-2 hover:bg-muted rounded-md text-center"
274+ className = "px-4 py-2 dark: hover:bg-night-sky-700 hover:bg-night-sky-300 dark:active:bg-night-sky-700 active:bg-night-sky-300 rounded-md text-center"
164275 activeProps = { {
165- className :
166- "font-bold bg-dawn-pink-300 dark:bg-night-sky-900" ,
276+ className : navStyles . active ,
167277 } }
168278 resetScroll
169279 >
0 commit comments