I have created this dummy top nav bar, where i have multiple drop-down which can be scrollable on x axis via buttons if multiple . But when i open the dropdown it is being opened in scroll view for y axis. rather it should open on top. Tried multiple things nothing worked. This looks like a simple issue, but clearly has exercised my brain.
Created a dummy nav bar here https://codesandbox.io/p/sandbox/87jmzv
import React, { useState } from 'react';
const TopNav = () => {
const [scrollPosition, setScrollPosition] = useState(0);
// Array of dropdowns, each with its own set of options
const dropdowns = [
{ id: 'dropdown1', label: 'Dropdown 1', options: ['Option 1', 'Option 2', 'Option 3'] },
{ id: 'dropdown2', label: 'Dropdown 2', options: ['Option A', 'Option B', 'Option C'] },
{ id: 'dropdown3', label: 'Dropdown 3', options: ['Option X', 'Option Y', 'Option Z'] },
{ id: 'dropdown2', label: 'Dropdown 2', options: ['Option A', 'Option B', 'Option C'] },
{ id: 'dropdown2', label: 'Dropdown 2', options: ['Option A', 'Option B', 'Option C'] },
{ id: 'dropdown2', label: 'Dropdown 2', options: ['Option A', 'Option B', 'Option C'] },
{ id: 'dropdown2', label: 'Dropdown 2', options: ['Option A', 'Option B', 'Option C'] },
// You can add more dropdowns here
];
const scrollLeft = () => {
setScrollPosition((prev) => Math.max(prev - 200, 0));
};
const scrollRight = () => {
setScrollPosition((prev) => Math.min(prev + 200, (dropdowns.length - 3) * 200));
};
return (
<div className="top-nav">
{/* Logo on the left */}
<div className="logo">Logo</div>
{/* Left Arrow Button */}
<button className="arrow-button" onClick={scrollLeft}>←</button>
{/* Scrollable Dropdown List */}
<div className="dropdowns-container">
<div className="dropdowns-wrapper" style={{ transform: `translateX(-${scrollPosition}px)` }}>
{dropdowns.map((dropdown) => (
<CustomDropdown key={dropdown.id} label={dropdown.label} options={dropdown.options} />
))}
</div>
</div>
{/* Right Arrow Button */}
<button className="arrow-button" onClick={scrollRight}>→</button>
</div>
);
};
const CustomDropdown = ({ label, options }) => {
const [isOpen, setIsOpen] = useState(false);
const [selectedOption, setSelectedOption] = useState(null);
const toggleDropdown = () => {
setIsOpen((prev) => !prev);
};
const selectOption = (option) => {
setSelectedOption(option);
setIsOpen(false); // Close dropdown after selecting
};
return (
<div className="dropdown">
<div className="dropdown-label" onClick={toggleDropdown}>
{selectedOption || label}
</div>
{isOpen && (
<div className="dropdown-list">
{options.map((option, index) => (
<div key={index} className="dropdown-item" onClick={() => selectOption(option)}>
{option}
</div>
))}
</div>
)}
</div>
);
};
export default TopNav;
css
/* Top Navigation Styling */
.top-nav {
display: flex;
align-items: center;
padding: 10px;
background-color: #f4f4f4;
border-bottom: 1px solid #ccc;
}
/* Logo Styling */
.logo {
font-size: 20px;
font-weight: bold;
margin-right: 20px;
}
/* Arrow Button Styling */
.arrow-button {
background-color: transparent;
border: none;
font-size: 20px;
cursor: pointer;
padding: 5px;
}
/* Dropdown Container Styling */
.dropdowns-container {
display: flex;
overflow-x: hidden;
width: 300px;
border: 1px solid #ccc;
padding: 5px;
}
/* Wrapper to handle scrolling */
.dropdowns-wrapper {
display: flex;
transition: transform 0.3s ease;
}
/* Individual Dropdown Styling */
.dropdown {
margin: 0 10px;
position: relative;
}
/* Label Styling */
.dropdown-label {
font-size: 14px;
margin-bottom: 5px;
font-weight: bold;
cursor: pointer;
padding: 5px;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 4px;
}
/* Custom Dropdown List */
.dropdown-list {
position: absolute;
top: 30px;
left: 0;
background-color: #fff;
border: 1px solid #ccc;
padding: 5px 0;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
z-index: 10;
width: 150px;
}
/* Dropdown Item Styling */
.dropdown-item {
padding: 8px 10px;
cursor: pointer;
}
.dropdown-item:hover {
background-color: #f4f4f4;
}
There's a simple solution for the primary issue here: overflow-x: clip
. This behaves differently than overflow-x: hidden
, allowing the dropdown content to spill out of the box in the y-axis.
You will likely need to do some extra work to close the dropdown when the trigger is outside of the viewable window of the container, though, otherwise the menu will show clipped along the x-axis.