The navigation system consists of two main components: the primary Navigation component and the MobileNav component for responsive mobile experiences.
Navigation Component
Overview
The primary navigation component (Navigation.tsx) provides a sticky header with branding, social links, and mobile menu toggle. It features a Spotify-inspired rounded design with smooth transitions.
Location: src/app/components/Navigation.tsx
Features
- Responsive design with mobile hamburger menu
- Typewriter animation for site name
- Integration with social media links
- Blog navigation link
- Accessibility attributes (ARIA labels)
Implementation
export default function Navigation(): ReactNode {
const [mobile, setMobile] = useState<boolean>(false);
function handleMobile(): void {
setMobile((prev) => !prev);
}
return (
<nav aria-label="Primary navigation">
<div className="flex flex-col bg-spotify-light-dark max-md:mx-2 max-md:mt-2 mx-32 mt-4 p-2 rounded-full max-md:rounded-xl">
{/* Navigation content */}
</div>
</nav>
);
}
Key Elements
State variable controlling mobile menu visibility
Toggle function for opening/closing mobile menu
Logo and Branding
The logo section uses a typewriter effect with the developer’s name:
<Link href="/" className="flex gap-2 text-3xl font-bold items-center">
<FaCode className="text-spotify-green w-[70px]" />
<TypewriterEffect
words={[
{ text: "Luan", className: "text-4xl" },
{ text: "Nguyen", className: "text-4xl" },
]}
className="place-self-center max-lg:hidden text-white"
/>
</Link>
The typewriter effect is hidden on mobile devices using the max-lg:hidden class to save space.
Desktop Navigation
Desktop navigation includes social links and blog access:
<section className="flex flex-row gap-4 items-center max-sm:hidden mx-4">
<SocialLinks />
<PiLineVerticalThin className="text-spotify-gray text-4xl" />
<Link
href="/blog"
className="text-3xl hover:text-spotify-green transition-colors duration-200"
aria-label="View blog posts"
>
<LuNewspaper />
</Link>
</section>
<button
type="button"
onClick={handleMobile}
className="sm:hidden"
aria-label={mobile ? "Close navigation menu" : "Open navigation menu"}
aria-expanded={mobile}
aria-controls="mobile-navigation"
>
{mobile ? (
<FaTimes className="text-4xl" aria-hidden="true" />
) : (
<GiHamburgerMenu className="text-4xl" aria-hidden="true" />
)}
</button>
MobileNav Component
Overview
The MobileNav component provides a slide-down menu for mobile devices with animated navigation links.
Location: src/app/components/MobileNav.tsx
Props Interface
interface MobileNavProps {
handleMobile: () => void;
}
Callback function to close the mobile menu when a link is clicked
Implementation
export default function MobileNav({ handleMobile }: MobileNavProps) {
const pathname = usePathname();
const isOnBlogPage = pathname?.startsWith("/blog");
const links = [
{
section: "Experience",
href: isOnBlogPage ? "/#experience" : "#experience",
},
{
section: "Programming Languages",
href: isOnBlogPage ? "/#programming-languages" : "#programming-languages",
},
{ section: "Projects", href: isOnBlogPage ? "/#project" : "#project" },
{
section: "Contributions",
href: isOnBlogPage ? "/#contribution" : "#contribution",
},
];
return (
<nav id="mobile-navigation" aria-label="Mobile navigation">
{/* Navigation links */}
</nav>
);
}
Features
Dynamic Routing
The component detects the current page and adjusts links accordingly:
const pathname = usePathname();
const isOnBlogPage = pathname?.startsWith("/blog");
// Links adjust based on current page
href: isOnBlogPage ? "/#experience" : "#experience"
When on the blog page, links use absolute paths (/) to return to the home page before navigating to sections.
Staggered Animation
Menu items animate in with staggered delays:
<li
className="hover:bg-spotify-green/10 rounded-lg transition-all duration-200 ease-in-out hover:translate-x-2 animate-in slide-in-from-left-2"
style={{
animationDelay: `${(index + 1) * 100}ms`,
animationFillMode: "both",
}}
>
<Link
href={link.href}
className="block p-4 text-spotify-white text-lg font-semibold hover:text-spotify-green transition-colors duration-200"
onClick={handleMobile}
>
{link.section}
</Link>
</li>
Navigation Links
The mobile menu includes quick access to:
- Experience: Professional work history
- Programming Languages: Technology proficiencies
- Projects: Portfolio showcase
- Contributions: GitHub activity
- Blog: Blog posts (with icon)
- Social Links: GitHub, LinkedIn, Twitter/X
Accessibility
Both navigation components include comprehensive ARIA labels and attributes for screen reader support.
aria-label="View blog posts"
aria-expanded={mobile}
aria-controls="mobile-navigation"
aria-hidden="true" // For decorative icons
Styling
Color Scheme
- Background:
bg-spotify-light-dark (#121212)
- Accent:
text-spotify-green (#1DB954)
- Text:
text-spotify-white (#FFFFFF)
- Muted text:
text-spotify-grey (#B3B3B3)
Responsive Breakpoints
- Mobile menu: Shows below
640px (sm)
- Desktop nav: Shows above
640px (sm)
- Logo text: Hidden below
1024px (lg)
- Rounded design: Changes from
rounded-full to rounded-xl on mobile
Dependencies
{
"react-icons": "Icon library (FaCode, GiHamburgerMenu, FaTimes, LuNewspaper)",
"next/link": "Client-side navigation",
"next/navigation": "usePathname hook for route detection",
"framer-motion": "Animation library (via TypewriterEffect component)"
}