Skip to content

Commit c3ecfd2

Browse files
AAminhanirii00
authored andcommitted
design: 내 편지함 페이지 퍼블리싱 (#16)
* design: 내 편지함 목록 페이지 퍼블리싱 * refactor: 리스트 디자인 컴포넌트로 분리 * design: 컴포넌트 props명 수정 및 sender, receiver 디자인 변경 * design: 내 편지함 상세 페이지 퍼블리싱 * refactor: 배경 이미지 삽입되는 로직 컴포넌트로 분리 * design: 필요한 모달 퍼블리싱 및 버튼과 연결 * rename: ListItemContainer -> ListItemWrapper로 컴포넌트명 수정 * refactor: 페이지 제목에 PageTitle 컴포넌트 적용
1 parent 223950a commit c3ecfd2

File tree

26 files changed

+499
-56
lines changed

26 files changed

+499
-56
lines changed

src/App.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Home from './pages/Home';
66
import LetterBoardPage from './pages/LetterBoard';
77
import LetterBoardDetailPage from './pages/LetterBoardDetail';
88
import LetterBoxPage from './pages/LetterBox';
9+
import LetterBoxDetailPage from './pages/LetterBoxDetail';
910
import LetterDetailPage from './pages/LetterDetail';
1011
import LoginPage from './pages/Login';
1112
import MyPage from './pages/MyPage';
@@ -25,8 +26,11 @@ const App = () => {
2526
<Route path="login" element={<LoginPage />} />
2627
<Route path="onboarding" element={<OnboardingPage />} />
2728
<Route path="letter">
28-
<Route path="random" element={<RandomLettersPage />} />
29-
<Route path="box" element={<LetterBoxPage />} />
29+
<Route element={<Layout />}>
30+
<Route path="random" element={<RandomLettersPage />} />
31+
<Route path="box" element={<LetterBoxPage />} />
32+
<Route path="box/:id" element={<LetterBoxDetailPage />} />
33+
</Route>
3034
<Route path="write" element={<WritePage />} />
3135
<Route path=":id" element={<LetterDetailPage />} />
3236
</Route>

src/assets/icons/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import ArrowLeftIcon from './arrow-left.svg?react';
33
import BoardIcon from './board.svg?react';
44
import DeleteIcon from './delete.svg?react';
55
import EnvelopeIcon from './envelope.svg?react';
6+
import InformationIcon from './infromation.svg?react';
67
import LikeFilledIcon from './like-filled.svg?react';
78
import LikeOutlinedIcon from './like-outlined.svg?react';
89
import NoticeIcon from './notice.svg?react';
@@ -14,6 +15,7 @@ export {
1415
AlarmIcon,
1516
PersonIcon,
1617
ArrowLeftIcon,
18+
InformationIcon,
1719
SirenFilledIcon,
1820
SirenOutlinedIcon,
1921
EnvelopeIcon,

src/assets/icons/infromation.svg

Lines changed: 8 additions & 0 deletions
Loading

src/assets/images/door.png

10.3 KB
Loading

src/components/BackgroundBottom.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import BgItem from '@/assets/images/field-4.png';
22

3+
import BackgroundImageWrapper from './BackgroundImageWrapper';
4+
35
const BackgroundBottom = () => {
46
return (
5-
<div
6-
className="background-image-filled fixed bottom-[-40px] left-1/2 z-[-10] h-42 w-full -translate-x-1/2 opacity-70"
7-
style={{ '--bg-image': `url(${BgItem})` } as React.CSSProperties}
7+
<BackgroundImageWrapper
8+
as="div"
9+
className="fixed bottom-[-40px] left-1/2 z-[-10] h-42 w-full -translate-x-1/2 opacity-70"
10+
imageUrl={BgItem}
811
/>
912
);
1013
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { twMerge } from 'tailwind-merge';
2+
3+
interface BackgroundImageWrapperProps {
4+
as?: React.ElementType;
5+
imageUrl: string;
6+
className?: string;
7+
children?: React.ReactNode;
8+
onClick?: () => void;
9+
}
10+
11+
const BackgroundImageWrapper = ({
12+
as: Component = 'div',
13+
imageUrl,
14+
className,
15+
children,
16+
onClick,
17+
}: BackgroundImageWrapperProps) => {
18+
return (
19+
<Component
20+
className={twMerge('background-image-filled', className)}
21+
style={{ '--bg-image': `url(${imageUrl})` } as React.CSSProperties}
22+
onClick={onClick}
23+
>
24+
{children}
25+
</Component>
26+
);
27+
};
28+
29+
export default BackgroundImageWrapper;

src/components/ConfirmModal.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import ModalBg from '@/assets/images/modal-yellow.png';
22

3+
import BackgroundImageWrapper from './BackgroundImageWrapper';
34
import ModalOverlay from './ModalOverlay';
45

56
interface ConfirmModalProps {
@@ -27,16 +28,13 @@ const ConfirmModal = ({
2728
return (
2829
<ModalOverlay>
2930
<div className="w-73">
30-
<section
31-
className="background-image-filled mb-12 rounded-lg p-5"
32-
style={{ '--bg-image': `url(${ModalBg})` } as React.CSSProperties}
33-
>
31+
<BackgroundImageWrapper as="section" className="mb-12 rounded-lg p-5" imageUrl={ModalBg}>
3432
<div className="flex flex-col gap-1">
3533
<p className="body-m text-gray-80">{title}</p>
3634
<p className="caption-r text-black">{description}</p>
3735
</div>
3836
{children}
39-
</section>
37+
</BackgroundImageWrapper>
4038
<section className="flex items-center gap-6">
4139
<button
4240
type="button"

src/components/ListItemWrapper.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { twMerge } from 'tailwind-merge';
2+
3+
interface ListItemWrapperProps {
4+
isSender?: boolean;
5+
className?: string;
6+
children: React.ReactNode;
7+
onClick?: (e: React.MouseEvent<HTMLElement>) => void;
8+
}
9+
10+
const ListItemWrapper = ({
11+
isSender = false,
12+
className,
13+
children,
14+
onClick,
15+
}: ListItemWrapperProps) => {
16+
return (
17+
<article
18+
className={twMerge(
19+
'relative flex overflow-hidden rounded-sm p-4',
20+
isSender ? 'list-sender-bg' : 'list-receiver-bg',
21+
className,
22+
)}
23+
onClick={onClick}
24+
>
25+
<div className="z-10 w-full">{children}</div>
26+
<div className="absolute inset-0 z-0 bg-white/50 blur-xl" />
27+
</article>
28+
);
29+
};
30+
31+
export default ListItemWrapper;

src/components/MessageModal.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ChangeEvent } from 'react';
22

33
import ModalBg from '@/assets/images/modal-pink.png';
44

5+
import BackgroundImageWrapper from './BackgroundImageWrapper';
56
import ModalOverlay from './ModalOverlay';
67
import TextareaField from './TextareaField';
78

@@ -30,19 +31,16 @@ const MessageModal = ({
3031
}: MessageModalProps) => {
3132
return (
3233
<ModalOverlay>
33-
<p className="body-sb mb-4 text-white">{description}</p>
34-
<section
35-
className="background-image-filled mb-12 w-78 rounded-lg p-4"
36-
style={{ '--bg-image': `url(${ModalBg})` } as React.CSSProperties}
37-
>
34+
<p className="body-sb mb-4 text-center text-white">{description}</p>
35+
<BackgroundImageWrapper as="section" className="mb-12 w-78 rounded-lg p-4" imageUrl={ModalBg}>
3836
<TextareaField
3937
rows={5}
4038
value={inputValue}
4139
placeholder={placeholder}
4240
onChange={onInputChange}
4341
/>
4442
{children}
45-
</section>
43+
</BackgroundImageWrapper>
4644
<section className="flex items-center gap-6">
4745
<button
4846
type="button"

src/components/PageTitle.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ interface PageTitleProps {
77

88
const PageTitle = ({ className, children }: PageTitleProps) => {
99
return (
10-
<h1 className={twMerge('text-gray-60 body-b rounded-full bg-white px-6 py-4', className)}>
10+
<h1 className={twMerge('text-gray-60 body-b w-fit rounded-full bg-white px-6 py-4', className)}>
1111
{children}
1212
</h1>
1313
);

0 commit comments

Comments
 (0)