Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/25 fix header and union section #31

Merged
merged 10 commits into from
Feb 16, 2025
17 changes: 17 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite --host",
"type-check": "tsc --noEmit",
"build": "tsc -b && vite build",
"lint": "eslint .",
Expand All @@ -15,6 +15,7 @@
"axios": "^1.7.9",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.4.0",
"react-responsive": "^10.0.0",
"react-router": "^7.1.5",
"react-slick": "^0.30.3",
Expand Down
6 changes: 4 additions & 2 deletions src/pages/Main/FarmSyetemNav/FarmSystemNav.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ interface FixedNavProps {

export const FixedNavWrapper = styled.div<FixedNavProps>`
position: fixed;
top: ${({ isVisible }) => (isVisible ? "10px" : "-50px")};
right: 20px;
top: ${({ isVisible, $isMobile }) =>
!$isMobile ? (isVisible ? "30px" : "-50px") :(isVisible ? "20px" : "-150px")};
right: ${({ $isMobile }) => ($isMobile ? "20px" : "50px")};
transition: top 0.3s ease-in-out;
z-index: 1000;
`;


export const Navbar = styled.nav<{ $isMobile: boolean }>`
background-color: #216D35;
padding: 10px 20px;
Expand Down
60 changes: 45 additions & 15 deletions src/pages/Main/FarmSyetemNav/FarmSystemNav.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,43 @@
import * as S from './FarmSystemNav.styled';
import { useState, useEffect } from 'react';
import useMediaQueries from '@/hooks/useMediaQueries';
import MobileNav from './MobileNav';

const sectionIds = ["about", "tracks", "achievements", "eligibility"];

export default function FarmSystemNav() {
const [isVisible, setIsVisible] = useState(false);
const { isMobile } = useMediaQueries();
const [currentSection, setCurrentSection] = useState("about");

useEffect(() => {
const handleScroll = () => {
if (window.scrollY > 200) {
const scrollPosition = window.scrollY;

if (scrollPosition > 200) {
setIsVisible(true);
} else {
setIsVisible(false);
}

// 현재 섹션 확인
for (const section of sectionIds) {
const element = document.getElementById(section);
if (element) {
const offsetTop = element.offsetTop;
const offsetBottom = offsetTop + element.offsetHeight;

if (scrollPosition >= offsetTop - 100 && scrollPosition < offsetBottom - 100) {
setCurrentSection(section);
}
}
}
};


window.addEventListener("scroll", handleScroll);
handleScroll();

return () => {
window.removeEventListener("scroll", handleScroll);
};
Expand All @@ -29,25 +51,33 @@ export default function FarmSystemNav() {
top: targetElement.getBoundingClientRect().top + window.scrollY,
behavior: "smooth",
});
setCurrentSection(targetId);
}
};

return (
<S.FixedNavWrapper isVisible={isVisible} $isMobile={isMobile}>
<S.Navbar $isMobile={isMobile}>
<S.NavItem $isMobile={isMobile} href="#about" onClick={(e) => handleSmoothScroll(e, "#about")}>
<S.Circle $isMobile={isMobile} /> Farm System이란?
</S.NavItem>
<S.NavItem $isMobile={isMobile} href="#tracks" onClick={(e) => handleSmoothScroll(e, "#tracks")}>
<S.Circle $isMobile={isMobile} /> 트랙 및 커리큘럼
</S.NavItem>
<S.NavItem $isMobile={isMobile} href="#achievements" onClick={(e) => handleSmoothScroll(e, "#achievements")}>
<S.Circle $isMobile={isMobile} /> 활동 및 성과
</S.NavItem>
<S.NavItem $isMobile={isMobile} href="#eligibility" onClick={(e) => handleSmoothScroll(e, "#eligibility")}>
<S.Circle $isMobile={isMobile} /> 지원 요건
</S.NavItem>
</S.Navbar>
{isMobile ? (
<MobileNav
currentSection={currentSection}
handleSmoothScroll={handleSmoothScroll}
/>
) : (
<S.Navbar $isMobile={isMobile}>
<S.NavItem $isMobile={isMobile} href="#about" onClick={(e) => handleSmoothScroll(e, "#about")}>
<S.Circle $isMobile={isMobile} /> Farm System이란?
</S.NavItem>
<S.NavItem $isMobile={isMobile} href="#tracks" onClick={(e) => handleSmoothScroll(e, "#tracks")}>
<S.Circle $isMobile={isMobile} /> 트랙 및 커리큘럼
</S.NavItem>
<S.NavItem $isMobile={isMobile} href="#achievements" onClick={(e) => handleSmoothScroll(e, "#achievements")}>
<S.Circle $isMobile={isMobile} /> 활동 및 성과
</S.NavItem>
<S.NavItem $isMobile={isMobile} href="#eligibility" onClick={(e) => handleSmoothScroll(e, "#eligibility")}>
<S.Circle $isMobile={isMobile} /> 지원 요건
</S.NavItem>
</S.Navbar>
)}
</S.FixedNavWrapper>
);
}
52 changes: 52 additions & 0 deletions src/pages/Main/FarmSyetemNav/MobileNav.styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import styled from 'styled-components';

export const MobileNavbar = styled.div<{ isNavOpen: boolean }>`
max-height: ${({ isNavOpen }) => (isNavOpen ? "300px" : "80px")};
overflow: hidden;
transition: max-height 0.1s ease-in-out;
display: inline-flex;
height: auto;
padding: 10px 10px;
flex-direction: column;
justify-content: center;
align-items: center;
width: 150px;
border-radius: 20px 0px 20px 20px;
border: 1px solid var(--FarmSystem_White, #FCFCFC);
background: var(--FarmSystem_Green01, #28723F);
`;

export const MobileNavItem = styled.a`
display: flex;
padding: 5px 0px;
align-items: center;
gap: 3px;
flex: 1 0 0;
`;

export const MobileNavText = styled.p`
color: var(--FarmSystem_White, #FCFCFC);
text-align: center;
font-size: 14px;
font-style: normal;
font-weight: 500;
line-height: 16px;
letter-spacing: -0.24px;
`;

/* 확장/축소 버튼 스타일 */
export const ExpandButton = styled.button`
color: var(--FarmSystem_White, #FCFCFC);
font-size: 24px;
cursor: pointer;
width: 80%;
background-color: rgba(0, 0, 0, 0.5);
border-radius: 15px;
display: flex;
justify-content: center;
align-items: center;
`;
74 changes: 74 additions & 0 deletions src/pages/Main/FarmSyetemNav/MobileNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { useState } from 'react';
import * as S from './MobileNav.styled';
import { IoMdArrowDropdown, IoMdArrowDropup } from "react-icons/io";

interface MobileNavProps {
currentSection: string;
handleSmoothScroll: (
event: React.MouseEvent<HTMLAnchorElement, MouseEvent>,
targetId: string
) => void;
}

const navItems = [
{ id: "about", text: "Farm System이란?" },
{ id: "tracks", text: "트랙 및 커리큘럼" },
{ id: "achievements", text: "활동 및 성과" },
{ id: "eligibility", text: "지원 요건" },
];

export default function MobileNav({ currentSection, handleSmoothScroll }: MobileNavProps) {
const [isNavOpen, setIsNavOpen] = useState(false);
const currentNavItem = navItems.find(item => item.id === currentSection) ?? navItems[0];

return (
<S.MobileNavbar isNavOpen={isNavOpen}>
{/*
isNavOpen이 false면 첫 번째 메뉴만 보이게,
true면 모든 메뉴가 보이게 설정
*/}
{!isNavOpen && (
<S.MobileNavItem
href={"#" + currentNavItem.id}
onClick={(e) => handleSmoothScroll(e, currentNavItem.id)}
>
<S.MobileNavText>{currentNavItem.text}</S.MobileNavText>
</S.MobileNavItem>
)}

{isNavOpen && (
<>
<S.MobileNavItem
href="#about"
onClick={(e) => handleSmoothScroll(e, "#about")}
>
<S.MobileNavText>Farm System이란?</S.MobileNavText>
</S.MobileNavItem>
<S.MobileNavItem
href="#tracks"
onClick={(e) => handleSmoothScroll(e, "#tracks")}
>
<S.MobileNavText>트랙 및 커리큘럼</S.MobileNavText>
</S.MobileNavItem>
<S.MobileNavItem
href="#achievements"
onClick={(e) => handleSmoothScroll(e, "#achievements")}
>
<S.MobileNavText>활동 및 성과</S.MobileNavText>
</S.MobileNavItem>
<S.MobileNavItem
href="#eligibility"
onClick={(e) => handleSmoothScroll(e, "#eligibility")}
>
<S.MobileNavText>지원 요건</S.MobileNavText>
</S.MobileNavItem>
</>
)}

{/* 확장/축소 버튼 */}
<S.ExpandButton onClick={() => setIsNavOpen((prev) => !prev)}>
{isNavOpen ? <IoMdArrowDropup /> : <IoMdArrowDropdown />}
</S.ExpandButton>
</S.MobileNavbar>
);
}
Loading