Skip to content

Commit c1fe944

Browse files
authored
Merge pull request #56 from prgrms-web-devcourse-final-project/style/community#18
Style/community#18
2 parents c9909ef + 0586a3d commit c1fe944

File tree

11 files changed

+224
-35
lines changed

11 files changed

+224
-35
lines changed

src/app/community/page.tsx

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,37 @@
1+
import CommunityFilter from '@/shared/components/community/CommunityFilter';
2+
import CommunityHeader from '@/shared/components/community/CommunityHeader';
3+
import CommunityTab from '@/shared/components/community/CommunityTab';
4+
import PostCard from '@/shared/components/community/PostCard';
5+
import WriteBtn from '@/shared/components/community/WriteBtn';
6+
17
function Page() {
2-
return <div></div>;
8+
return (
9+
<main className="page-layout max-w-1024">
10+
<div className="mt-3 mb-10 flex flex-col gap-8 ">
11+
<section aria-labelledby="community-heading">
12+
<h1 id="community-heading" className="sr-only">
13+
커뮤니티 페이지
14+
</h1>
15+
<CommunityHeader />
16+
</section>
17+
18+
<section
19+
aria-label="탭과 글쓰기"
20+
className="flex justify-between item-center sm:flex-row flex-col gap-4 mt-1"
21+
>
22+
<CommunityTab />
23+
<WriteBtn />
24+
</section>
25+
26+
<section aria-label="게시물 목록">
27+
<CommunityFilter />
28+
<PostCard label="레시피" />
29+
<PostCard label="팁" />
30+
<PostCard label="질문" />
31+
<PostCard label="자유" />
32+
</section>
33+
</div>
34+
</main>
35+
);
336
}
437
export default Page;
11.1 KB
Loading

src/shared/components/InputBox/SelectBox.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function SelectBox({ ref, option, title }: Props) {
2121
};
2222

