Skip to content

Commit

Permalink
헤더 및 홈페이지 구현 완료
Browse files Browse the repository at this point in the history
  • Loading branch information
choihooo committed Jan 24, 2025
1 parent 0f0d83c commit b791188
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 11 deletions.
19 changes: 8 additions & 11 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useState } from "react";
import Header from "./components/Header.tsx";
import {
FullpageContainer,
FullpageSection,
Expand All @@ -11,25 +12,21 @@ export default function App() {

return (
<>
<header className="fixed top-0 left-0 z-50 w-full">
<nav className="flex justify-between text-white mx-[40px] mt-[12px] ">
<div>Howu</div>
<div className="opacity-50">
<img src="/menu.svg" />
</div>
</nav>
</header>
<Header />
<FullpageContainer
activeIndex={activeIndex}
setActiveIndex={setActiveIndex}
>
<FullpageSection name="first">
<FullpageSection name="Home">
<Home />
</FullpageSection>
<FullpageSection name="second">
<FullpageSection name="Intro">
<div>Section 2</div>
</FullpageSection>
<FullpageSection name="third">
<FullpageSection name="Project">
<div>Section 3</div>
</FullpageSection>
<FullpageSection name="Activities">
<div>Section 3</div>
</FullpageSection>
</FullpageContainer>
Expand Down
126 changes: 126 additions & 0 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { useRef, useEffect, useState } from "react";
import { useSpring, animated, config } from "@react-spring/web";

function Header() {
const [menuOpen, setMenuOpen] = useState(false);
const menuRef = useRef<HTMLDivElement>(null);

// 메뉴 외부 클릭 감지
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
setMenuOpen(false);
}
};

document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [menuRef]);

const menuAnimation = useSpring({
transform: menuOpen ? "translateX(0%)" : "translateX(100%)",
opacity: menuOpen ? 1 : 0,
config: config.stiff,
onRest: () => {
if (!menuOpen) {
setMenuOpen(false); // Ensure menu is set to closed after animation completes
}
},
});

const items = ["Home", "Intro", "Project", "Activities"];
const menuItems = items.map((item, index) => {
const delay = menuOpen ? index * 100 : (items.length - index - 1) * 100;
const itemAnimation = useSpring({
transform: menuOpen ? "translateX(0px)" : "translateX(250px)",
opacity: menuOpen ? 1 : 0,
delay,
config: config.wobbly,
});

return (
<animated.button
style={itemAnimation}
className="px-10 text-3xl font-bold text-left"
key={item}
onClick={() => {
setMenuOpen(false);
window.location.hash = `#${item}`;
}}
>
{item}
</animated.button>
);
});

const blogAnimation = useSpring({
transform: menuOpen ? "translateX(0px)" : "translateX(250px)",
opacity: menuOpen ? 1 : 0,
delay: menuOpen ? 500 : 100,
config: config.wobbly,
});

const divAnimation = useSpring({
transform: menuOpen ? "translateX(0px)" : "translateX(250px)",
opacity: menuOpen ? 1 : 0,
delay: menuOpen ? 600 : 0,
config: config.wobbly,
});

const contactAnimation = useSpring({
transform: menuOpen ? "translateX(0px)" : "translateX(250px)",
opacity: menuOpen ? 1 : 0,
delay: menuOpen ? 700 : 200,
config: config.wobbly,
});

return (
<header className="fixed top-0 left-0 z-50 w-full">
<nav className="flex items-center justify-between px-5 py-5 text-white">
<div>Howu</div>
<div onClick={() => setMenuOpen(!menuOpen)}>
<img src="/menu.svg" alt="Menu" className="cursor-pointer" />
</div>
</nav>
<animated.div
ref={menuRef}
style={menuAnimation}
className="fixed top-0 right-0 w-[400px] h-full bg-black text-white opacity-95"
>
<button
onClick={() => setMenuOpen(false)}
className="absolute text-white top-5 right-5"
>
X
</button>
<div className="flex flex-col py-[100px] gap-[24px]">{menuItems}</div>
<div className="flex items-center gap-3 px-10 text-left">
<animated.button
onClick={() => {
window.open("https://blog.howu.run", "_blank");
}}
style={blogAnimation}
>
Blog
</animated.button>
<animated.div
style={divAnimation}
className="w-[1px] h-3 bg-white"
></animated.div>
<animated.button
onClick={() => {
window.location.href = "mailto:[email protected]";
}}
style={contactAnimation}
>
Contact
</animated.button>
</div>
</animated.div>
</header>
);
}

export default Header;
File renamed without changes.
File renamed without changes.
Empty file added src/pages/Project.tsx
Empty file.

0 comments on commit b791188

Please sign in to comment.