From a5145a2d90f2db5638d573c2a477e5e59bbed673 Mon Sep 17 00:00:00 2001 From: kiyeong Date: Fri, 8 Nov 2024 19:25:27 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=82=AC=EC=9D=B4=EB=93=9C=EB=B0=94=20?= =?UTF-8?q?=EC=95=88=EB=82=B4=20tooltip=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/main/sidebar/index.tsx | 161 +++++++++++++++++++++++++++++-- 1 file changed, 151 insertions(+), 10 deletions(-) diff --git a/src/pages/main/sidebar/index.tsx b/src/pages/main/sidebar/index.tsx index 0e6c15b..b6ef53d 100644 --- a/src/pages/main/sidebar/index.tsx +++ b/src/pages/main/sidebar/index.tsx @@ -1,9 +1,13 @@ -// sidebar.tsx - import { Box, IconButton, Flex, Link, Button } from "@chakra-ui/react"; -import { ArrowForwardIcon, ArrowBackIcon } from "@chakra-ui/icons"; +import { + ArrowForwardIcon, + ArrowBackIcon, + InfoOutlineIcon, + CloseIcon, +} from "@chakra-ui/icons"; import styled from "@emotion/styled"; import knuLogo from "@/assets/knuLogo.svg"; +import React, { useEffect, useState } from "react"; interface SidebarProps { isOpen: boolean; @@ -11,10 +15,41 @@ interface SidebarProps { } export const Sidebar: React.FC = ({ isOpen, toggleSidebar }) => { + const [showTooltip, setShowTooltip] = useState(false); + + useEffect(() => { + // 로컬 스토리지에서 tooltip이 닫혔는지 확인 + const tooltipDismissed = localStorage.getItem("tooltipDismissed"); + let timer: NodeJS.Timeout; + + if (tooltipDismissed !== "true" && !isOpen) { + // 사이드바가 닫히면 1.5초 후에 말풍선을 보이게 함 + timer = setTimeout(() => { + setShowTooltip(true); + }, 500); + } else { + // 로컬 스토리지에 값이 있거나 사이드바가 열리면 말풍선을 숨김 + setShowTooltip(false); + } + + // 컴포넌트 언마운트 시 타이머 클리어 + return () => { + if (timer) { + clearTimeout(timer); + } + }; + }, [isOpen]); + const handleKakaoLogin = () => { window.location.href = "http://127.0.0.1:8080"; }; + // 닫기 버튼 클릭 시 로컬 스토리지에 값 저장하고 말풍선 숨기기 + const handleTooltipClose = () => { + localStorage.setItem("tooltipDismissed", "true"); + setShowTooltip(false); + }; + return ( <> @@ -86,6 +121,30 @@ export const Sidebar: React.FC = ({ isOpen, toggleSidebar }) => { )} + {/* 사이드바가 닫힌 후 1.5초 뒤에 말풍선이 표시되도록 함 */} + {!isOpen && showTooltip && ( + + + + + +

사이드바를 열어 로그인하거나

+

히스토리를 볼 수 있어요!

+
+ + + +
+
+
+ )} ); }; @@ -107,29 +166,40 @@ const SidebarContainer = styled(Box, { padding-top: 16px; `; -// 열기/닫기 버튼, 사이드바 오른쪽 중앙에 위치 const ToggleButton = styled(IconButton)` position: absolute; - right: -20px; + right: -40px; top: 50%; transform: translateY(-50%); background-color: #fcb9aa; color: white; border-radius: 50%; - width: 50px; - height: 50px; + width: 100px; + height: 100px; transition: background-color 0.2s, transform 0.2s; display: flex; align-items: center; justify-content: center; + &::before { + content: ""; + position: absolute; + top: -10px; + bottom: -10px; + left: -10px; + right: -10px; + background: transparent; + } + & > svg { - margin-left: 20px; // 아이콘을 오른쪽으로 살짝 이동 + width: 40px; + height: 40px; + margin-left: 50px; } &:hover { background-color: #fcb9aa; - transform: translateY(-50%) scale(1.2); + transform: translateY(-50%) scale(1.1); } `; @@ -142,7 +212,7 @@ const Divider = styled.hr` const Footer = styled(Box)` position: absolute; - bottom: 0; + bottom: 30px; padding: 20px; font-size: 12px; line-height: 1.5; @@ -172,3 +242,74 @@ const KakaoLoginImage = styled.img` height: 45px; filter: brightness(1.2); `; + +const TooltipContainer = styled(Box)` + position: fixed; + top: 45%; + left: 20px; + transform: translateY(-50%); + display: flex; + align-items: center; + z-index: 9999; + + animation: bounce 2s ease-in-out infinite; // 애니메이션 적용 + + @keyframes bounce { + 0%, + 100% { + transform: translateY(-50%); + } + 50% { + transform: translateY(-70%); // 위로 더 크게 이동 + } + } +`; + +const TooltipBox = styled(Box)` + position: absolute; + left: 100%; + top: 50%; + transform: translateY(-50%); + font-size: 14px; + width: 250px; + margin-left: -150px; // 아이콘과 말풍선 간격 + margin-top: -50px; // 아이콘과 말풍선 중앙 정렬 + padding: 16px; // 말풍선 내부 여백 (위아래 여백을 더 추가) + background-color: #fcb9aa; + color: white; // 텍스트 색상 + border-radius: 8px; // 말풍선 모서리 둥글기 + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); // 그림자 효과 + position: relative; + + &::after { + content: ""; + position: absolute; + bottom: -7px; // 말풍선의 아래쪽 끝에 위치 + left: 5px; // 말풍선 왼쪽 모서리에 가깝게 위치하도록 설정 + transform: translateY(50%); + border-width: 8px; + border-style: solid; + border-color: #fcb9aa transparent transparent transparent; // 꼬리의 색상 지정 (위쪽 방향으로) + } +`; + +const CloseButton = styled(IconButton)` + position: absolute; + top: 5px; // 박스 상단에서 8px 떨어지게 설정 + right: 0px; // 박스 오른쪽에서 8px 떨어지게 설정 + background: none; + color: white; + border: none; + width: 20px; // 버튼 너비 설정 (작게 조정) + height: 20px; // 버튼 높이 설정 (작게 조정) + padding: 0; // 내부 여백 최소화 + + & > svg { + width: 14px; // 아이콘 크기 설정 (작게 조정) + height: 14px; // 아이콘 크기 설정 (작게 조정) + } + + &:hover { + background: none; + } +`;