DEV Community

Cover image for Creating Blog Tutorial Using Next.JS 15 & TailwindCSS 4.0 (Part #5)
gerry leo nugroho
gerry leo nugroho

Posted on

Creating Blog Tutorial Using Next.JS 15 & TailwindCSS 4.0 (Part #5)

Welcome back, blog architects! We’ve laid down our core layout components, setting a sleek foundation with a blurry navbar, multi-column footer, and tailored page layouts. Now, let’s amp up the UX with Navigation, Cards & Grids, and some Interactive Elements, channeling modern’s bold aesthetic—think responsive menus, animated cards, and engaging hover effects. We're going wild with loads of creativity here, leveraging Next.js 15.x.x’s server-side magic and Tailwind CSS 4.x.x’s modern utilities, all while ensuring the code is digestible for newbies and SEO-optimized. Let’s dive into this vibrant continuation!


Navigation: Guiding Users with Style

Navigation is the compass of our blog—intuitive, responsive, and visually striking. We’ll craft a desktop menu with dropdowns, a mobile off-canvas menu, SEO-friendly breadcrumbs, and dynamic pagination.

src/components/DesktopMenu.tsx – Horizontal Menu with Dropdowns

"use client"; // Client-side for dropdown interactivity import Link from "next/link"; import { useState } from "react"; import { FaChevronDown } from "react-icons/fa"; export default function DesktopMenu() { const [isDropdownOpen, setIsDropdownOpen] = useState(false); // Tracks dropdown state return ( <nav> {/* Simple Links */} <Link href="/about">About</Link> <Link href="/blog">Blog</Link> {/* Dropdown Menu */} <div onMouseEnter={() => setIsDropdownOpen(true)} onMouseLeave={() => setIsDropdownOpen(false)} > Categories {isDropdownOpen && ( <ul> <li>Tech</li> <li>Lifestyle</li> <li>Coding</li> </ul> )} </div> <Link href="/search">Search</Link> </nav> ); } 
Enter fullscreen mode Exit fullscreen mode

Why It’s Awesome

  • Dropdown: A hover-triggered menu with backdrop-blur-md for a glassy effect, fading in/out smoothly.
  • Hover Effects: Links scale up with hover:scale-105—a subtle nod to modern design’s interactivity.
  • Accessibility: ARIA attributes enhance screen reader support.

src/components/MobileMenu.tsx – Off-Canvas with Animations

Already integrated into BlurNavbar.tsx from the last section—its off-canvas design uses translate-y animations for a slick mobile experience.


src/components/Breadcrumbs.tsx – SEO-Friendly Navigation

import Link from "next/link"; type Crumb = { label: string; href: string }; export default function Breadcrumbs({ crumbs }: { crumbs: Crumb[] }) { return ( <nav> <Link href="/">Home</Link> {crumbs.map((crumb, index) => ( <span key={crumb.href}> / {index === crumbs.length - 1 ? ( <span>{crumb.label}</span> ) : ( <Link href={crumb.href}>{crumb.label}</Link> )} </span> ))} </nav> ); } 
Enter fullscreen mode Exit fullscreen mode

Usage Example

In src/app/blog/[slug]/page.tsx, add:

<Breadcrumbs crumbs={[ { label: "Blog", href: "/blog" }, { label: "Post Title", href: "/blog/post-title" }, ]} /> 
Enter fullscreen mode Exit fullscreen mode

Why It Shines

  • SEO: Links improve crawlability; the final crumb is text-only for current page semantics.
  • Responsive: Wraps gracefully on small screens.

src/components/Pagination.tsx – Dynamic Pagination

"use client"; import Link from "next/link"; import { usePathname, useSearchParams } from "next/navigation"; export default function Pagination({ totalPages, basePath, }: { totalPages: number; basePath: string; }) { const pathname = usePathname(); const searchParams = useSearchParams(); const currentPage = Number(searchParams.get("page")) || 1; const pages = Array.from({ length: totalPages }, (_, i) => i + 1); return ( <div> {pages.map((page) => ( <Link key={page} href={`${pathname}?page=${page}`} className={currentPage === page ? "active" : ""} > {page} </Link> ))} </div> ); } 
Enter fullscreen mode Exit fullscreen mode

Usage Example

In src/app/blog/page.tsx, add:

<Pagination totalPages={10} basePath="/blog" /> 
Enter fullscreen mode Exit fullscreen mode

Why It’s Great

  • Dynamic: Uses Next.js’s useSearchParams for page tracking.
  • Styling: Rounded buttons with hover transitions aligned with modern web design polish.

Cards & Grids: Visual Storytelling

Cards are the heartbeat of our blog’s content—responsive, interactive, and eye-catching.

src/components/PostCard.tsx – Enhanced from Last Section

Updated with more flair:

import Link from "next/link"; import Image from "next/image"; type Post = { slug: string; frontmatter: { title: string; description: string; imageOg?: string; category: string; }; }; export default function PostCard({ post, variant = "grid", }: { post: Post; variant?: "grid" | "list"; }) { return ( <div> {/* Image with Hover Zoom */} {post.frontmatter.imageOg && ( <Image src={post.frontmatter.imageOg} alt={post.frontmatter.title} width={300} height={200} className="hover:scale-105 transition-transform" /> )} {/* Content */} <div> <span>{post.frontmatter.category}</span> <h3>{post.frontmatter.title}</h3> <p>{post.frontmatter.description}</p> </div> </div> ); } 
Enter fullscreen mode Exit fullscreen mode

What’s New?

  • Category Badge: A rounded tag adds visual hierarchy.
  • Hover Effects: Card lifts with hover:shadow-xl and image zooms—pure modern design's energy.
  • Responsive Images: sizes attribute optimizes image loading.

src/components/CategoryCard.tsx – Category Highlights

import Link from "next/link"; export default function CategoryCard({ category, count, }: { category: string; count: number; }) { return ( <div> {/* Overlay Effect */} <div> <span>{category}</span> <span>{count} Posts</span> </div> </div> ); } 
Enter fullscreen mode Exit fullscreen mode

Usage Example

In src/app/page.tsx’s trending section:

<CategoryCard category="Tech" count={15} /> 
Enter fullscreen mode Exit fullscreen mode

Why It Pops

  • Gradient: A bold background with a hover overlay adds depth.
  • Relative Positioning: Ensures text stays above the overlay.

src/components/AuthorCard.tsx – Author Spotlight

import Image from "next/image"; import { FaTwitter, FaLinkedin } from "react-icons/fa"; export default function AuthorCard({ name, bio, avatar, twitter, linkedin, }: { name: string; bio: string; avatar: string; twitter?: string; linkedin?: string; }) { return ( <div> <Image src={avatar} alt={name} width={100} height={100} /> <h3>{name}</h3> <p>{bio}</p> {twitter && <a href={twitter}><FaTwitter /></a>} {linkedin && <a href={linkedin}><FaLinkedin /></a>} </div> ); } 
Enter fullscreen mode Exit fullscreen mode

Why It Works

  • Compact: A clean layout for author bios, with social icons for engagement.
  • Dark Mode: Tailwind’s dark: classes ensure readability.

Interactive Elements: Engaging Users

Let’s add some interactivity with hover effects and reusable components.

src/components/HoverImage.tsx – Image with Zoom

import Image from "next/image"; export default function HoverImage({ src, alt, width, height, }: { src: string; alt: string; width: number; height: number; }) { return ( <div className="group"> <Image src={src} alt={alt} width={width} height={height} className="group-hover:scale-110 transition-transform" loading="lazy" /> </div> ); } 
Enter fullscreen mode Exit fullscreen mode

Why It’s Engaging

  • Zoom: group-hover:scale-110 creates a subtle, inviting effect.
  • Lazy Loading: Native loading="lazy" boosts performance.

src/components/Tooltip.tsx – Contextual Info

"use client"; import { useState } from "react"; export default function Tooltip({ content, children, }: { content: string; children: React.ReactNode; }) { const [isVisible, setIsVisible] = useState(false); return ( <div onMouseEnter={() => setIsVisible(true)} onMouseLeave={() => setIsVisible(false)} > {children} {isVisible && <span>{content}</span>} </div> ); } 
Enter fullscreen mode Exit fullscreen mode

Usage Example

<Tooltip content="This is a tooltip"> <button>Click here</button> </Tooltip> 
Enter fullscreen mode Exit fullscreen mode

Why It’s Handy

  • Simple: A hover-triggered tooltip with Tailwind styling.
  • Accessible: Naturally works with mouse and touch (though keyboard support could be added).

To Be Continued

We’ve tackled Navigation, Cards & Grids, and started Interactive Elements—all with modern-design-inspired flair, responsive design, and SEO-friendly code. This is part two of a multi-part journey due to the epic scope you’ve set!


Top comments (0)