From 6e6fc2df32a08868589673878bbb370f4ed49072 Mon Sep 17 00:00:00 2001 From: sikkzz Date: Sat, 25 Nov 2023 20:22:41 +0900 Subject: [PATCH 1/3] issue #144 refactor: conflict resolve --- src/assets/icon/ic-notification.svg | 3 + src/components/Header/Header/Header.jsx | 38 ++++++++-- src/components/Header/Header/Header.styles.js | 30 ++++++-- src/components/Header/SubHeader/SubHeader.jsx | 70 +++++-------------- .../Header/SubHeader/SubHeader.style.js | 6 +- .../NotificationDropdown.jsx | 39 +++++------ .../NotificationDropdown.style.js | 6 +- 7 files changed, 96 insertions(+), 96 deletions(-) create mode 100644 src/assets/icon/ic-notification.svg diff --git a/src/assets/icon/ic-notification.svg b/src/assets/icon/ic-notification.svg new file mode 100644 index 000000000..f8c4f529d --- /dev/null +++ b/src/assets/icon/ic-notification.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/Header/Header/Header.jsx b/src/components/Header/Header/Header.jsx index dd1702746..d4b358083 100644 --- a/src/components/Header/Header/Header.jsx +++ b/src/components/Header/Header/Header.jsx @@ -2,7 +2,9 @@ import React, { useEffect, useRef, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { NavLink, useLocation } from "react-router-dom"; +import NotificationIcon from "@/assets/icon/ic-notification.svg"; import Logo from "@/assets/img/img-selody-logo/1x.png"; +import NotificationDropdown from "@/components/Notification/NotificationDropdown/NotificationDropdown"; import { openModal } from "@/features/ui/ui-slice"; import { @@ -16,6 +18,8 @@ import { TabButton, ContainerHeader, WrapDiv, + NotificationButton, + NotificationDiv, } from "./Header.styles"; import GroupCreateModal from "../GroupCreateModal/GroupCreateModal"; import ProfileDropdown from "../ProfileDropdown/ProfileDropdown"; @@ -26,20 +30,32 @@ const Header = () => { const dispatch = useDispatch(); const profileRef = useRef(); - const dropdownRef = useRef(); + const profileDropdownRef = useRef(); + const notiRef = useRef(); + const notiDropdownRef = useRef(); const isSchedule = path === "/" || path === "/share"; const isFeed = path === "/community" || path === "mypage"; const { openedModal } = useSelector((state) => state.ui); - const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const [isProfileDropdownOpen, setIsProfileDropdownOpen] = useState(false); + const [isNotiDropdownOpen, setIsNotiDropdownOpen] = useState(false); const handleDropdown = (e) => { - if (isDropdownOpen && !dropdownRef.current.contains(e.target)) { - setIsDropdownOpen(false); + if ( + isProfileDropdownOpen && + !profileDropdownRef.current.contains(e.target) + ) { + setIsProfileDropdownOpen(false); } else if (profileRef.current.contains(e.target)) { - setIsDropdownOpen(true); + setIsProfileDropdownOpen(true); + } + + if (isNotiDropdownOpen && !notiDropdownRef.current.contains(e.target)) { + setIsNotiDropdownOpen(false); + } else if (notiRef.current.contains(e.target)) { + setIsNotiDropdownOpen(true); } }; @@ -86,13 +102,23 @@ const Header = () => { > 그룹 만들기 + + + + + {isNotiDropdownOpen && ( + + )} + - {isDropdownOpen && } + {isProfileDropdownOpen && ( + + )} {openedModal === "CREATE_GROUP" && } diff --git a/src/components/Header/Header/Header.styles.js b/src/components/Header/Header/Header.styles.js index 759e27f03..71fe319f9 100644 --- a/src/components/Header/Header/Header.styles.js +++ b/src/components/Header/Header/Header.styles.js @@ -90,26 +90,24 @@ export const GroupCreateButton = styled.button` border: 1px solid ${({ theme }) => theme.colors.primary}; border-radius: 100px; padding: 12px 36px; - background-color: white; + background-color: ${({ theme }) => theme.colors.white}; color: ${({ theme }) => theme.colors.primary}; font-size: 13px; font-family: Inter; font-weight: 700; - box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25); + box-shadow: 0px 4px 2px 0px rgba(0, 0, 0, 0.25); &:hover { - box-shadow: 0px 4px 2px 0px rgba(0, 0, 0, 0.25); + background-color: ${({ theme }) => theme.colors.bg_02}; } &:active { - box-shadow: 0px 4px 2px 0px rgba(0, 0, 0, 0.25); - background-color: #ccc4ff; + background-color: ${({ theme }) => `${theme.colors.bg_03}30`}; } `; export const ProfileDiv = styled.div` position: relative; - margin-left: 28px; `; export const ProfileImg = styled.img` @@ -119,3 +117,23 @@ export const ProfileImg = styled.img` border-radius: 50%; object-fit: contain; `; + +export const NotificationDiv = styled.div` + position: relative; +`; + +export const NotificationButton = styled.button` + margin: 0 24px; + cursor: pointer; + border-radius: 50%; + width: 40px; + height: 40px; + text-align: center; + + &:hover { + background-color: ${({ theme }) => theme.colors.bg_02}; + } + &:active { + background-color: ${({ theme }) => `${theme.colors.btn_01}30`}; + } +`; diff --git a/src/components/Header/SubHeader/SubHeader.jsx b/src/components/Header/SubHeader/SubHeader.jsx index 80309842a..984de4e56 100644 --- a/src/components/Header/SubHeader/SubHeader.jsx +++ b/src/components/Header/SubHeader/SubHeader.jsx @@ -1,15 +1,9 @@ -import React, { useEffect, useRef, useState } from "react"; +import React from "react"; import { NavLink } from "react-router-dom"; -import { NotificationButton, SubHeaderDiv, SubTabUl } from "./SubHeader.style"; -import NotificationDropdown from "../../Notification/NotificationDropdown/NotificationDropdown"; +import { SubHeaderDiv, SubTabUl } from "./SubHeader.style"; const SubHeader = ({ tab }) => { - const buttonRef = useRef(); - const dropdownRef = useRef(); - - const [isNotiTabOpen, setIsNotiTabOpen] = useState(false); - const listItems = tab === "schedule" ? [ @@ -18,56 +12,24 @@ const SubHeader = ({ tab }) => { ] : [ { path: "/community", title: "홈" }, - { path: null, title: "알림" }, { path: "/mypage", title: "마이페이지" }, ]; - const closeDropdown = (e) => { - if ( - !buttonRef.current.contains(e.target) && - !dropdownRef.current.contains(e.target) - ) { - setIsNotiTabOpen(false); - } - }; - - useEffect(() => { - if (isNotiTabOpen) { - window.addEventListener("click", closeDropdown); - } - - return () => { - window.removeEventListener("click", closeDropdown); - }; - }); - return ( - <> - - - {listItems.map(({ path, title }) => ( -
  • - {path === null ? ( - setIsNotiTabOpen(true)} - > - {title} - - ) : ( - (isActive ? "isActive" : "")} - > - {title} - - )} -
  • - ))} -
    -
    - {isNotiTabOpen && } - + + + {listItems.map(({ path, title }) => ( +
  • + (isActive ? "isActive" : "")} + > + {title} + +
  • + ))} +
    +
    ); }; diff --git a/src/components/Header/SubHeader/SubHeader.style.js b/src/components/Header/SubHeader/SubHeader.style.js index 442679e90..edf27c864 100644 --- a/src/components/Header/SubHeader/SubHeader.style.js +++ b/src/components/Header/SubHeader/SubHeader.style.js @@ -1,7 +1,7 @@ import styled from "styled-components"; export const SubHeaderDiv = styled.div` - display: ${({ isNotiTabOpen }) => (isNotiTabOpen ? "block" : "none")}; + display: none; position: absolute; top: 100%; z-index: 2; @@ -32,7 +32,3 @@ export const SubTabUl = styled.ul` font-weight: 600; } `; - -export const NotificationButton = styled.button` - cursor: pointer; -`; diff --git a/src/components/Notification/NotificationDropdown/NotificationDropdown.jsx b/src/components/Notification/NotificationDropdown/NotificationDropdown.jsx index a886153cf..607684acd 100644 --- a/src/components/Notification/NotificationDropdown/NotificationDropdown.jsx +++ b/src/components/Notification/NotificationDropdown/NotificationDropdown.jsx @@ -3,7 +3,6 @@ import React, { forwardRef } from "react"; import DropdownBubble from "@/assets/icon/ic-notification-dropdown.svg"; import { - ContainerDiv, DropdownWrapDiv, MenuWrapDiv, HeaderDiv, @@ -52,26 +51,24 @@ const NotificationDropdown = forwardRef((_, dropdownRef) => { ]; return ( - - - - - -

    알림

    -
    - - {mockItems.map(({ id, groupName, time, text }) => ( - - ))} - -
    -
    -
    + + + + +

    알림

    +
    + + {mockItems.map(({ id, groupName, time, text }) => ( + + ))} + +
    +
    ); }); diff --git a/src/components/Notification/NotificationDropdown/NotificationDropdown.style.js b/src/components/Notification/NotificationDropdown/NotificationDropdown.style.js index b3ba6c5b6..cc5026057 100644 --- a/src/components/Notification/NotificationDropdown/NotificationDropdown.style.js +++ b/src/components/Notification/NotificationDropdown/NotificationDropdown.style.js @@ -1,11 +1,9 @@ import styled from "styled-components"; -export const ContainerDiv = styled.div``; - export const MenuWrapDiv = styled.div` position: absolute; - top: calc(100% + 90px); - left: 36px; + top: calc(100% + 16px); + right: -100%; z-index: 99; `; From 3b03a63b687967e2bcd267bf83ec282a122e98c3 Mon Sep 17 00:00:00 2001 From: 2Junsu Date: Thu, 16 Nov 2023 15:23:43 +0900 Subject: [PATCH 2/3] issue #144 refactor: Refactor dropdown --- src/components/Header/Header/Header.jsx | 45 +++++++++--------- .../ProfileDropdown/ProfileDropdown.jsx | 47 ++++++++----------- .../ProfileDropdown/ProfileDropdown.style.js | 2 - .../NotificationDropdown.jsx | 8 ++-- 4 files changed, 48 insertions(+), 54 deletions(-) diff --git a/src/components/Header/Header/Header.jsx b/src/components/Header/Header/Header.jsx index d4b358083..1717f278d 100644 --- a/src/components/Header/Header/Header.jsx +++ b/src/components/Header/Header/Header.jsx @@ -30,9 +30,7 @@ const Header = () => { const dispatch = useDispatch(); const profileRef = useRef(); - const profileDropdownRef = useRef(); const notiRef = useRef(); - const notiDropdownRef = useRef(); const isSchedule = path === "/" || path === "/share"; const isFeed = path === "/community" || path === "mypage"; @@ -42,28 +40,29 @@ const Header = () => { const [isProfileDropdownOpen, setIsProfileDropdownOpen] = useState(false); const [isNotiDropdownOpen, setIsNotiDropdownOpen] = useState(false); - const handleDropdown = (e) => { - if ( - isProfileDropdownOpen && - !profileDropdownRef.current.contains(e.target) - ) { + const handleProfileDropdown = (e) => { + const { target } = e; + + if (isProfileDropdownOpen && !profileRef.current.contains(target)) { setIsProfileDropdownOpen(false); - } else if (profileRef.current.contains(e.target)) { - setIsProfileDropdownOpen(true); } + }; + + const handleNotiDropdown = (e) => { + const { target } = e; - if (isNotiDropdownOpen && !notiDropdownRef.current.contains(e.target)) { + if (isNotiDropdownOpen && !notiRef.current.contains(target)) { setIsNotiDropdownOpen(false); - } else if (notiRef.current.contains(e.target)) { - setIsNotiDropdownOpen(true); } }; useEffect(() => { - window.addEventListener("click", handleDropdown); + window.addEventListener("click", handleProfileDropdown); + window.addEventListener("click", handleNotiDropdown); return () => { - window.removeEventListener("click", handleDropdown); + window.removeEventListener("click", handleProfileDropdown); + window.removeEventListener("click", handleNotiDropdown); }; }); @@ -103,22 +102,26 @@ const Header = () => { 그룹 만들기 - + { + setIsNotiDropdownOpen(!isNotiDropdownOpen); + }} + > - {isNotiDropdownOpen && ( - - )} + {isNotiDropdownOpen && } { + setIsProfileDropdownOpen(!isProfileDropdownOpen); + }} /> - {isProfileDropdownOpen && ( - - )} + {isProfileDropdownOpen && } {openedModal === "CREATE_GROUP" && } diff --git a/src/components/Header/ProfileDropdown/ProfileDropdown.jsx b/src/components/Header/ProfileDropdown/ProfileDropdown.jsx index 23e7474ae..7b4188d2e 100644 --- a/src/components/Header/ProfileDropdown/ProfileDropdown.jsx +++ b/src/components/Header/ProfileDropdown/ProfileDropdown.jsx @@ -1,41 +1,34 @@ -import React, { forwardRef } from "react"; +import React from "react"; import { useDispatch } from "react-redux"; import { Link, useNavigate } from "react-router-dom"; import DropdownBubble from "@/assets/icon/ic-profile-dropdown.svg"; import { logout } from "@/features/auth/auth-service"; -import { - ContainerDiv, - ItemButton, - MenuUl, - MenuWrapDiv, -} from "./ProfileDropdown.style"; +import { ItemButton, MenuUl, MenuWrapDiv } from "./ProfileDropdown.style"; -const ProfileDropdown = forwardRef((_, dropdownRef) => { +const ProfileDropdown = () => { const dispatch = useDispatch(); const navigate = useNavigate(); return ( - - - - -
  • - - 설정 - -
  • -
    -
  • - dispatch(logout(navigate))}> - 로그아웃 - -
  • -
    -
    -
    + + + +
  • + + 설정 + +
  • +
    +
  • + dispatch(logout(navigate))}> + 로그아웃 + +
  • +
    +
    ); -}); +}; export default ProfileDropdown; diff --git a/src/components/Header/ProfileDropdown/ProfileDropdown.style.js b/src/components/Header/ProfileDropdown/ProfileDropdown.style.js index 38c667f85..986d39108 100644 --- a/src/components/Header/ProfileDropdown/ProfileDropdown.style.js +++ b/src/components/Header/ProfileDropdown/ProfileDropdown.style.js @@ -1,7 +1,5 @@ import styled from "styled-components"; -export const ContainerDiv = styled.div``; - export const MenuWrapDiv = styled.div` position: absolute; top: calc(100% + 24px); diff --git a/src/components/Notification/NotificationDropdown/NotificationDropdown.jsx b/src/components/Notification/NotificationDropdown/NotificationDropdown.jsx index 607684acd..f3fb8083c 100644 --- a/src/components/Notification/NotificationDropdown/NotificationDropdown.jsx +++ b/src/components/Notification/NotificationDropdown/NotificationDropdown.jsx @@ -1,4 +1,4 @@ -import React, { forwardRef } from "react"; +import React from "react"; import DropdownBubble from "@/assets/icon/ic-notification-dropdown.svg"; @@ -10,7 +10,7 @@ import { } from "./NotificationDropdown.style"; import NotificationItem from "../NotificationItem/NotificationItem"; -const NotificationDropdown = forwardRef((_, dropdownRef) => { +const NotificationDropdown = () => { const mockItems = [ { id: 1, @@ -51,7 +51,7 @@ const NotificationDropdown = forwardRef((_, dropdownRef) => { ]; return ( - + @@ -70,6 +70,6 @@ const NotificationDropdown = forwardRef((_, dropdownRef) => { ); -}); +}; export default NotificationDropdown; From 5104a00a926d6af97e68b7f8ed8219fe00ab9f40 Mon Sep 17 00:00:00 2001 From: 2Junsu Date: Thu, 16 Nov 2023 15:39:59 +0900 Subject: [PATCH 3/3] issue #144 design: Fix header css --- src/components/Header/Header/Header.styles.js | 4 ++-- .../NotificationDropdown/NotificationDropdown.style.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Header/Header/Header.styles.js b/src/components/Header/Header/Header.styles.js index 71fe319f9..b3a48d0e2 100644 --- a/src/components/Header/Header/Header.styles.js +++ b/src/components/Header/Header/Header.styles.js @@ -76,7 +76,7 @@ export const TabButton = styled.button` font-weight: ${({ isActive }) => (isActive ? "600" : "500")}; border-bottom: ${({ isActive, theme: { colors } }) => isActive ? `2px solid ${colors.primary}` : 0}; - padding: 10px 8px 8px; + padding: 10px 0; &:hover { color: ${({ theme }) => theme.colors.primary}; @@ -123,7 +123,7 @@ export const NotificationDiv = styled.div` `; export const NotificationButton = styled.button` - margin: 0 24px; + margin: 0 16px; cursor: pointer; border-radius: 50%; width: 40px; diff --git a/src/components/Notification/NotificationDropdown/NotificationDropdown.style.js b/src/components/Notification/NotificationDropdown/NotificationDropdown.style.js index cc5026057..5a0c95af0 100644 --- a/src/components/Notification/NotificationDropdown/NotificationDropdown.style.js +++ b/src/components/Notification/NotificationDropdown/NotificationDropdown.style.js @@ -3,7 +3,7 @@ import styled from "styled-components"; export const MenuWrapDiv = styled.div` position: absolute; top: calc(100% + 16px); - right: -100%; + right: calc(-100% - 24px); z-index: 99; `;