Drop-down menus can be seen on many websites, and submenus pop up automatically when the mouse hovers over navigation elements. Benefits:
The semantic label of navigation is nav, the content is list ul, and the horizontal distribution of list elements can be floating or flex. For example:
<nav>
<ul>
<li>导航1</li>
<li>导航2</li>
<li>导航3</li>
</ul>
</nav>
Drop-down menus are also list structures, such as:
<nav>
<ul>
<li>
<a>导航1</a>
<ul>
<li>导航1-1</li>
<li>导航1-2</li>
<li>导航1-3</li>
</ul>
</li>
<li>导航2</li>
<li>导航3</li>
</ul>
</nav>
if it is a non-automatic (hover) pop-up, you can directly use HTML5/select & options.
Respond to mouse events
- Close dropdown menu when the mouse leaves the nav-item and all its child elements, and the corresponding DOM Event is mouseleave. (not mouseout) two。 When the mouse enters the nav-item root element, open dropdown menu, and the corresponding DOM Event is mouseenter. (more accurate than mouseover)
TSX structure of Dropdown
The list is generated by array rendering, treats items as Functor, and applies rendering functions to each element. That is, fmap renderToTSX items.
type Anchor = {
name: string
href?: string
}
const Dropdown = ({ items }: { items: Anchor[] }) => (
<ul className="head-dropdown">
{items.map(({ name, href }) => (
<li>
<a href={href}>{name}</a>
</li>
))}
</ul>
)
In order to avoid DOM structure reflow caused by dropdown menu dynamic display, absolute positioning is used to get it out of the document stream.
.head-dropdown {
position: absolute;
z-index: 999;
}
Because you want to display dropdown menu dynamically, it is an asynchronous DOM operation. Use setState to implement.
type NavItemProps = Anchor & {
items: Anchor[]
}
const NavItem = ({ name, href, items }: NavItemProps) => {
const [display, setComponent] = useState(<></>)
const visible = () => setComponent(<Dropdown items={items} />)
const hidden = () => setComponent(<></>)
return (
<li className="nav-item" onMouseEnter={visible} onMouseLeave={hidden}>
<a href={href}>{name}</a>
{display}
</li>
)
}
Cascading style sheets for nav-item. Use floats below if you need to be compatible with IE10.
.nav-item {
float: left;
padding: 0 0.5rem;
}
const App = () => (
<nav>
<ul>
<NavItem
name="item1"
items={[
{ name: "subitem1", href: "#" },
{ name: "subitem2", href: "#" },
{ name: "subitem3", href: "#" }
]}
/>
</ul>
</nav>
)