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.
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>
);
}
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;
Output
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",
},
];
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;
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>
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" : ""
}`}
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>
);
}
So this is how we can implement navbar in server layout component in nextjs .
Hope this was helpful , thanks!!
Top comments (0)