I'm building a React expense tracker app with Tailwind CSS. My navbar has a user profile dropdown menu that cut off at the right edge of the screen instead of rendering fully visible.
Current behavior: The dropdown opens but overflows outside the right edge of the viewport and gets cut off.
Expected behavior: The dropdown should appear fully visible below the user button, aligned to the right side of the navbar.
I'm sharing the code too
import React, { useEffect, useRef, useState } from 'react'
import { navbarStyles } from '../assets/dummyStyles.js'
import img1 from '../assets/logo.png'
import { ChevronDown, LogOut, User } from 'lucide-react';
import { useNavigate } from 'react-router-dom'
import axios from 'axios'
const BASE_URL = 'http://localhost:4000/api'
const Navbar = ({user: propUser, onLogout}) => {
const navigate = useNavigate();
const menuRef = useRef();
const [menuOpen, setMenuOpen] = useState(false);
const user = propUser || {
name:"",
email:"",
};
// to fetch the user data from server
useEffect(() => {
const fetchUserData = async () => {
try {
const token = localStorage.getItem("token");
if(!token) return;
const response = await axios.get(${BASE_URL}/user/me,{
headers: {Authorization:Bearer ${token}},
});
const userData = response.data.user || response.data;
setUser(userData);
} catch (error) {
console.log("Failed to load profile", error);
}
};
if(!propUser){
fetchUserData();
}
},[propUser]);
const toggleMenu = () => setMenuOpen((prev) => !prev);
const handleLogout = () => {
setMenuOpen(false);
localStorage.removeItem("token");
onLogout?.();
navigate("/login");
};
// close the toggle menu if click outside the box
useEffect(() => {
const handleClickOutside = (e) => {
if (menuRef.current && !menuRef.current.contains(e.target)) {
setMenuOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
return (
<header className={navbarStyles.header}>
<div className={navbarStyles.container}>
{/logo/}
<div onClick={() => navigate("/") } className={navbarStyles.logoContainer}>
<div className={navbarStyles.logoImage}>
<img src={img1} alt="logo" style={{
width: "48px",
height: "48px",
objectFit: "contain",
borderRadius: "12px"
}} />
</div>
<span className={navbarStyles.logoText}>Expense Tracker</span>
</div>
{/*if the user is present */}
{user && (
<div className={navbarStyles.userContainer} ref={menuRef}>
<button onClick={toggleMenu} className={navbarStyles.userButton}>
<div className='relative'>
<div className={navbarStyles.userAvatar}>
{user?.name?.[0]?.toUpperCase() || "U"}
</div>
<div className={navbarStyles.statusIndicator}></div>
</div>
<div className={navbarStyles.userTextContainer}>
<p className={navbarStyles.userName}>
{user?.name || ""}
</p>
<p className={navbarStyles.userEmail}>
{user?.email || "user@expensetracker.com"}
</p>
</div>
<ChevronDown className={navbarStyles.chevronIcon(menuOpen)}/>
</button>
{/* dropdown menu */}
{menuOpen && (
<div className={navbarStyles.dropdownMenu}>
<div className={navbarStyles.dropdownHeader}>
<div className='flex items-center gap-3'>
<div className={navbarStyles.dropdownAvatar}>
{user ?. name?. [0]?.toUpperCase() || ""}
</div>
<div>
<div className={navbarStyles.dropdownName}>
{user?.name || ""}
</div>
<div className={navbarStyles.dropdownEmail}>
{user?.email || "user@expensetracker.com"}
</div>
</div>
</div>
</div>
<div className={navbarStyles.menuItemContainer}>
<button onClick={() => {
setMenuOpen(false);
navigate("/profile");
}} className={navbarStyles.menuItem}
>
<User className='w-4 h-4'/>
<span>
My Profile
</span>
</button>
</div>
<div className={navbarStyles.menuItemBorder}>
<button onClick={handleLogout} className={navbarStyles.logoutButton}>
<LogOut className='w-4 h-4'/>
<span>Log Out</span>
</button>
</div>
</div>
)}
</div>
)}
</div>
</header>
)
}
export default Navbar
Also sharing the dummystyles.js code too which I'm using in my navbar.jsx file.
export const navbarStyles = {
// Layout and container styles
header: "sticky top-0 z-50 bg-white border-b border-gray-100 shadow-sm",
container: "flex items-center justify-between px-4 py-3 md:px-6 w-full",
// Logo styles
logoContainer: "flex items-center gap-0 cursor-pointer",
logoImage: "w-12 h-12 rounded-xl overflow-hidden flex-shrink-0",
dropdownMenu: "absolute top-full mt-2 right-0 w-64 bg-white rounded-xl shadow-xl border border-gray-100 z-[999]",