Tailwind CSS also provides utilities for interactions and transitions, enabling smooth animations. Additionally, its customization options and supportive community enhance the functionality and integration of flyout menus within a broader application ecosystem.
Here is the GitHub repo with the entire code. Below, you will find the link to the example page.
Example page hosted on Vercel -> https://nextjs14-contentful-syntax-highlighting.vercel.app/
Used Stack
I will start with my default stack:
Next.js 14 as the web framework, and I will use the provided middleware edge function
TailwindCss for Styling
Contentful CMS (Free Plan)
Vercel for hosting
Adapting Navigation-Component for the Flyout Menu
We adapt the file src/components/header/navbar.component.tsx and start with some new imports.
import { Popover } from "@headlessui/react";
import { ChevronDownIcon } from "@heroicons/react/20/solid";
import {
BookmarkSquareIcon,
CalendarDaysIcon,
LifebuoyIcon,
} from "@heroicons/react/24/outline";We proceed with a new const, which is static in this example and will be replaced in a follow-up with data coming from Contentful (headless CMS).
const resources = [
{
name: "Overview",
description: "Learn how to maximize our platform",
href: "/seo-tools",
icon: BookmarkSquareIcon,
},
{
name: "Slugify",
description: "Get all of your questions answered",
href: "/seo-tools/slugify",
icon: LifebuoyIcon,
},
];Desktop Menu
Now follows the integration of the menu for the desktop breakpoint (Row Number 207)
<Popover className="relative">
<Popover.Button className="border-transparent text-gray-500 dark:text-gray-50 hover:border-gray-300 hover:text-gray-700 inline-flex items-center text-base px-1 pt-1 border-b-2 font-medium">
<span>Seo-Tools</span>
<ChevronDownIcon className="w-5 h-5" aria-hidden="true" />
</Popover.Button>
<Popover.Panel className="absolute left-1/2 z-10 mt-5 flex w-screen max-w-max -translate-x-1/2 px-4 transition data-[closed]:translate-y-1 data-[closed]:opacity-0 data-[enter]:duration-200 data-[leave]:duration-150 data-[enter]:ease-out data-[leave]:ease-in">
<div className="flex-auto w-screen max-w-md overflow-hidden text-sm leading-6 bg-white shadow-lg rounded-3xl ring-1 ring-gray-900/5">
<div className="p-4">
{resources.map((item) => (
<div
key={item.name}
className="relative flex p-4 rounded-lg group gap-x-6 hover:bg-gray-50"
>
<div className="flex items-center justify-center flex-none mt-1 rounded-lg h-11 w-11 bg-gray-50 group-hover:bg-white">
<item.icon
className="w-6 h-6 text-gray-600 group-hover:text-indigo-600"
aria-hidden="true"
/>
</div>
<div>
<a
href={item.href}
className="font-semibold text-gray-900"
>
{item.name}
<span className="absolute inset-0" />
</a>
<p className="mt-1 text-gray-600">
{item.description}
</p>
</div>
</div>
))}
</div>
</div>
</Popover.Panel>
</Popover>Mobile Menu
Last but not least, we integrate the menu for the mobile breakpoint (Row Number 461)
<Popover className="relative">
<Popover.Button className="border-transparent text-gray-600 dark:text-gray-100 hover:bg-gray-100 dark:hover:text-indigo-700 hover:border-gray-300 hover:text-gray-800 block pl-3 pr-4 py-2 border-l-4 text-base font-medium">
<span>Seo-Tools</span>
<ChevronDownIcon className="w-5 h-5" aria-hidden="true" />
</Popover.Button>
<Popover.Panel className="absolute left-1/2 z-10 mt-5 flex w-screen max-w-max -translate-x-1/2 px-4 transition data-[closed]:translate-y-1 data-[closed]:opacity-0 data-[enter]:duration-200 data-[leave]:duration-150 data-[enter]:ease-out data-[leave]:ease-in">
<div className="flex-auto w-screen max-w-md overflow-hidden text-sm leading-6 bg-white shadow-lg rounded-3xl ring-1 ring-gray-900/5">
<div className="p-4">
{resources.map((item) => (
<div
key={item.name}
className="relative flex p-4 rounded-lg group gap-x-6 hover:bg-gray-50"
>
<div className="flex items-center justify-center flex-none mt-1 rounded-lg h-11 w-11 bg-gray-50 group-hover:bg-white">
<item.icon
className="w-6 h-6 text-gray-600 group-hover:text-indigo-600"
aria-hidden="true"
/>
</div>
<div>
<a
href={item.href}
className="font-semibold text-gray-900"
>
{item.name}
<span className="absolute inset-0" />
</a>
<p className="mt-1 text-gray-600">
{item.description}
</p>
</div>
</div>
))}
</div>
</div>
</Popover.Panel>
</Popover>Final Result
It’s very easy and straightforward. In a follow-up story, we will improve it and connect the needed menu point with the Contentful CMS, so stay tuned.

Cloudapp-dev, and before you leave us
Thank you for reading until the end. Before you go:


