Skip to content

Commit b49ac52

Browse files
authored
Merge pull request #32 from geulDa/feat/#17/header-components
✨Feat: header components 구현
2 parents fd6cef7 + 1dc2915 commit b49ac52

File tree

4 files changed

+133
-4
lines changed

4 files changed

+133
-4
lines changed

src/pages/index.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1+
import { ControlBar, Header } from '@/shared/components';
12
import { Icon } from '@/shared/icons';
23

34
export default function Home() {
45
return (
56
<>
67
<div className='flex flex-col items-center justify-center min-h-screen py-2 bg-gray-50'>
78
<main className='flex flex-col items-center justify-center w-full flex-1 px-4 sm:px-20 text-center'>
9+
<Header onClick={() => {}} className='' title={'글다'} />
10+
<ControlBar isLoggedIn={false} onLogin={() => {}} userName={''} />
11+
<ControlBar isLoggedIn={true} userName='홍길동' onLogin={() => {}} />
812
<h1 className='text-4xl sm:text-6xl font-extrabold text-gray-900 mb-4'>
913
초기 세팅 완료
1014
<Icon name='User' color='mint-600' />
1115
</h1>
12-
<Icon name='CalendarBlank' size={200} color='gray-900' />
13-
<Icon name='User' size={200} color='blue-400' />
14-
<Icon name='User' size={200} color='red-300' />
15-
<Icon name='User' size={200} color='red-300' />
16+
1617
<p className='mt-3 text-lg sm:text-2xl text-gray-600'>
1718
Next.js(Page Router) + TS + Tailwind + Axios
1819
</p>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { Icon } from '@/shared/icons';
2+
import { cn } from '@/shared/lib';
3+
import { cva } from 'class-variance-authority';
4+
5+
interface ControlBarProps {
6+
isLoggedIn: boolean;
7+
onLogin: () => void;
8+
userName: string;
9+
className?: string;
10+
}
11+
12+
const rightStyle = cva('flex items-center gap-[0.6rem] transition w-[7.8rem]', {
13+
variants: {
14+
state: {
15+
loggedIn: 'text-mint-600',
16+
guest: 'text-gray-400 hover:text-gray-600',
17+
},
18+
},
19+
defaultVariants: { state: 'guest' },
20+
});
21+
22+
const ControlBar = ({
23+
onLogin,
24+
isLoggedIn,
25+
userName = '글다',
26+
className,
27+
}: ControlBarProps) => {
28+
const rightState = isLoggedIn ? 'loggedIn' : ('guest' as const);
29+
const iconColor = isLoggedIn ? 'mint-600' : ('gray-400' as const);
30+
31+
return (
32+
<header className={cn('bg-none w-full h-[5.4rem]', className)} role='group'>
33+
<div className='h-full grid grid-cols-[auto_1fr_auto] items-center gap-[1.2rem]'>
34+
<div
35+
className='w-[7.8rem] h-[5.4rem] rounded-[0.6rem] bg-gray-200'
36+
aria-hidden
37+
/>
38+
39+
<h1 className='justify-self-center text-headline-sm-serif font-[400] leading-[2.4rem] tracking-[0.015rem] text-gray-900'>
40+
글다
41+
</h1>
42+
{isLoggedIn ? (
43+
<div className={cn(rightStyle({ state: rightState }), 'min-w-0')}>
44+
<Icon name='User' size={24} color={iconColor} />
45+
<span
46+
className='text-body-md w-[5.3rem] truncate block'
47+
aria-label={`${userName}님`}
48+
>
49+
{userName}
50+
</span>
51+
</div>
52+
) : (
53+
<button
54+
type='button'
55+
onClick={(e) => {
56+
e.stopPropagation();
57+
onLogin?.();
58+
}}
59+
className={rightStyle({ state: rightState })}
60+
aria-label='Log In'
61+
>
62+
<Icon name='User' size={24} color={iconColor} />
63+
<span className='text-body-md'>Log In</span>
64+
</button>
65+
)}
66+
</div>
67+
</header>
68+
);
69+
};
70+
71+
export default ControlBar;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { Icon } from '@/shared/icons';
2+
import { cn } from '@/shared/lib';
3+
import { cva, type VariantProps } from 'class-variance-authority';
4+
5+
interface HeaderProps {
6+
title: string;
7+
onClick: () => void;
8+
className?: string;
9+
color?: VariantProps<typeof headerStyle>['color'];
10+
}
11+
12+
const headerStyle = cva(
13+
'w-full h-[11.8rem] px-[1.6rem] pb-[1.8rem] pt-[7.6rem] fixed top-0 left-0 right-0 z-[100]',
14+
{
15+
variants: {
16+
color: {
17+
mint300: 'bg-mint-300',
18+
mint50: 'bg-mint-50',
19+
},
20+
},
21+
defaultVariants: {
22+
color: 'mint300',
23+
},
24+
},
25+
);
26+
27+
const Header = ({ title, onClick, color, className }: HeaderProps) => {
28+
return (
29+
<header className={cn(headerStyle({ color }), className)}>
30+
<div className='mx-auto h-[2.4rem] grid grid-cols-[auto_1fr_auto] items-center text-mint-900'>
31+
<button
32+
type='button'
33+
aria-label='뒤로가기'
34+
onClick={onClick}
35+
className='grid place-items-center w-[2.4rem] h-[2.4rem]'
36+
>
37+
<Icon name='Caret' size={24} color='mint-900' />
38+
</button>
39+
40+
<h1
41+
className={cn(
42+
'justify-self-center',
43+
'text-title-md font-[600] leading-[2.4rem] tracking-[0.015rem]',
44+
)}
45+
>
46+
{title}
47+
</h1>
48+
49+
<div aria-hidden className='w-[2.4rem] h-[2.4rem]' />
50+
</div>
51+
</header>
52+
);
53+
};
54+
55+
export default Header;

src/shared/components/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as Header } from './header/Header';
2+
export { default as ControlBar } from './header/ControlBar';

0 commit comments

Comments
 (0)