Skip to content

Commit 805b556

Browse files
committed
refactor: header 컴포넌트 리팩토링
1 parent 946b68e commit 805b556

File tree

6 files changed

+78
-148
lines changed

6 files changed

+78
-148
lines changed
Lines changed: 15 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,22 @@
1-
import { useEffect, useState } from 'react';
2-
import { Link, useRouterState } from '@tanstack/react-router';
3-
import { Harmony } from '@/components/logo';
4-
import { Button } from '@/components/ui/button';
5-
import { cn } from '@/lib/utils';
6-
7-
interface HeaderProps {
8-
className?: string;
9-
}
10-
11-
function Header({ className }: HeaderProps) {
12-
const router = useRouterState();
13-
const { pathname } = router.location;
14-
const [isTop, setIsTop] = useState(true);
15-
16-
useEffect(() => {
17-
const handleScroll = () => {
18-
const currentScrollY = window.scrollY;
19-
setIsTop(currentScrollY <= 10);
20-
};
21-
22-
handleScroll();
23-
window.addEventListener('scroll', handleScroll, { passive: true });
24-
25-
return () => window.removeEventListener('scroll', handleScroll);
26-
}, []);
27-
28-
const isLoginPage = pathname === '/login';
29-
const isSignupPage = pathname === '/signup';
30-
31-
const headerClasses = cn(
32-
'fixed top-0 w-full h-16',
33-
'flex items-center justify-between',
34-
'px-6 bg-white dark:bg-black',
35-
'text-black dark:text-white',
36-
'transition-all duration-200',
37-
{
38-
'border-b border-gray-200 dark:border-gray-800 shadow-sm': !isTop,
39-
},
40-
className
41-
);
1+
import { ReactNode } from 'react';
422

3+
function Header({ children }: { children: ReactNode }) {
434
return (
44-
<header className={headerClasses}>
45-
{/* Logo Section */}
46-
<div className="flex items-center space-x-4">
47-
<Link to="/" className="transition-opacity hover:opacity-80">
48-
<Harmony size={32} />
49-
</Link>
50-
</div>
51-
52-
{/* Navigation Buttons */}
53-
<nav className="flex items-center space-x-3">
54-
{!isLoginPage && (
55-
<Button variant={isSignupPage ? 'outline' : 'ghost'} asChild>
56-
<Link to="/login" className="hover:text-primary font-medium transition-colors">
57-
로그인
58-
</Link>
59-
</Button>
60-
)}
61-
62-
{!isSignupPage && (
63-
<Button variant="outline" asChild>
64-
<Link to="/signup" className="hover:text-primary font-medium transition-colors">
65-
회원가입
66-
</Link>
67-
</Button>
68-
)}
69-
</nav>
5+
<header className="px-6">
6+
<nav className="flex h-16 items-center justify-between">{children}</nav>
707
</header>
718
);
729
}
7310

11+
function Left({ children }: { children: ReactNode }) {
12+
return <div className="flex items-center gap-4">{children}</div>;
13+
}
14+
15+
function Right({ children }: { children: ReactNode }) {
16+
return <div className="flex items-center gap-2">{children}</div>;
17+
}
18+
19+
Header.Left = Left;
20+
Header.Right = Right;
21+
7422
export default Header;

apps/client/src/components/navigation/topbar.tsx

Lines changed: 0 additions & 15 deletions
This file was deleted.

apps/client/src/pages/Home.tsx

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
import { Link } from '@tanstack/react-router';
22
import { Button } from '@/components/ui/button';
33
import { Github, HarmonyWithText } from '@/components/logo';
4-
import { Topbar } from '@/components/navigation/topbar';
4+
import Header from '@/components/Header';
55

66
function Home() {
77
return (
88
<div className="flex min-h-screen flex-col">
9-
<Topbar
10-
leftContent={
9+
<Header>
10+
<Header.Left>
1111
<Link to="/">
1212
<HarmonyWithText />
1313
</Link>
14-
}
15-
rightContent={
16-
<>
17-
<Button variant="ghost" asChild>
18-
<Link to="/login">Login</Link>
19-
</Button>
20-
<Button asChild>
21-
<Link to="/signup">Register</Link>
22-
</Button>
23-
</>
24-
}
25-
/>
14+
</Header.Left>
15+
<Header.Right>
16+
<Button variant="ghost" className="hover:text-primary hover:bg-white" asChild>
17+
<Link to="/login">Login</Link>
18+
</Button>
19+
<Button asChild>
20+
<Link to="/signup">Register</Link>
21+
</Button>
22+
</Header.Right>
23+
</Header>
2624

2725
<main className="mt-16 flex-grow bg-white text-black dark:bg-black dark:text-white">
2826
<section className="container mx-auto max-w-6xl from-pink-500 via-red-500 to-yellow-500 px-6 py-20 text-center">

apps/client/src/pages/Login.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
import { Link } from '@tanstack/react-router';
22
import { Button } from '@/components/ui/button.tsx';
33
import { HarmonyWithText } from '@/components/logo';
4-
import { Topbar } from '@/components/navigation/topbar';
4+
import Header from '@/components/Header';
55
import Footer from '@/components/Footer.tsx';
66
import { LoginForm } from '@/features/auth/components/LoginForm.tsx';
77

88
function Login() {
99
return (
1010
<>
1111
<div className="flex h-screen flex-col">
12-
<Topbar
13-
leftContent={
12+
<Header>
13+
<Header.Left>
1414
<Link to="/">
1515
<HarmonyWithText />
1616
</Link>
17-
}
18-
rightContent={
19-
<Button variant="outline" asChild>
17+
</Header.Left>
18+
<Header.Right>
19+
<Button variant="outline" className="hover:bg-primary hover:text-white" asChild>
2020
<Link to="/signup">Register</Link>
2121
</Button>
22-
}
23-
/>
22+
</Header.Right>
23+
</Header>
2424

2525
<main className="flex h-full items-center justify-center">
2626
<div className="w-full max-w-md">

apps/client/src/pages/Signup.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
import { Link } from '@tanstack/react-router';
22
import { Button } from '@/components/ui/button';
33
import { HarmonyWithText } from '@/components/logo';
4-
import { Topbar } from '@/components/navigation/topbar';
4+
import Header from '@/components/Header';
55
import Footer from '@/components/Footer.tsx';
66
import { SignupForm } from '@/features/auth/components/SignupForm.tsx';
77

88
export function Signup() {
99
return (
1010
<div className="flex h-screen flex-col">
11-
<Topbar
12-
leftContent={
11+
<Header>
12+
<Header.Left>
1313
<Link to="/">
1414
<HarmonyWithText />
1515
</Link>
16-
}
17-
rightContent={
18-
<Button variant="outline" asChild>
16+
</Header.Left>
17+
<Header.Right>
18+
<Button variant="outline" className="hover:bg-primary hover:text-white" asChild>
1919
<Link to="/login">Login</Link>
2020
</Button>
21-
}
22-
/>
21+
</Header.Right>
22+
</Header>
23+
2324
<main className="flex h-full items-center justify-center">
2425
<div className="w-full max-w-md rounded-2xl border">
2526
<div className="mb-8 pt-12 text-center">

apps/client/src/routes/_auth.tsx

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { SlashIcon } from '@radix-ui/react-icons';
55
import { ChangeEvent, useState } from 'react';
66
import axios from 'axios';
77
import { Harmony } from '@/components/logo';
8-
import { Topbar } from '@/components/navigation/topbar';
8+
import Header from '@/components/Header';
99
import {
1010
DropdownMenu,
1111
DropdownMenuContent,
@@ -220,43 +220,41 @@ function AuthLayout() {
220220

221221
return (
222222
<div>
223-
<Topbar
224-
leftContent={
225-
<>
226-
<Link to={params.project === undefined ? '/account' : '/$project'}>
227-
<Harmony />
228-
</Link>
229-
<SlashIcon className="h-5 text-gray-300" />
230-
<div className="flex items-center gap-2">
231-
<h2>{(params.project && currentProject?.title) ?? 'My Account'}</h2>
232-
<DropdownMenu>
233-
<DropdownMenuTrigger className="h-8">
234-
<ChevronsUpDownIcon className="h-4 w-4" />
235-
</DropdownMenuTrigger>
236-
<DropdownMenuContent align="start" className="bg-white">
223+
<Header>
224+
<Header.Left>
225+
<Link to={params.project === undefined ? '/account' : '/$project'}>
226+
<Harmony />
227+
</Link>
228+
<SlashIcon className="h-5 text-gray-300" />
229+
<div className="flex items-center gap-2">
230+
<h2>{(params.project && currentProject?.title) ?? 'My Account'}</h2>
231+
<DropdownMenu>
232+
<DropdownMenuTrigger className="h-8">
233+
<ChevronsUpDownIcon className="h-4 w-4" />
234+
</DropdownMenuTrigger>
235+
<DropdownMenuContent align="start" className="bg-white">
236+
<DropdownMenuItem
237+
asChild
238+
className="hover:cursor-pointer focus:bg-[#f2f2f2] focus:text-black"
239+
>
240+
<Link to="/account">My Account</Link>
241+
</DropdownMenuItem>
242+
{projects.map((project) => (
237243
<DropdownMenuItem
244+
key={project.id}
238245
asChild
239246
className="hover:cursor-pointer focus:bg-[#f2f2f2] focus:text-black"
240247
>
241-
<Link to="/account">My Account</Link>
248+
<Link to="/$project/board" params={{ project: String(project.id) }}>
249+
{project.title}
250+
</Link>
242251
</DropdownMenuItem>
243-
{projects.map((project) => (
244-
<DropdownMenuItem
245-
key={project.id}
246-
asChild
247-
className="hover:cursor-pointer focus:bg-[#f2f2f2] focus:text-black"
248-
>
249-
<Link to="/$project/board" params={{ project: String(project.id) }}>
250-
{project.title}
251-
</Link>
252-
</DropdownMenuItem>
253-
))}
254-
</DropdownMenuContent>
255-
</DropdownMenu>
256-
</div>
257-
</>
258-
}
259-
rightContent={
252+
))}
253+
</DropdownMenuContent>
254+
</DropdownMenu>
255+
</div>
256+
</Header.Left>
257+
<Header.Right>
260258
<DropdownMenu>
261259
<DropdownMenuTrigger>
262260
<Avatar className="h-8 w-8 border">
@@ -283,8 +281,8 @@ function AuthLayout() {
283281
</DropdownMenuItem>
284282
</DropdownMenuContent>
285283
</DropdownMenu>
286-
}
287-
/>
284+
</Header.Right>
285+
</Header>
288286
<Dialog
289287
open={isProfileOpen}
290288
onOpenChange={(isProfileOpen) => {

0 commit comments

Comments
 (0)