Learning Log/React

[react] 드롭다운 메뉴 만들기

자척개 2023. 2. 15. 20:43
반응형

구현할 메뉴의 예시입니다

 

위에 7가지 메뉴가 적혀있는 부분을 menu로,

menubox에 mouseenter 시 드롭다운되는 메뉴를 newmenubox로 칭하겠습니다

 

구현할 메뉴 이미지

 

JSX 부분

menu.js

import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import { MENU_DATA } from '../data/menuData';
import NewMenuBox from '../NewMenuBox/NewMenuBox';
import OtherMenuBox from '../OtherMenuBox/OtherMenuBox';
import './Menu.scss';

const Menu = () => {
const [isShown, setIsShown] = useState(false);
const [menuId, setMenuId] = useState(0);

const onMouseEnter = () => setIsShown(true);
const onMouseLeave = () => setIsShown(false);
const onMouseEnterList = id => setMenuId(id);

return (
<div className="menu">
<div className="menuWrapper">
{MENU_DATA.map(menu => {
return (
<div key={menu.id}>
<ul className="menuLists" onMouseEnter={onMouseEnter}>
<Link className="toProductList" to={'/main'}>
<li
className="menuList"
onMouseEnter={() => onMouseEnterList(menu.id)}
id={menu.id}
>
{menu.name}
</li>
</Link>
</ul>

{menuId === 1 ? (
<NewMenuBox
className="menubox"
isShown={isShown}
onMouseLeave={onMouseLeave}
onMouseEnter={onMouseEnter}
/>
) : (
(menuId === 2 || menuId === 3 || menuId === 4) && (
<OtherMenuBox
className="menubox"
isShown={isShown}
onMouseLeave={onMouseLeave}
onMouseEnter={onMouseEnter}
/>
)
)}
</div>
);
})}
</div>
</div>
);
};

export default Menu;

 

 

newMenubox.js

import React from 'react';
import ItemLists from '../ItemLists/ItemLists';
import {
NEW_ITEMS,
MEN_ITEMS,
WOMEN_ITEMS,
KIDS_ITEMS,
ACC_ITEMS,
} from '../data/newMenuBoxData';
import './NewMenuBox.scss';

const NewMenuBox = ({ isShown, onMouseEnter, onMouseLeave }) => {
return (
<div className="newMenuBox">
{isShown && (
<>
<div
className="newMenuBoxWrapper"
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
<div className="itemWrapper">
{NEW_ITEMS.map(item => {
return <ItemLists key={item.id} item={item} />;
})}
</div>
<div className="itemWrapper">
{MEN_ITEMS.map(item => {
return <ItemLists key={item.id} item={item} />;
})}
</div>
<div className="itemWrapper">
{WOMEN_ITEMS.map(item => {
return <ItemLists key={item.id} item={item} />;
})}
</div>
<div className="itemWrapper">
{KIDS_ITEMS.map(item => {
return <ItemLists key={item.id} item={item} />;
})}
</div>
<div className="itemWrapper">
{ACC_ITEMS.map(item => {
return <ItemLists key={item.id} item={item} />;
})}
</div>
</div>

<div className="blur" />
</>
)}
</div>
);
};

export default NewMenuBox;

CSS 부분

menu.scss

@import '../../../styles/mixin.scss';

.menu {
.menuWrapper {
@include flex(space-between, center);
position: relative;
width: 100%;
height: 80px;

.menuLists {
@include flex(space-between, center);
gap: 25px;
list-style: none;

.toProductList {
color: black;

.menuList {
float: left;
padding: 10px;
font-weight: bold;
cursor: pointer;

&:hover {
padding-bottom: 5px;
border-bottom: 2px solid black;
}
}
}
}
}
}
 

 

newMenuBox.scss

@import '../../../styles/mixin.scss';

.newMenuBox {
position: absolute;
top: 130%;
left: -69%;
width: 100vw;
height: 100vh;
margin: auto;

.newMenuBoxWrapper {
@include flex(space-around, flex-start);
flex-direction: row;
width: 100%;
height: 400px;
padding: 40px 50px;

.itemWrapper {
display: flex;
flex-direction: column;
gap: 10px;

.itemList {
cursor: pointer;

&[id='0'] {
font-weight: 600;
}
}
}
}

.blur {
position: relative;
width: 100%;
height: 100%;
background-color: #f5f5f5;
opacity: 0.3;

&::after {
position: absolute;
width: 100%;
height: 100%;
background-color: #f5f5f5;
top: 0;
left: 0;
opacity: 0.5;
z-index: -1;
}
}
}
반응형