DEV Community

Cover image for Next.js Tutorial : Adding Navbar with active Styling in a Server Component Layout
Vipin Chandra
Vipin Chandra

Posted on

Next.js Tutorial : Adding Navbar with active Styling in a Server Component Layout

The recent and major update in Next.js is the App router.

App router provides and facilitate a way to structure your pages in a reusable manner , such example are like not-found.tsx , loading.tsx and layout.tsx.

Every web app have some common pieces that are need to available in all the page of the application or parts of it.

Such one example is Navigation bar.

With Nextjs , we can leverage the use of layout.tsx to add Navigation bar in all the pages.

In nextjs , all the pages are by default server-components

And if we are looking to use layout.tsx , we need to make sure that its a server component as well because layout.tsx will wrap all the other sub route pages ex: /about , /user , /settings.

The navbar that we want to include in a layout will be a client-component and the reason behind is that it will involve client interaction (clicking) and also we need to have active state.

So this is how the component hierarchy will be structured.

hierarchy

So lets get into the action , before we create the navbar component.

lets take a look on the layout.tsx , for styles we are using tailwindcss.

import type { Metadata } from "next";
import "./globals.css";
import Head from "next/head";
import { Poppins } from "next/font/google";

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

const poppins = Poppins({
  subsets: ["latin"],
  weight: ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
  display: "swap",
  variable: "--font-poppins",
});

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
      <html lang="en" className={`${poppins.variable}`}>
        <Head>
          <link rel="preconnect" href="https://fonts.googleapis.com" />
          <link rel="preconnect" href="https://fonts.gstatic.com" />
          <link
            href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
            rel="stylesheet"
          />
        </Head>
        <body className="font-poppins antialiased p-4 container md:mx-auto md:p-10 bg-spotify-black">
          {children}
        </body>
      </html>
  );
}

Enter fullscreen mode Exit fullscreen mode

This will be the root layout of all the pages.

Now we will create the navbar.tsx


"use client";

import Link from "next/link";
import React from "react";
import { usePathname } from "next/navigation";
import { Url } from "next/dist/shared/lib/router/router";

interface INavbarProps {}

const navItems = [
  {
    id: "home",
    label: "Home",
    href: "/home",
  },
  {
    id: "about",
    label: "About",
    href: "/about",
  },
  {
    id: "settings",
    label: "Settings",
    href: "/settings",
  },
];

const Navbar: React.FunctionComponent<INavbarProps> = (props) => {
  const pathname = usePathname();
  const isActive = (path: Url) => pathname === path;

  return (
    <nav className="pb-4 md:pb-8 flex justify-between items-center">
      <Link
        href="/"
        className="text-lg md:text-3xl font-bold text-spotify-green"
      >
        webapp
      </Link>
     <ul className="flex justify-end items-center gap-4">
        {navItems.map((eachItem) => (
          <li key={eachItem.id}>
            <Link
              href={eachItem.href}
              className={`${
                isActive(eachItem.href) ? "text-spotify-green" : ""
              }`}
            >
              {eachItem.label}
            </Link>
          </li>
        ))}
      </ul>
    </nav>
  );
};

export default Navbar;



Enter fullscreen mode Exit fullscreen mode

Output

result


Let's breakdown the navbar.tsx and understand its bits and pieces.

1. Make this a client component using "use client";

2. Setting Up Navigation Items

Define your navigation items in an array. Each item includes an id, label, and href.

const navItems = [
  {
    id: "home",
    label: "Home",
    href: "/home",
  },
  {
    id: "about",
    label: "About",
    href: "/about",
  },
  {
    id: "settings",
    label: "Settings",
    href: "/settings",
  },
];

Enter fullscreen mode Exit fullscreen mode

3. Using usePathname to Get the Current Path

Next.js provides the usePathname hook from next/navigation to retrieve the current path. You can use this to determine if a link is active.


import { usePathname } from "next/navigation";
import { Url } from "next/dist/shared/lib/router/router";

const isActive = (path: Url) => pathname === path;

Enter fullscreen mode Exit fullscreen mode

4. Iterate through all the navItems in the component


<ul className="flex justify-end items-center gap-4">
        {navItems.map((eachItem) => (
          <li key={eachItem.id}>
            <Link
              href={eachItem.href}
              className={`${
                isActive(eachItem.href) ? "text-spotify-green" : ""
              }`}
            >
              {eachItem.label}
            </Link>
          </li>
        ))}
</ul>

Enter fullscreen mode Exit fullscreen mode

5. Styling Active Links

In the code above, the isActive function checks if the current path matches the link’s href. When active, a specific class (text-spotify-green) is added to style the link.


className={`${
  isActive(eachItem.href) ? "text-spotify-green" : ""
}`}

Enter fullscreen mode Exit fullscreen mode

Lets add the navbar.tsx component to our layout.tsx

import type { Metadata } from "next";
import "./globals.css";
import Head from "next/head";
import { Poppins } from "next/font/google";
import Navbar from "@src/components/Navbar";

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

const poppins = Poppins({
  subsets: ["latin"],
  weight: ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
  display: "swap",
  variable: "--font-poppins",
});

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
      <html lang="en" className={`${poppins.variable}`}>
        <Head>
          <link rel="preconnect" href="https://fonts.googleapis.com" />
          <link rel="preconnect" href="https://fonts.gstatic.com" />
          <link
            href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
            rel="stylesheet"
          />
        </Head>
        <body className="font-poppins antialiased p-4 container md:mx-auto md:p-10 bg-spotify-black">
          <Navbar/>
          {children}
        </body>
      </html>
  );
}

Enter fullscreen mode Exit fullscreen mode

So this is how we can implement navbar in server layout component in nextjs .

Hope this was helpful , thanks!!

Top comments (0)