Page Layout and Header

Setting up the page layout and the transparent header for the static site with blog using NextJS, React with Radix UI and Shadcn UI.


Components

The initial version of the main layout contains the navigation menu. src/components/main-nav.tsx:

import { MainNav } from "./main-nav";
 
export function SiteHeader() {
  return (
    <header className="sticky top-0 w-full border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
      <div className="container flex h-14 max-w-screen-2xl items-center">
        <MainNav />
        <div className="flex flex-1 items-center justify-end space-x-2">
          <nav className="flex items-center">
            {/* Placeholder for buttons to be added */}
          </nav>
        </div>
      </div>
    </header>
  );
}

The main navigation initially includes links to the blog and the about page. We use the usePathname function to get the relative URL of the current page and use it to highlight the current menu item. src/components/site-header.tsx:

"use client";
 
import Link from "next/link";
import { usePathname } from "next/navigation";
import { cn } from "@/lib/utils";
 
export function MainNav() {
  const pathname = usePathname();
  return (
    <nav className="flex items-center space-x-4 lg:space-x-6">
      <Link
        href="/blog"
        className={cn(
          "text-sm font-medium transition-colors hover:text-primary",
          pathname === "/blog" ? "text-foreground" : "text-foreground/60"
        )}
      >
        Blog
      </Link>
      <Link
        href="/about"
        className={cn(
          "text-sm font-medium transition-colors hover:text-primary",
          pathname === "/about" ? "text-foreground" : "text-foreground/60"
        )}
      >
        About
      </Link>
    </nav>
  );
}

Main Layout

The main layout contains the header on top and then display the individual page contents. src/app/layout.tsx:

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { SiteHeader } from "@/components/site-header";
 
const inter = Inter({ subsets: ["latin"] });
 
export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};
 
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className="min-h-screen bg-background font-sans antialiased">
        <div className="relative flex min-h-dvh flex-col bg-background">
          <SiteHeader />
          <main className="flex-1">{children}</main>
        </div>
      </body>
    </html>
  );
}
 

The main page is also excised of the initial next boilerplate code. src/app/page.tsx:

export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <section>A sign of things to come</section>
    </main>
  );
}


Last Updated: