Skip to content

Commit d826980

Browse files
authored
Merge pull request #31 from DguFarmSystem/fix/25-fix-header-and-union-section
Fix/25 fix header and union section
2 parents 16a7342 + 08ec5fb commit d826980

File tree

9 files changed

+239
-57
lines changed

9 files changed

+239
-57
lines changed

package-lock.json

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"version": "0.0.0",
55
"type": "module",
66
"scripts": {
7-
"dev": "vite",
7+
"dev": "vite --host",
88
"type-check": "tsc --noEmit",
99
"build": "tsc -b && vite build",
1010
"lint": "eslint .",
@@ -16,6 +16,7 @@
1616
"framer-motion": "^12.4.3",
1717
"react": "^18.3.1",
1818
"react-dom": "^18.3.1",
19+
"react-icons": "^5.4.0",
1920
"react-responsive": "^10.0.0",
2021
"react-router": "^7.1.5",
2122
"react-slick": "^0.30.3",

src/pages/Main/FarmSyetemNav/FarmSystemNav.styled.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ interface FixedNavProps {
77

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

17+
1618
export const Navbar = styled.nav<{ $isMobile: boolean }>`
1719
background-color: #216D35;
1820
padding: 10px 20px;
Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,43 @@
11
import * as S from './FarmSystemNav.styled';
22
import { useState, useEffect } from 'react';
33
import useMediaQueries from '@/hooks/useMediaQueries';
4+
import MobileNav from './MobileNav';
5+
6+
const sectionIds = ["about", "tracks", "achievements", "eligibility"];
47

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

913
useEffect(() => {
1014
const handleScroll = () => {
11-
if (window.scrollY > 200) {
15+
const scrollPosition = window.scrollY;
16+
17+
if (scrollPosition > 200) {
1218
setIsVisible(true);
1319
} else {
1420
setIsVisible(false);
21+
}
22+
23+
// 현재 섹션 확인
24+
for (const section of sectionIds) {
25+
const element = document.getElementById(section);
26+
if (element) {
27+
const offsetTop = element.offsetTop;
28+
const offsetBottom = offsetTop + element.offsetHeight;
29+
30+
if (scrollPosition >= offsetTop - 100 && scrollPosition < offsetBottom - 100) {
31+
setCurrentSection(section);
32+
}
33+
}
1534
}
1635
};
1736

37+
1838
window.addEventListener("scroll", handleScroll);
39+
handleScroll();
40+
1941
return () => {
2042
window.removeEventListener("scroll", handleScroll);
2143
};
@@ -29,25 +51,33 @@ export default function FarmSystemNav() {
2951
top: targetElement.getBoundingClientRect().top + window.scrollY,
3052
behavior: "smooth",
3153
});
54+
setCurrentSection(targetId);
3255
}
3356
};
3457

3558
return (
3659
<S.FixedNavWrapper isVisible={isVisible} $isMobile={isMobile}>
37-
<S.Navbar $isMobile={isMobile}>
38-
<S.NavItem $isMobile={isMobile} href="#about" onClick={(e) => handleSmoothScroll(e, "#about")}>
39-
<S.Circle $isMobile={isMobile} /> Farm System이란?
40-
</S.NavItem>
41-
<S.NavItem $isMobile={isMobile} href="#tracks" onClick={(e) => handleSmoothScroll(e, "#tracks")}>
42-
<S.Circle $isMobile={isMobile} /> 트랙 및 커리큘럼
43-
</S.NavItem>
44-
<S.NavItem $isMobile={isMobile} href="#achievements" onClick={(e) => handleSmoothScroll(e, "#achievements")}>
45-
<S.Circle $isMobile={isMobile} /> 활동 및 성과
46-
</S.NavItem>
47-
<S.NavItem $isMobile={isMobile} href="#eligibility" onClick={(e) => handleSmoothScroll(e, "#eligibility")}>
48-
<S.Circle $isMobile={isMobile} /> 지원 요건
49-
</S.NavItem>
50-
</S.Navbar>
60+
{isMobile ? (
61+
<MobileNav
62+
currentSection={currentSection}
63+
handleSmoothScroll={handleSmoothScroll}
64+
/>
65+
) : (
66+
<S.Navbar $isMobile={isMobile}>
67+
<S.NavItem $isMobile={isMobile} href="#about" onClick={(e) => handleSmoothScroll(e, "#about")}>
68+
<S.Circle $isMobile={isMobile} /> Farm System이란?
69+
</S.NavItem>
70+
<S.NavItem $isMobile={isMobile} href="#tracks" onClick={(e) => handleSmoothScroll(e, "#tracks")}>
71+
<S.Circle $isMobile={isMobile} /> 트랙 및 커리큘럼
72+
</S.NavItem>
73+
<S.NavItem $isMobile={isMobile} href="#achievements" onClick={(e) => handleSmoothScroll(e, "#achievements")}>
74+
<S.Circle $isMobile={isMobile} /> 활동 및 성과
75+
</S.NavItem>
76+
<S.NavItem $isMobile={isMobile} href="#eligibility" onClick={(e) => handleSmoothScroll(e, "#eligibility")}>
77+
<S.Circle $isMobile={isMobile} /> 지원 요건
78+
</S.NavItem>
79+
</S.Navbar>
80+
)}
5181
</S.FixedNavWrapper>
5282
);
5383
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import styled from 'styled-components';
2+
3+
export const MobileNavbar = styled.div<{ isNavOpen: boolean }>`
4+
max-height: ${({ isNavOpen }) => (isNavOpen ? "300px" : "80px")};
5+
overflow: hidden;
6+
transition: max-height 0.1s ease-in-out;
7+
8+
display: inline-flex;
9+
height: auto;
10+
padding: 10px 10px;
11+
flex-direction: column;
12+
justify-content: center;
13+
align-items: center;
14+
15+
width: 150px;
16+
17+
border-radius: 20px 0px 20px 20px;
18+
border: 1px solid var(--FarmSystem_White, #FCFCFC);
19+
background: var(--FarmSystem_Green01, #28723F);
20+
`;
21+
22+
export const MobileNavItem = styled.a`
23+
display: flex;
24+
padding: 5px 0px;
25+
align-items: center;
26+
gap: 3px;
27+
flex: 1 0 0;
28+
`;
29+
30+
export const MobileNavText = styled.p`
31+
color: var(--FarmSystem_White, #FCFCFC);
32+
text-align: center;
33+
font-size: 14px;
34+
font-style: normal;
35+
font-weight: 500;
36+
line-height: 16px;
37+
letter-spacing: -0.24px;
38+
`;
39+
40+
/* 확장/축소 버튼 스타일 */
41+
export const ExpandButton = styled.button`
42+
color: var(--FarmSystem_White, #FCFCFC);
43+
font-size: 24px;
44+
cursor: pointer;
45+
width: 80%;
46+
background-color: rgba(0, 0, 0, 0.5);
47+
border-radius: 15px;
48+
49+
display: flex;
50+
justify-content: center;
51+
align-items: center;
52+
`;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { useState } from 'react';
2+
import * as S from './MobileNav.styled';
3+
import { IoMdArrowDropdown, IoMdArrowDropup } from "react-icons/io";
4+
5+
interface MobileNavProps {
6+
currentSection: string;
7+
handleSmoothScroll: (
8+
event: React.MouseEvent<HTMLAnchorElement, MouseEvent>,
9+
targetId: string
10+
) => void;
11+
}
12+
13+
const navItems = [
14+
{ id: "about", text: "Farm System이란?" },
15+
{ id: "tracks", text: "트랙 및 커리큘럼" },
16+
{ id: "achievements", text: "활동 및 성과" },
17+
{ id: "eligibility", text: "지원 요건" },
18+
];
19+
20+
export default function MobileNav({ currentSection, handleSmoothScroll }: MobileNavProps) {
21+
const [isNavOpen, setIsNavOpen] = useState(false);
22+
const currentNavItem = navItems.find(item => item.id === currentSection) ?? navItems[0];
23+
24+
return (
25+
<S.MobileNavbar isNavOpen={isNavOpen}>
26+
{/*
27+
isNavOpen이 false면 첫 번째 메뉴만 보이게,
28+
true면 모든 메뉴가 보이게 설정
29+
*/}
30+
{!isNavOpen && (
31+
<S.MobileNavItem
32+
href={"#" + currentNavItem.id}
33+
onClick={(e) => handleSmoothScroll(e, currentNavItem.id)}
34+
>
35+
<S.MobileNavText>{currentNavItem.text}</S.MobileNavText>
36+
</S.MobileNavItem>
37+
)}
38+
39+
{isNavOpen && (
40+
<>
41+
<S.MobileNavItem
42+
href="#about"
43+
onClick={(e) => handleSmoothScroll(e, "#about")}
44+
>
45+
<S.MobileNavText>Farm System이란?</S.MobileNavText>
46+
</S.MobileNavItem>
47+
<S.MobileNavItem
48+
href="#tracks"
49+
onClick={(e) => handleSmoothScroll(e, "#tracks")}
50+
>
51+
<S.MobileNavText>트랙 및 커리큘럼</S.MobileNavText>
52+
</S.MobileNavItem>
53+
<S.MobileNavItem
54+
href="#achievements"
55+
onClick={(e) => handleSmoothScroll(e, "#achievements")}
56+
>
57+
<S.MobileNavText>활동 및 성과</S.MobileNavText>
58+
</S.MobileNavItem>
59+
<S.MobileNavItem
60+
href="#eligibility"
61+
onClick={(e) => handleSmoothScroll(e, "#eligibility")}
62+
>
63+
<S.MobileNavText>지원 요건</S.MobileNavText>
64+
</S.MobileNavItem>
65+
</>
66+
)}
67+
68+
{/* 확장/축소 버튼 */}
69+
<S.ExpandButton onClick={() => setIsNavOpen((prev) => !prev)}>
70+
{isNavOpen ? <IoMdArrowDropup /> : <IoMdArrowDropdown />}
71+
</S.ExpandButton>
72+
</S.MobileNavbar>
73+
);
74+
}

0 commit comments

Comments
 (0)