Outside Click Behavior
It is common feature for a menus - to be closed when user clicks somewhere else (outside the dropdown panel).
To achileve this functionality - we can use this custom hook
import { useEffect } from "react";
function UseOuterClickNotifier(onOuterClick, innerRef) {
useEffect(
() => {
// only add listener, if the element exists
if (innerRef.current) {
document.addEventListener("click", handleClick);
}
// unmount previous first in case inputs have changed
return () => document.removeEventListener("click", handleClick);
function handleClick(e) {
innerRef.current && !innerRef.current.contains(e.target) && onOuterClick(e);
}
},
[onOuterClick, innerRef] // invoke again, if inputs have changed
);
}
export default UseOuterClickNotifier;
So now , our month menu opens when clickinh inside input and closes when clicking outside
UseOuterClickNotifier(
e => setShown(false),
elRef
);
Displaying Months
Now - to the main purpose of the our widget: the displaying months:
const months = ['Jan', 'Feb', 'Mar', 'Spr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
...
{shown && <div className="month-menu-dropdown">
<header>
<div className="top-arrow"></div>
<button onClick={decYear}>></button>
<div className="year-holder">{year}</div>
<button onClick={incYear}><</button>
</header>
{months.map((month, index) => (<button key={month} onClick={e => monthClick(e, index)}>{month}</button>))}
</div>}
to get the buttons ordered at 3 columns and 4 rows, i will use grid-css feature:
.month-menu-dropdown {
position: absolute;
right: 0;
top: 59px;
min-width: 170px;
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 2px;
row-gap: 5px;
z-index: 3;
background: #fff;
border: 1px solid var(--text-color);
border-radius: 2px;
border: 1px solid grey;
padding: 5px 0;
}