@@ -3,6 +3,18 @@ import { Link, Outlet, useLocation, useNavigate } from 'react-router-dom'
33import siteContent from './siteContent.json'
44import { githubConfig } from './generated/githubData'
55import { activeTemplate } from './lib/activeTemplate'
6+ import { NavSearch } from './components/NavSearch'
7+
8+ const FORK_URL = 'https://github.com/amide-init/gitfolio/fork'
9+
10+ // Fork SVG icon (GitHub fork icon)
11+ function ForkIcon ( { className } : { className ?: string } ) {
12+ return (
13+ < svg viewBox = "0 0 16 16" className = { className ?? 'h-3 w-3 fill-current' } aria-hidden = "true" >
14+ < path d = "M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z" />
15+ </ svg >
16+ )
17+ }
618
719type Theme = 'dark' | 'light'
820
@@ -27,6 +39,8 @@ function App() {
2739 // threejs template gets sci-fi HUD navbar
2840 const isThreejs = template === 'threejs'
2941
42+ const showSearch = ( githubConfig as { showSearch ?: boolean } ) . showSearch !== false
43+
3044 const [ mobileMenuOpen , setMobileMenuOpen ] = useState ( false )
3145 const scanRef = useRef < HTMLCanvasElement > ( null )
3246 const footerScanRef = useRef < HTMLCanvasElement > ( null )
@@ -242,13 +256,29 @@ function App() {
242256 </ a >
243257 </ nav >
244258
245- { /* Mobile hamburger */ }
246- < button
247- type = "button"
248- onClick = { ( ) => setMobileMenuOpen ( ( prev ) => ! prev ) }
249- className = "md:hidden flex h-8 w-8 items-center justify-center rounded-md text-slate-400 hover:text-slate-100 hover:bg-white/5 transition"
250- aria-label = { mobileMenuOpen ? 'Close menu' : 'Open menu' }
251- >
259+ { /* Right-side controls: search + claim + hamburger */ }
260+ < div className = "flex items-center gap-2" >
261+ { /* Search */ }
262+ { showSearch && < NavSearch variant = "threejs" /> }
263+
264+ { /* Claim / Fork CTA */ }
265+ < a
266+ href = { FORK_URL }
267+ target = "_blank"
268+ rel = "noreferrer"
269+ className = "hidden sm:inline-flex items-center gap-1.5 rounded-md border border-indigo-500/30 bg-indigo-500/10 px-2.5 py-1 text-[11px] font-semibold text-indigo-300 transition hover:bg-indigo-500/20 hover:border-indigo-400/50"
270+ >
271+ < ForkIcon className = "h-3 w-3 fill-current" />
272+ Fork & deploy
273+ </ a >
274+
275+ { /* Mobile hamburger */ }
276+ < button
277+ type = "button"
278+ onClick = { ( ) => setMobileMenuOpen ( ( prev ) => ! prev ) }
279+ className = "md:hidden flex h-8 w-8 items-center justify-center rounded-md text-slate-400 hover:text-slate-100 hover:bg-white/5 transition"
280+ aria-label = { mobileMenuOpen ? 'Close menu' : 'Open menu' }
281+ >
252282 { mobileMenuOpen ? (
253283 < svg className = "h-5 w-5" fill = "none" viewBox = "0 0 24 24" stroke = "currentColor" strokeWidth = { 2 } >
254284 < path strokeLinecap = "round" strokeLinejoin = "round" d = "M6 18L18 6M6 6l12 12" />
@@ -258,8 +288,9 @@ function App() {
258288 < path strokeLinecap = "round" strokeLinejoin = "round" d = "M4 6h16M4 12h16M4 18h16" />
259289 </ svg >
260290 ) }
261- </ button >
262- </ div >
291+ </ button >
292+ </ div > { /* end right-side controls */ }
293+ </ div > { /* end header inner */ }
263294
264295 { /* Animated scan-line bottom border */ }
265296 < canvas ref = { scanRef } width = { 1200 } height = { 1 } className = "w-full block" aria-hidden = "true" style = { { height : 1 } } />
@@ -291,6 +322,23 @@ function App() {
291322 >
292323 Stats
293324 </ a >
325+ { /* Mobile: Fork CTA */ }
326+ < a
327+ href = { FORK_URL }
328+ target = "_blank"
329+ rel = "noreferrer"
330+ onClick = { ( ) => setMobileMenuOpen ( false ) }
331+ className = "border-t border-blue-900/20 py-2.5 flex items-center gap-2 text-sm font-medium text-indigo-400 hover:text-indigo-300 transition-colors"
332+ >
333+ < ForkIcon className = "h-3.5 w-3.5 fill-current" />
334+ Fork & deploy your own
335+ </ a >
336+ { /* Mobile: Search */ }
337+ { showSearch && (
338+ < div className = "border-t border-blue-900/20 py-2.5" >
339+ < NavSearch variant = "threejs" />
340+ </ div >
341+ ) }
294342 </ div >
295343 </ nav >
296344 ) }
@@ -348,6 +396,26 @@ function App() {
348396 </ nav >
349397 ) }
350398
399+ { /* Desktop: search + claim (hidden on mobile) */ }
400+ < div className = "hidden md:flex items-center gap-2" >
401+ { showSearch && < NavSearch variant = "default" /> }
402+ < a
403+ href = { FORK_URL }
404+ target = "_blank"
405+ rel = "noreferrer"
406+ className = { `inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-[11px] font-semibold transition ${
407+ isHacker
408+ ? 'border-green-900 bg-green-950/40 text-green-600 hover:bg-green-900/30'
409+ : isNetflix
410+ ? 'border-white/10 bg-white/5 text-[#e5e5e5] hover:bg-white/10'
411+ : 'border-indigo-300/60 bg-indigo-50 text-indigo-600 hover:bg-indigo-100 dark:border-indigo-500/30 dark:bg-indigo-500/10 dark:text-indigo-300 dark:hover:bg-indigo-500/20'
412+ } `}
413+ >
414+ < ForkIcon className = "h-3 w-3 fill-current" />
415+ Fork & deploy
416+ </ a >
417+ </ div >
418+
351419 { /* Mobile controls: hamburger */ }
352420 < div className = "flex items-center gap-2 md:hidden" >
353421 < button
@@ -381,6 +449,23 @@ function App() {
381449 < Link to = "/blogs" onClick = { ( ) => setMobileMenuOpen ( false ) } className = { `border-t py-2.5 transition-colors ${ isHacker ? 'border-green-900/40 hover:text-green-400' : isNetflix ? 'border-white/5 hover:text-white' : 'border-slate-200/60 hover:text-slate-900 dark:border-white/5 dark:hover:text-slate-50' } ` } > Blogs</ Link >
382450 < Link to = "/projects" onClick = { ( ) => setMobileMenuOpen ( false ) } className = { `border-t py-2.5 transition-colors ${ isHacker ? 'border-green-900/40 hover:text-green-400' : isNetflix ? 'border-white/5 hover:text-white' : 'border-slate-200/60 hover:text-slate-900 dark:border-white/5 dark:hover:text-slate-50' } ` } > Projects</ Link >
383451 < a href = { `${ import . meta. env . BASE_URL } #stats` } onClick = { ( ) => setMobileMenuOpen ( false ) } className = { `border-t py-2.5 transition-colors ${ isHacker ? 'border-green-900/40 hover:text-green-400' : isNetflix ? 'border-white/5 hover:text-white' : 'border-slate-200/60 hover:text-slate-900 dark:border-white/5 dark:hover:text-slate-50' } ` } > { isHacker ? '~/stats' : 'Stats' } </ a >
452+ { /* Mobile: Fork CTA */ }
453+ < a
454+ href = { FORK_URL }
455+ target = "_blank"
456+ rel = "noreferrer"
457+ onClick = { ( ) => setMobileMenuOpen ( false ) }
458+ className = { `border-t py-2.5 flex items-center gap-2 transition-colors ${ isHacker ? 'border-green-900/40 text-green-600 hover:text-green-400' : isNetflix ? 'border-white/5 text-[#e5e5e5] hover:text-white' : 'border-slate-200/60 text-indigo-500 hover:text-indigo-700 dark:border-white/5 dark:text-indigo-400 dark:hover:text-indigo-300' } ` }
459+ >
460+ < ForkIcon className = "h-3.5 w-3.5 fill-current" />
461+ Fork & deploy your own
462+ </ a >
463+ { /* Mobile: Search */ }
464+ { showSearch && (
465+ < div className = "border-t py-2.5 dark:border-white/5 border-slate-200/60" >
466+ < NavSearch variant = "default" />
467+ </ div >
468+ ) }
384469 </ div >
385470 </ nav >
386471 ) }
0 commit comments