Skip to content

Commit 7a22827

Browse files
authored
Shared components - 모달 추가 및 기타 컴포넌트 디자인 변경 반영 (#21)
* feat: 일부 공유 컴포넌트 반응형으로 수정 고정 너비가 아니라 full로 수정함. 고정 크기일 필요가 없어보여서 임시로 수정. 추후 디자이너가 결정한 것으로 수정 가능. * feat: 배너 컴포넌트 반응형으로 수정 * feat: 모달 컴포넌트 및 관련 훅과 스토어 생성 (진행중) 모달 공통 컴포넌트와 파생 컴포넌트 제작. 공통에서 종속적인 부분이 있어 합성 컴포넌트로 제작. 모달 전역 관리를 위해 zustand와 커스텀 훅을 사용. svgr관련 세팅 대해 브랜치 꼬여서 임시 저장. * feat: ModalAddingSubGoal 일단 완성. 일단, 외부로 동작의 책임을 넘김. 기타 변경사항들은 코드 다듬기. * feat: next설정에서 svgr처리. * feat: ModalButton컴포넌트 디자인 디테일 수정 전체 border대해 round가 아니도록. 길이는 외부의 container에서 처리할 수 있도록. * feat: 메인 페이지 원상 복구 useModal확인 용으로 사용했었어서, 기본 값으로 복원했습니다. * feat: 모달 합성 컴포넌트 재료 및 ModalAddingSubGoal위치 변경 및 스토리 수정 폴더 깔끔하게 수정. 스토리북에서 설명 및 사이드바 경로, docs에서 잘 보이도록 render추가. 모달 공통 타입 d.ts파일로 변경. * feat: ModalAddingGoal 완성 * feat: ModalDeletingSubGoal 완성 * feat: 리액션 통째로 svg화 * feat: ModalCompletingGoal 완성 * feat: Checkbox 컴포넌트 디자인 변경 따른 수정 * feat: TodoItem 컴포넌트 디자인 변경 따른 수정 * feat: svg 수정에 따른 컴포넌트 svgr 적용 변경 * feat: api generator관련 mjs기반으로 수정 cjs, mjs둘다 사용되고 있어서 ts를 ts-node로 실행시키면 에러가 발생했습니다. * feat: FloatingButton 디자인 변경 따른 배경색 수정 * feat: GoalInfo 컴포넌트 복구 이전에 실수로 삭제했었던 것으로 보임. * feat: 린트 에러 수정 및 eslint-config-next재설치 os차이 때문인지 린트에서 에러나서 재설치 했습니다.
1 parent e9d8a9d commit 7a22827

36 files changed

+2265
-65
lines changed

api/generated/motimo/Api.ts

Lines changed: 1014 additions & 0 deletions
Large diffs are not rendered by default.

api/generator.ts renamed to api/generator.mjs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import { generateApi } from "swagger-typescript-api";
22
import path from "path";
33
import fs from "fs";
44

5-
const generate = async (domain: string, url: string) => {
5+
// .env 파일의 환경 변수를 로드.
6+
import "dotenv/config";
7+
8+
const generate = async (domain, url) => {
69
const PATH_TO_OUTPUT_DIR = path.resolve(
710
process.cwd(),
811
`./api/generated/${domain}`,
@@ -47,4 +50,5 @@ const generate = async (domain: string, url: string) => {
4750
});
4851
};
4952

50-
generate("example", "https://petstore.swagger.io/v2/swagger.json");
53+
// generate("example", "https://petstore.swagger.io/v2/swagger.json");
54+
generate("motimo", process.env.SWAGGER_URL);

app/_components/ModalRenderer.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"use client";
2+
3+
import useModalStore from "@/stores/useModalStore";
4+
import { useEffect, useState } from "react";
5+
import { createPortal } from "react-dom";
6+
7+
const ModalRenderer = () => {
8+
const OpenedModal = useModalStore((state) => state.Modal);
9+
const [mounted, setMounted] = useState(false);
10+
11+
// 클라이언트에서 createPoratl이 적용되도록..
12+
// document는 클라이언트에서만 잡히므로.
13+
useEffect(() => {
14+
setMounted(true);
15+
}, []);
16+
17+
return mounted && OpenedModal && createPortal(OpenedModal, document.body);
18+
};
19+
export default ModalRenderer;

app/layout.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Metadata } from "next";
22
// import { Geist, Geist_Mono } from "next/font/google";
33
import localFont from "next/font/local";
44
import "./globals.css";
5+
import ModalRenderer from "./_components/ModalRenderer";
56

67
const customFont = localFont({
78
src: "../public/fonts/SUIT-Variable.woff2",
@@ -30,7 +31,10 @@ export default function RootLayout({
3031
crossOrigin="anonymous" // 일반적으로 폰트에는 추가하는 것이 좋음
3132
/>
3233
</head>
33-
<body className={`${customFont.variable} antialiased`}>{children}</body>
34+
<body className={`${customFont.variable} antialiased`}>
35+
<ModalRenderer />
36+
{children}
37+
</body>
3438
</html>
3539
);
3640
}

components/shared/Banner/Banner.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ interface BannerProps {
66
const Banner = ({ title, tag }: BannerProps) => {
77
return (
88
<>
9-
<div className="w-96 px-6 py-4 bg-indigo-500 inline-flex justify-start items-center gap-3">
9+
<div className="w-full px-6 py-4 bg-indigo-500 inline-flex justify-start items-center gap-3">
1010
<div className="min-w-0 flex-1 inline-flex flex-col justify-center items-start gap-2">
1111
<p className="overflow-x-hidden self-stretch justify-center text-Color-white text-base font-bold font-['SUIT_Variable'] leading-tight">
1212
{title}

components/shared/Checkbox/Checkbox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const Checkbox = ({ ...props }: CheckboxProps) => {
1212
${`appearance-none w-4 h-4 relative bg-background-alternative rounded outline-[1.50px] outline-offset-[-1.50px] outline-Color-gray-20 overflow-hidden
1313
hover:outline-Color-gray-40
1414
checked:bg-center
15-
checked:bg-background-primary
15+
checked:bg-background-strong
1616
checked:outline-0
1717
checked:bg-[url("data:image/svg+xml,%3Csvg%20width%3D%2214%22%20height%3D%2214%22%20viewBox%3D%220%200%2014%2014%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M3.58325%207.27735L6.08343%209.77734L11.0833%204.77734%22%20stroke%3D%22white%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%3C%2Fsvg%3E")]
1818
checked:hover:bg-Color-primary-70

components/shared/FloatingButton/FloatingButton.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ const FloatingButton = ({ ...props }: FLoatingButtonProps) => {
1010
<>
1111
<button
1212
{...props}
13-
className="w-12 h-12 p-2 bg-indigo-500 rounded-[999px] shadow-[0px_2px_4px_0px_rgba(0,0,0,0.10)] inline-flex justify-center items-center gap-2"
13+
className="w-12 h-12 p-2 bg-background-strong rounded-[999px] shadow-[0px_2px_4px_0px_rgba(0,0,0,0.10)] inline-flex justify-center items-center gap-2"
1414
>
15-
<div className="w-6 h-6 relative overflow-hidden">
15+
<div className="w-6 h-6 relative overflow-hidden text-white">
1616
<PlusSvg width={24} height={24} />
1717
</div>
1818
</button>

components/shared/GoalInfo/GoalInfo.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const GoalInfo = ({ leftDateNum, leftTodoNum }: GoalInfoProps) => {
88
// 혹은 밖에서 무한 쿼리 첫 페이지의 메타 데이터 사용할 수도 있음
99
return (
1010
<>
11-
<div className="w-80 h-10 px-3 py-0.5 bg-background-alternative rounded-lg shadow-[0px_0px_4px_0px_rgba(0,0,0,0.10)] inline-flex justify-start items-center gap-4">
11+
<div className="w-full min-w-80 h-10 px-3 py-0.5 bg-background-alternative rounded-lg shadow-[0px_0px_4px_0px_rgba(0,0,0,0.10)] inline-flex justify-start items-center gap-4">
1212
<div className="flex justify-start items-center gap-0.5">
1313
<div className="w-5 h-5 relative overflow-hidden">
1414
<CalendarSvg />
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// plop-templates/story.tsx.hbs
2+
import type { Meta, StoryObj } from "@storybook/react";
3+
import ModalAddingGoal from "./ModalAddingGoal"; // 실제 컴포넌트 파일 임포트
4+
5+
const meta = {
6+
title: "Shared/Modals/ModalAddingGoal", // Storybook 사이드바 경로 (프로젝트 규칙에 맞게 수정)
7+
component: ModalAddingGoal,
8+
parameters: {
9+
// Canvas 레이아웃을 중앙으로 정렬하거나 패딩을 추가할 수 있습니다.
10+
layout: "centered",
11+
docs: {
12+
description: {
13+
component: "비동기 처리는 외부에 일임",
14+
},
15+
},
16+
},
17+
// Docs 탭 자동 생성을 위해 필요합니다.
18+
tags: ["autodocs"],
19+
// Controls Addon에서 Props를 어떻게 제어할지, 설명을 추가합니다.
20+
// 모든 스토리에 적용될 기본 Props (선택 사항)
21+
args: {
22+
// 예시: label: 'ModalAddingGoal',
23+
},
24+
// 모달 docs용 렌더 옵션 -- 이렇게 안하면 docs에선 쪼그라져 보임. w-full 때매.
25+
render: (args) => {
26+
return (
27+
<>
28+
<div style={{ minWidth: "320px", height: "300px" }}>
29+
<ModalAddingGoal {...args} />
30+
</div>
31+
</>
32+
);
33+
},
34+
} satisfies Meta<typeof ModalAddingGoal>;
35+
36+
export default meta;
37+
38+
type Story = StoryObj<typeof meta>;
39+
40+
// 가장 기본적인 Primary 스토리
41+
// argTypes를 Primary는 기본으로 가집니다.
42+
export const Primary: Story = {
43+
argTypes: {
44+
// 예시: backgroundColor: { control: 'color', description: '컴포넌트 배경색' },
45+
},
46+
args: {
47+
onAddGoal: async () => {
48+
console.log("스토리북 -- 비동기 처리");
49+
},
50+
onClose: () => {
51+
console.log("스토리북 -- close");
52+
},
53+
// Primary 스토리에만 적용될 Props
54+
},
55+
};
56+
57+
/*
58+
// UI variatns들을 스토리로 생성합니다.
59+
// 추가적인 스토리 예시:
60+
export const Secondary: Story = {
61+
args: {
62+
label: 'Secondary ModalAddingGoal',
63+
},
64+
};
65+
66+
export const Large: Story = {
67+
args: {
68+
size: 'large',
69+
label: 'Large ModalAddingGoal',
70+
},
71+
};
72+
*/
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
"use client";
2+
3+
import Modal from "../_compound/Modal";
4+
5+
interface ModalAddingGoalProps extends ModalCommon {
6+
onAddGoal: () => Promise<void>;
7+
}
8+
9+
const ModalAddingGoal = ({ onClose, onAddGoal }: ModalAddingGoalProps) => {
10+
return (
11+
<>
12+
<Modal
13+
backdropProps={{
14+
onClick: () => {
15+
onClose();
16+
},
17+
}}
18+
bodyNode={<Body />}
19+
footerNode={[
20+
<Modal.Button
21+
onClick={() => {
22+
onClose();
23+
}}
24+
key={"cancel"}
25+
text="취소"
26+
color="alternative"
27+
/>,
28+
<Modal.Button
29+
onClick={() => {
30+
// 비동기 동작 추후에 처리해야 함. 아직 미정이지만.. 수정할 부분임.
31+
onAddGoal();
32+
}}
33+
key={"add"}
34+
text="추가"
35+
color="primary"
36+
/>,
37+
]}
38+
/>
39+
</>
40+
);
41+
};
42+
export default ModalAddingGoal;
43+
44+
const Body = () => {
45+
return (
46+
<div className="flex justify-center items-center p-6">
47+
<div className="justify-start text-label-strong text-base font-bold font-['SUIT_Variable'] leading-tight">
48+
새로운 목표를 추가하시겠습니까?
49+
</div>
50+
</div>
51+
);
52+
};

0 commit comments

Comments
 (0)