Bottom Navigation
Premium Tailwind bottom navigation bars optimized for mobile web apps, featuring active state micro-animations and glassmorphism.
Install via CLI
Run this command to automatically add the component and its dependencies to your project.
npx @abhaysinghr516/business-wish add bottom-navigationnpx @abhaysinghr516/business-wish init first to initialize your project.A polished Tailwind bottom navigation component brings native-app framing to your mobile web projects. These Tailwind mobile nav solutions feature floating action buttons, intelligent safe-area padding, and smooth icon transitions.
Looking for desktop routing? Explore our top Header designs or side Sidebar structures.
Basic Bottom Navigation
A clean, flat, glassmorphic bottom navigation bar tailored for mobile devices or constrained responsive designs. Features a slide-up micro-interaction for active labels.
"use client";
import React, { useState } from "react";
import { Bell, Home, Search, User } from "lucide-react";
const BottomNavigation = () => {
const [active, setActive] = useState("home");
return (
<nav className="fixed bottom-0 left-0 right-0 bg-white/70 dark:bg-neutral-900/70 backdrop-blur-xl border-t border-neutral-200/50 dark:border-neutral-800/50 pb-safe-area-inset-bottom z-50 transition-colors duration-300">
<div className="flex justify-around items-center max-w-md mx-auto px-4 h-16">
{[
{ id: "home", icon: Home, label: "Home" },
{ id: "search", icon: Search, label: "Search" },
{ id: "notifications", icon: Bell, label: "Alerts" },
{ id: "profile", icon: User, label: "Profile" },
].map(({ id, icon: Icon, label }) => {
const isActive = active === id;
return (
<a
key={id}
href="#"
onClick={(e) => {
e.preventDefault();
setActive(id);
}}
className="group flex flex-col items-center justify-center w-16 h-full relative"
>
<div
className={`flex items-center justify-center w-10 h-10 rounded-full transition-all duration-300 ${
isActive
? "bg-neutral-100 dark:bg-neutral-800"
: "bg-transparent group-hover:bg-neutral-50 dark:group-hover:bg-neutral-800/50"
}`}
>
<Icon
className={`w-5 h-5 transition-all duration-300 ${
isActive
? "text-neutral-900 dark:text-neutral-100 scale-110"
: "text-neutral-500 dark:text-neutral-400"
}`}
strokeWidth={isActive ? 2.5 : 2}
/>
</div>
<span
className={`absolute bottom-1.5 text-[10px] font-medium tracking-wide transition-all duration-300 ${
isActive
? "text-neutral-900 dark:text-neutral-100 opacity-100 translate-y-0"
: "text-neutral-500 dark:text-neutral-400 opacity-0 translate-y-1"
}`}
>
{label}
</span>
</a>
);
})}
</div>
</nav>
);
};
export default BottomNavigation;
Bubble Navigation
A floating pill-shaped navigation offering a seamless transition between destinations showing text only upon activation.
"use client";
import React, { useState } from "react";
import { Heart, Home, Search, User } from "lucide-react";
const BubbleNavigation = () => {
const [active, setActive] = useState("home");
return (
<nav className="fixed bottom-6 left-0 right-0 z-50 pointer-events-none">
<div className="flex justify-center px-4 w-full">
<div className="pointer-events-auto bg-white/70 dark:bg-neutral-900/70 backdrop-blur-xl rounded-full shadow-[0_8px_30px_rgb(0,0,0,0.06)] dark:shadow-[0_8px_30px_rgb(0,0,0,0.3)] border border-neutral-200/50 dark:border-neutral-800/50 p-1.5 flex items-center gap-1 transition-colors duration-300">
{[
{ id: "home", icon: Home, label: "Home" },
{ id: "search", icon: Search, label: "Search" },
{ id: "favorites", icon: Heart, label: "Likes" },
{ id: "user", icon: User, label: "Profile" },
].map(({ id, icon: Icon, label }) => {
const isActive = active === id;
return (
<a
key={id}
href="#"
onClick={(e) => {
e.preventDefault();
setActive(id);
}}
className={`flex items-center gap-2 px-4 py-2.5 rounded-full transition-all duration-300 ${
isActive
? "bg-neutral-900 dark:bg-white text-white dark:text-neutral-900 shadow-md"
: "text-neutral-500 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-neutral-100 hover:bg-neutral-100/50 dark:hover:bg-neutral-800/50"
}`}
>
<Icon
className={`w-4 h-4 transition-transform duration-300 ${
isActive ? "scale-105" : "scale-100"
}`}
strokeWidth={isActive ? 2.5 : 2}
/>
{isActive && (
<span className="text-[13px] font-medium tracking-tight whitespace-nowrap overflow-hidden animate-in slide-in-from-left-2 duration-300">
{label}
</span>
)}
</a>
);
})}
</div>
</div>
</nav>
);
};
export default BubbleNavigation;
FAB Navigation
A premium, glassmorphic bottom navigation featuring a central Floating Action Button (FAB) seamlessly elevated from the layout.
"use client";
import React, { useState } from "react";
import { Bell, Home, Plus, Search, User } from "lucide-react";
const FabNavigation = () => {
const [active, setActive] = useState("home");
const [fabHovered, setFabHovered] = useState(false);
return (
<nav className="fixed bottom-6 left-0 right-0 z-50 pointer-events-none">
<div className="flex justify-center px-4 w-full h-[72px] items-end">
<div className="pointer-events-auto relative bg-white/70 dark:bg-neutral-900/70 backdrop-blur-xl rounded-[2rem] shadow-[0_8px_30px_rgb(0,0,0,0.06)] dark:shadow-[0_8px_30px_rgb(0,0,0,0.3)] border border-neutral-200/50 dark:border-neutral-800/50 w-full max-w-sm px-6 h-16 flex items-center justify-between transition-colors duration-300">
<div className="flex gap-4">
{[
{ id: "home", icon: Home },
{ id: "search", icon: Search },
].map(({ id, icon: Icon }) => {
const isActive = active === id;
return (
<a
key={id}
href="#"
onClick={(e) => {
e.preventDefault();
setActive(id);
}}
className={`p-2.5 rounded-full transition-all duration-300 ${
isActive
? "bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100"
: "text-neutral-500 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-neutral-100 hover:bg-neutral-50 dark:hover:bg-neutral-800/50"
}`}
>
<Icon className="w-5 h-5" strokeWidth={isActive ? 2.5 : 2} />
</a>
);
})}
</div>
<button
onMouseEnter={() => setFabHovered(true)}
onMouseLeave={() => setFabHovered(false)}
className="absolute left-1/2 -top-6 transform -translate-x-1/2 bg-neutral-900 dark:bg-white text-white dark:text-neutral-900 rounded-full p-3.5 shadow-xl transition-all duration-300 hover:scale-105 active:scale-95 ring-[6px] ring-neutral-50/50 dark:ring-neutral-900/50"
>
<Plus
className={`w-6 h-6 transition-transform duration-300 ${
fabHovered ? "rotate-90" : ""
}`}
strokeWidth={2.5}
/>
</button>
<div className="flex gap-4">
{[
{ id: "notifications", icon: Bell },
{ id: "profile", icon: User },
].map(({ id, icon: Icon }) => {
const isActive = active === id;
return (
<a
key={id}
href="#"
onClick={(e) => {
e.preventDefault();
setActive(id);
}}
className={`p-2.5 rounded-full transition-all duration-300 ${
isActive
? "bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100"
: "text-neutral-500 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-neutral-100 hover:bg-neutral-50 dark:hover:bg-neutral-800/50"
}`}
>
<Icon className="w-5 h-5" strokeWidth={isActive ? 2.5 : 2} />
</a>
);
})}
</div>
</div>
</div>
</nav>
);
};
export default FabNavigation;