Skip to main content
The navigation system consists of two main components: the primary Navigation component and the MobileNav component for responsive mobile experiences.

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

mobile
boolean
State variable controlling mobile menu visibility
handleMobile
function
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>

Mobile Menu Toggle

<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;
}
handleMobile
() => void
required
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>
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)"
}

Build docs developers (and LLMs) love