Skip to content

Commit c2c5161

Browse files
committed
Enhance footer and hero section with animated elements and typewriter effect
- Added a second canvas for animated scan-line effect in the footer. - Refactored animation logic to apply to both navbar and footer canvases. - Redesigned footer layout with improved navigation and action buttons. - Introduced typewriter effect for description text in the hero section. - Added new CSS animations for fade-in and shimmer effects. - Implemented social media icons with SVGs in the hero section. - Enhanced accessibility and visual feedback for buttons and links.
1 parent e6ea4fe commit c2c5161

3 files changed

Lines changed: 377 additions & 93 deletions

File tree

src/App.tsx

Lines changed: 157 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,33 @@ function App() {
2929

3030
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
3131
const scanRef = useRef<HTMLCanvasElement>(null)
32+
const footerScanRef = useRef<HTMLCanvasElement>(null)
3233

33-
// Animated scan-line canvas for threejs navbar bottom border
34+
// Animated scan-line canvas — shared animation logic, runs on both navbar and footer canvases
3435
useEffect(() => {
3536
if (!isThreejs) return
36-
const canvas = scanRef.current
37-
if (!canvas) return
38-
const ctx = canvas.getContext('2d')
39-
if (!ctx) return
37+
const canvases = [scanRef.current, footerScanRef.current].filter(Boolean) as HTMLCanvasElement[]
38+
if (!canvases.length) return
39+
4040
let frame: number
4141
let t = 0
4242
const draw = () => {
4343
frame = requestAnimationFrame(draw)
4444
t += 0.012
45-
const w = canvas.width
46-
ctx.clearRect(0, 0, w, 1)
47-
const grad = ctx.createLinearGradient(0, 0, w, 0)
48-
const pos = (Math.sin(t) * 0.5 + 0.5)
49-
const span = 0.28
50-
grad.addColorStop(Math.max(0, pos - span), 'rgba(59,130,246,0)')
51-
grad.addColorStop(pos, 'rgba(99,179,255,0.9)')
52-
grad.addColorStop(Math.min(1, pos + span), 'rgba(6,182,212,0)')
53-
ctx.fillStyle = grad
54-
ctx.fillRect(0, 0, w, 1)
45+
canvases.forEach((canvas) => {
46+
const ctx = canvas.getContext('2d')
47+
if (!ctx) return
48+
const w = canvas.width
49+
ctx.clearRect(0, 0, w, 1)
50+
const grad = ctx.createLinearGradient(0, 0, w, 0)
51+
const pos = Math.sin(t) * 0.5 + 0.5
52+
const span = 0.28
53+
grad.addColorStop(Math.max(0, pos - span), 'rgba(59,130,246,0)')
54+
grad.addColorStop(pos, 'rgba(99,179,255,0.9)')
55+
grad.addColorStop(Math.min(1, pos + span), 'rgba(6,182,212,0)')
56+
ctx.fillStyle = grad
57+
ctx.fillRect(0, 0, w, 1)
58+
})
5559
}
5660
draw()
5761
return () => cancelAnimationFrame(frame)
@@ -389,42 +393,146 @@ function App() {
389393
</main>
390394

391395
<footer className={footerClasses}>
392-
<div className="mx-auto flex max-w-5xl flex-col items-start justify-between gap-3 px-6 sm:flex-row sm:items-center">
393-
<div>
394-
<p>{footer.text}</p>
395-
<p className="mt-1 text-[11px] text-slate-500">{footer.subtleText}</p>
396+
{isThreejs ? (
397+
<div className="mx-auto max-w-5xl px-6 py-10">
398+
{/* Animated scan-line top edge */}
399+
<canvas
400+
ref={footerScanRef}
401+
width={1200}
402+
height={1}
403+
className="mb-8 w-full block"
404+
aria-hidden="true"
405+
style={{ height: 1 }}
406+
/>
407+
408+
<div className="flex flex-col gap-8 sm:flex-row sm:items-start sm:justify-between">
409+
{/* Left — logo + tagline */}
410+
<div className="flex flex-col gap-3">
411+
<Link to="/" className="group inline-flex items-center gap-2.5 no-underline">
412+
<span className="flex h-8 w-8 items-center justify-center rounded-xl bg-gradient-to-tr from-blue-600 to-cyan-400 text-xs font-semibold text-[#050509] ring-1 ring-blue-500/30 transition group-hover:ring-cyan-400/50">
413+
{navInitials}
414+
</span>
415+
<span className="text-xs font-semibold tracking-widest uppercase text-slate-400 transition group-hover:text-slate-200">
416+
{hero.title}
417+
</span>
418+
</Link>
419+
<p className="max-w-xs text-[11px] leading-relaxed text-slate-500">{footer.text}</p>
420+
{footer.subtleText && (
421+
<p className="text-[10px] text-slate-600">{footer.subtleText}</p>
422+
)}
423+
</div>
424+
425+
{/* Center — quick nav */}
426+
<nav aria-label="Footer navigation" className="flex flex-col gap-2">
427+
<p className="mb-1 text-[9px] font-bold uppercase tracking-[0.25em] text-slate-600">Navigate</p>
428+
{[
429+
{ to: '/', label: 'Home' },
430+
{ to: '/videos', label: 'Videos' },
431+
{ to: '/blogs', label: 'Blogs' },
432+
{ to: '/projects', label: 'Projects' },
433+
].map(({ to, label }) => (
434+
<Link
435+
key={to}
436+
to={to}
437+
className="text-[11px] text-slate-500 transition hover:text-blue-400"
438+
>
439+
{label}
440+
</Link>
441+
))}
442+
<a
443+
href={`${import.meta.env.BASE_URL}#stats`}
444+
className="text-[11px] text-slate-500 transition hover:text-blue-400"
445+
>
446+
Stats
447+
</a>
448+
</nav>
449+
450+
{/* Right — action buttons */}
451+
<div className="flex flex-col gap-3">
452+
<p className="mb-1 text-[9px] font-bold uppercase tracking-[0.25em] text-slate-600">Project</p>
453+
<a
454+
href="https://github.com/amide-init/gitfolio"
455+
target="_blank"
456+
rel="noreferrer"
457+
className="inline-flex items-center gap-1.5 rounded-md border border-amber-400/30 bg-amber-400/10 px-2.5 py-1 text-[11px] font-semibold text-amber-300 transition hover:bg-amber-400/20"
458+
>
459+
<svg viewBox="0 0 16 16" className="h-3.5 w-3.5 fill-current" aria-hidden="true">
460+
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.75.75 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.873 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z" />
461+
</svg>
462+
Star on GitHub
463+
</a>
464+
<a
465+
href="https://github.com/amide-init/gitfolio/fork"
466+
target="_blank"
467+
rel="noreferrer"
468+
className="inline-flex items-center gap-1.5 rounded-md border border-indigo-400/30 bg-indigo-400/10 px-2.5 py-1 text-[11px] font-semibold text-indigo-300 transition hover:bg-indigo-400/20"
469+
>
470+
<svg viewBox="0 0 16 16" className="h-3.5 w-3.5 fill-current" aria-hidden="true">
471+
<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" />
472+
</svg>
473+
Fork
474+
</a>
475+
<Link
476+
to="/admin"
477+
className="text-[11px] font-medium text-slate-600 transition hover:text-slate-400"
478+
>
479+
Admin ↗
480+
</Link>
481+
</div>
482+
</div>
483+
484+
{/* Bottom rule + copyright */}
485+
<div className="mt-8 flex flex-col items-center gap-1 border-t border-blue-900/20 pt-6 sm:flex-row sm:justify-between">
486+
<p className="text-[10px] text-slate-700">
487+
Built with{' '}
488+
<a href="https://github.com/amide-init/gitfolio" target="_blank" rel="noreferrer" className="text-slate-600 hover:text-blue-400 transition-colors">
489+
Gitfolio
490+
</a>
491+
</p>
492+
<div className="flex items-center gap-1.5">
493+
<span className="h-1 w-1 rounded-full bg-blue-500 opacity-60 animate-pulse" />
494+
<span className="text-[10px] text-slate-700 font-mono">threejs template</span>
495+
</div>
496+
</div>
396497
</div>
397-
<div className="flex flex-wrap items-center gap-2">
398-
<a
399-
href="https://github.com/amide-init/gitfolio"
400-
target="_blank"
401-
rel="noreferrer"
402-
className="inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-[11px] font-semibold transition border-amber-400/40 bg-amber-400/10 text-amber-500 hover:bg-amber-400/20 dark:border-amber-400/30 dark:text-amber-300 dark:hover:bg-amber-400/20"
403-
>
404-
<svg viewBox="0 0 16 16" className="h-3.5 w-3.5 fill-current" aria-hidden="true">
405-
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.75.75 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.873 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z" />
406-
</svg>
407-
Star
408-
</a>
409-
<a
410-
href="https://github.com/amide-init/gitfolio/fork"
411-
target="_blank"
412-
rel="noreferrer"
413-
className="inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-[11px] font-semibold transition border-indigo-400/40 bg-indigo-400/10 text-indigo-500 hover:bg-indigo-400/20 dark:border-indigo-400/30 dark:text-indigo-300 dark:hover:bg-indigo-400/20"
414-
>
415-
<svg viewBox="0 0 16 16" className="h-3.5 w-3.5 fill-current" aria-hidden="true">
416-
<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" />
417-
</svg>
418-
Fork
419-
</a>
420-
<Link
421-
to="/admin"
422-
className="text-[11px] font-medium text-slate-500 underline-offset-2 hover:underline dark:text-slate-400"
423-
>
424-
Admin
425-
</Link>
498+
) : (
499+
<div className="mx-auto flex max-w-5xl flex-col items-start justify-between gap-3 px-6 sm:flex-row sm:items-center">
500+
<div>
501+
<p>{footer.text}</p>
502+
<p className="mt-1 text-[11px] text-slate-500">{footer.subtleText}</p>
503+
</div>
504+
<div className="flex flex-wrap items-center gap-2">
505+
<a
506+
href="https://github.com/amide-init/gitfolio"
507+
target="_blank"
508+
rel="noreferrer"
509+
className="inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-[11px] font-semibold transition border-amber-400/40 bg-amber-400/10 text-amber-500 hover:bg-amber-400/20 dark:border-amber-400/30 dark:text-amber-300 dark:hover:bg-amber-400/20"
510+
>
511+
<svg viewBox="0 0 16 16" className="h-3.5 w-3.5 fill-current" aria-hidden="true">
512+
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.75.75 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.873 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z" />
513+
</svg>
514+
Star
515+
</a>
516+
<a
517+
href="https://github.com/amide-init/gitfolio/fork"
518+
target="_blank"
519+
rel="noreferrer"
520+
className="inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-[11px] font-semibold transition border-indigo-400/40 bg-indigo-400/10 text-indigo-500 hover:bg-indigo-400/20 dark:border-indigo-400/30 dark:text-indigo-300 dark:hover:bg-indigo-400/20"
521+
>
522+
<svg viewBox="0 0 16 16" className="h-3.5 w-3.5 fill-current" aria-hidden="true">
523+
<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" />
524+
</svg>
525+
Fork
526+
</a>
527+
<Link
528+
to="/admin"
529+
className="text-[11px] font-medium text-slate-500 underline-offset-2 hover:underline dark:text-slate-400"
530+
>
531+
Admin
532+
</Link>
533+
</div>
426534
</div>
427-
</div>
535+
)}
428536
</footer>
429537
</div>
430538
)

src/index.css

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,26 @@
77
to { opacity: 1; }
88
}
99

10+
@keyframes fadeInUp {
11+
from { opacity: 0; transform: translateY(22px); }
12+
to { opacity: 1; transform: translateY(0); }
13+
}
14+
15+
@keyframes fadeInRight {
16+
from { opacity: 0; transform: translateX(-16px); }
17+
to { opacity: 1; transform: translateX(0); }
18+
}
19+
20+
@keyframes shimmer {
21+
0% { background-position: -200% center; }
22+
100% { background-position: 200% center; }
23+
}
24+
25+
@keyframes blink {
26+
0%, 100% { opacity: 1; }
27+
50% { opacity: 0; }
28+
}
29+
1030
@layer base {
1131
body {
1232
@apply min-h-screen bg-slate-50 text-slate-900 antialiased;

0 commit comments

Comments
 (0)