2323
return (
24-
<div className="flex flex-col gap-2 relative h-6 w-30">
24+
<div className="flex flex-col gap-2 relative h-6">
2525
<button
2626
ref={ref}
2727
className="flex gap-2 cursor-pointer text-base"
@@ -38,7 +38,7 @@ function SelectBox({ ref, option, title }: Props) {
3838

3939
<ul
4040
className={`w-30 bg-white text-gray-dark p-2 rounded-xl duration-200 absolute transition-all
41-
${isOpen ? 'opacity-100 top-8' : 'opacity-0 pointer-events-none top-4'}`}
41+
${isOpen ? 'opacity-100 top-8 right-0' : 'opacity-0 pointer-events-none top-4 right-0'}`}
4242
role="listbox"
4343
>
4444
{option.map((v, i) => (
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use client';
2+
3+
import SelectBox from '../InputBox/SelectBox';
4+
function CommunityFilter() {
5+
return (
6+
<section
7+
className="w-full flex justify-between items-center border-b-1 border-gray-light pb-1.5"
8+
aria-label="커뮤니티 정렬 필터"
9+
>
10+
<p aria-live="polite">100개</p>
11+
<SelectBox option={['최신순', '인기순', '댓글순']} title={'최신순'} />
12+
</section>
13+
);
14+
}
15+
16+
export default CommunityFilter;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import PageHeader from '../pageHeader/PageHeader';
2+
import headerImg from '@/shared/assets/images/community_page_header.webp';
3+
4+
function CommunityHeader() {
5+
return (
6+
<section aria-label="커뮤니티 헤더">
7+
<PageHeader src={headerImg} title="Community" description="칵테일에 관한 모든 이야기" />
8+
</section>
9+
);
10+
}
11+
12+
export default CommunityHeader;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use client';
2+
3+
import tw from '@/shared/utills/tw';
4+
import { useState } from 'react';
5+
6+
const tabItem = [
7+
{ title: '전체' },
8+
{ title: '레시피' },
9+
{ title: '팁' },
10+
{ title: '질문' },
11+
{ title: '자유' },
12+
];
13+
14+
function CommunityTab() {
15+
const [selectedIdx, setSelectedIdx] = useState(0);
16+
17+
return (
18+
<section className="relative sm:w-[70%] w-full" aria-label="커뮤니티 탭">
19+
<div className="w-full overflow-x-scroll no-scrollbar scroll-smooth">
20+
<div className="flex gap-3 w-max" aria-label="커뮤니티 카테고리">
21+
{tabItem.map(({ title }, idx) => (
22+
<button
23+
key={title + idx}
24+
role="tab"
25+
aria-selected={selectedIdx === idx}
26+
tabIndex={selectedIdx === idx ? 0 : -1}
27+
onClick={() => setSelectedIdx(idx)}
28+
className={tw(
29+
`border-1 py-1 px-3 rounded-2xl transition-colors ease-in`,
30+
selectedIdx === idx ? 'bg-secondary text-primary' : ''
31+
)}
32+
>
33+
{title}
34+
</button>
35+
))}
36+
</div>
37+
</div>
38+
</section>
39+
);
40+
}
41+
42+
export default CommunityTab;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import Image from 'next/image';
2+
import prePost from '@/shared/assets/images/prepost_img.webp';
3+
import PostLabel from './PostLabel';
4+
5+
function PostCard({ label }: { label: string }) {
6+
return (
7+
<article className="pt-[30] pb-3 border-b-1 border-gray-light">
8+
<PostLabel title={label} />
9+
10+
<section className="flex items-start justify-between mt-3 cursor-pointer" role="link">
11+
<div className="flex flex-col gap-3">
12+
<p className="font-bold sm:text-xl text-lg">칵테일 만들 때 준비물</p>
13+
<div className="font-light sm:text-[15px] text-sm">
14+
<p>칵테일 처음 만들어 보는데 랄랄</p>
15+
<p>가나다라마바사아자차카파타하</p>
16+
</div>
17+
<ul
18+
className="flex font-light sm:gap-3 gap-1 sm:text-[14px] text-[12px] text-gray"
19+
aria-label="게시글 정보"
20+
>
21+
<li>실버븬</li>
22+
<li aria-hidden="true">|</li>
23+
<li>3분 전</li>
24+
<li aria-hidden="true">|</li>
25+
<li>조회 3</li>
26+
<li aria-hidden="true">|</li>
27+
<li>댓글 3</li>
28+
</ul>
29+
</div>
30+
<figure className="flex items-start">
31+
<Image
32+
src={prePost}
33+
alt="예비사진"
34+
width={120}
35+
height={120}
36+
className="md:w-[120px] sm:w-[100px] w-[80px] self-start"
37+
/>
38+
</figure>
39+
</section>
40+
</article>
41+
);
42+
}
43+
44+
export default PostCard;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
function PostLabel({ title }: { title: string }) {
2+
return (
3+
<span
4+
role="status"
5+
aria-label={title}
6+
className={` text-primary py-1 px-2 rounded-md text-sm
7+
${
8+
title === '레시피'
9+
? 'bg-[#FFE4E6]'
10+
: title === '팁'
11+
? 'bg-[#EDE9FE]'
12+
: title === '질문'
13+
? 'bg-[#E0F2FE]'
14+
: title === '자유'
15+
? 'bg-[#D1FAE5]'
16+
: ''
17+
}`}
18+
>
19+
{title}
20+
</span>
21+
);
22+
}
23+
24+
export default PostLabel;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import Write from '@/shared/assets/icons/edit_28.svg';
2+
3+
function WriteBtn() {
4+
return (
5+
<button className="flex items-center justify-center py-1 px-2.5 bg-tertiary rounded-lg">
6+
<Write />
7+
글쓰기
8+
</button>
9+
);
10+
}
11+
12+
export default WriteBtn;

src/shared/components/header/DropdownMenu.tsx

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ function DropdownMenu({ isClicked, setIsClicked }: Props) {
5858
};
5959

6060
return (
61-
<div
61+
<nav
6262
className="w-full h-screen bg-secondary absolute top-0 left-0 px-[12px] font-serif block sm:hidden"
63-
role="menu"
63+
role="navigation"
6464
aria-label="메인 네비게이션 메뉴"
6565
tabIndex={-1}
6666
id="mobile-dropdown-menu"
@@ -75,52 +75,53 @@ function DropdownMenu({ isClicked, setIsClicked }: Props) {
7575
className="w-[62px] md:w-[82px] h-auto"
7676
/>
7777
</div>
78-
<div className="my-5">
79-
<ul className="flex flex-col gap-[12px] text-black px-2">
80-
{navItem.map(({ label, href }, idx) => (
81-
<li
82-
className={`font-normal ${pathname === href ? 'pl-1' : 'px-3 py-[12px]'}`}
83-
key={href}
78+
<ul className="flex flex-col gap-[12px] text-black px-2 my-5">
79+
{navItem.map(({ label, href }, idx) => (
80+
<li className={`font-normal ${pathname === href ? 'pl-1' : 'px-3 py-[12px]'}`} key={href}>
81+
<Link
82+
href={href}
83+
onNavigate={() => setIsClicked(false)}
84+
className={`items-start ${pathname === href ? 'bg-tertiary/70 inline-flex pr-5 p-2 rounded-md text-secondary' : 'hover:text-black/70 flex'}`}
85+
aria-current={pathname === href ? 'page' : undefined}
8486
>
85-
<Link
86-
href={href}
87-
onNavigate={() => setIsClicked(false)}
88-
className={`items-start ${pathname === href ? 'bg-tertiary/70 inline-flex pr-5 p-2 rounded-md text-secondary' : 'hover:text-black/70 flex'}`}
89-
aria-current={pathname === href ? 'page' : undefined}
87+
<span className="text-[20px] mr-3">{idx + 1}. </span>
88+
<span
89+
className="text-[28px]"
90+
ref={(el) => {
91+
textRef.current[idx] = el;
92+
}}
93+
onMouseEnter={() => handleMouseEnter(idx)}
94+
onMouseLeave={() => handleMouseLeave(idx)}
9095
>
91-
<span className="text-[20px] mr-3">{idx + 1}. </span>
92-
<span
93-
className="text-[28px]"
94-
ref={(el) => {
95-
textRef.current[idx] = el;
96-
}}
97-
onMouseEnter={() => handleMouseEnter(idx)}
98-
onMouseLeave={() => handleMouseLeave(idx)}
99-
>
100-
{label}
101-
</span>
102-
</Link>
103-
</li>
104-
))}
105-
</ul>
106-
</div>
107-
<div className="border border-t-[1px] border-t-gray flex items-center py-[32px] gap-2">
96+
{label}
97+
</span>
98+
</Link>
99+
</li>
100+
))}
101+
</ul>
102+
103+
<section
104+
aria-label="로그인 로그아웃"
105+
className="border border-t-[1px] border-t-gray flex items-center py-[32px] gap-2"
106+
>
108107
<User color="var(--color-primary)" />
109108
<button type="button" className="text-black font-light text-xl hover:text-black/70">
110109
로그인/회원가입
111110
</button>
112-
</div>
111+
</section>
112+
113113
<div className="absolute top-1.5 left-3">
114114
<button
115115
type="button"
116+
aria-label="모바일 메뉴 닫기"
116117
onClick={() => {
117118
setIsClicked(false);
118119
}}
119120
>
120121
<Close color="var(--color-primary)" className="w-8 h-8" />
121122
</button>
122123
</div>
123-
</div>
124+
</nav>
124125
);
125126
}
126127

0 commit comments

Comments
 (0)