Skip to content
Open
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"react-router-dom": "^7.11.0",
"react-spinners": "^0.17.0",
"swiper": "^12.0.3",
"tailwind-merge": "^3.5.0",
"tailwindcss": "^4.1.18",
"zod": "^4.2.1",
"zustand": "^5.0.10"
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 38 additions & 16 deletions src/components/common/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,52 @@
import Pencil from "../../assets/icons/pencil-primary-500.svg";
import type { ReactElement } from "react";
import { twMerge } from "tailwind-merge";

interface ButtonProps {
onClick?: () => void;
text: string;
type: "button" | "submit" | "reset";
interface ButtonType {
children: ReactElement | string;
size: "Btn_L" | "Btn_M" | "Btn_S";
variant: "primary" | "gray" | "transparent";
disabled?: boolean;
bgColor?: "primary" | "white";
onClick?: () => void;
type?: "button" | "submit" | "reset";
className: string;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이부분을 매튜님이 예시 보여주셨던 것 처럼
interface ButtonProp extends React.HTMLAttributes<HTMLButtonElement>
이런식으로 선언해보는 건 어떨까 싶습니다. disabled, onClick, type 등이 props로 존재하는 걸로 압니다! 한번 적용해보면 좋을 것 같아요!

참고할만한 블로그 첨부합니다
https://velog.io/@dongkyun/TS-HTMLElement의-type-상속받기

Comment on lines +4 to 8

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

sizevariant가 필수 속성으로 선언되어 있지만 기본값이 존재합니다.

인터페이스에서 sizevariant가 필수(? 없음)로 선언되어 있으나, 컴포넌트 내부에서 기본값("Btn_M", "primary")을 제공하고 있습니다. 이로 인해 TypeScript에서 props 전달 시 항상 명시해야 하는 것으로 인식됩니다.

🛠️ 제안 수정안
 interface ButtonType extends ButtonHTMLAttributes<HTMLButtonElement> {
   children: ReactNode;
-  size: "Btn_L" | "Btn_M" | "Btn_S";
-  variant: "primary" | "gray" | "transparent";
+  size?: "Btn_L" | "Btn_M" | "Btn_S";
+  variant?: "primary" | "gray" | "transparent";
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/common/Button.tsx` around lines 4 - 8, The ButtonType
interface declares size and variant as required even though the Button component
provides defaults ("Btn_M" and "primary"); update the ButtonType definition to
make size and variant optional (add ?), leaving the component's defaulting logic
in the Button component intact so callers need not always pass those props;
reference ButtonType and the Button component to locate the change.


export default function Button({
const SIZES = {
Btn_L: "px-[10px] py-[16px]",
Btn_S: "px-[24px] py-[6px]",
Btn_M: "px-[10px] py-[16px]", // padding을 className에 직접 지정 가능
};
const VARIANTS = {
primary: "bg-primary-700 text-white",
gray: "bg-gray-100",
transparent: "bg-transparent border-1 border-primary-700",
};

const Button = ({
children = "",
size = "Btn_M",
Comment thread
jangmk05 marked this conversation as resolved.
Outdated
variant = "primary",
disabled = false,
onClick,
text,
type,
disabled,
bgColor = "primary",
}: ButtonProps) {
className,
}: ButtonType) => {
const sizeClass = SIZES[size];
const variantClass = VARIANTS[variant];
const disabledClass = disabled && "opacity-50 cursor-not-allowed";

return (
<button
className={`w-[343px] px-[10px] py-[16px] flex items-center justify-center gap-[10px] rounded-xl font-semibold text-[20px] leading-[22px] text-center cursor-pointer
${bgColor == "primary" ? "bg-primary-700 text-white" : "bg-white text-primary-500 border border-primary-500"}`}
onClick={onClick}
type={type}
disabled={disabled}
className={twMerge(
`rounded-xl flex justify-center items-center ${sizeClass} ${variantClass} ${disabledClass} ${className}`,
)}
>
{bgColor === "white" && <img src={Pencil} />}
{text}
{children}
</button>
);
}
};

export default Button;
18 changes: 9 additions & 9 deletions src/components/meal-plan/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -215,16 +215,16 @@ export default function BottomSheet({

<div className="fixed bottom-0 left-1/2 -translate-x-1/2 flex justify-center pb-10">
<Button
text={isOpen ? "바꾸기" : "수정완료"}
size="Btn_L"
variant="primary"
type="button"
onClick={() => {
if (isOpen) {
handleChange();
} else {
setIsModalOpen(true);
}
}}
/>
className="w-[343px]"
onClick={handleChange}
>
<span className="text-xl font-semibold leading-[22px]">
{isOpen ? "바꾸기" : "수정완료"}
</span>
</Button>
Comment thread
jangmk05 marked this conversation as resolved.
Outdated
</div>
</div>
);
Expand Down
8 changes: 6 additions & 2 deletions src/components/meal-plan/ReviewModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,10 @@ export default function ReviewModal({
</div>
<div className="w-full p-[10px] flex justify-center">
<Button
size="Btn_L"
variant="primary"
type="button"
text="등록"
className="w-[343px]"
onClick={() => {
const reviewData: createReview = {
recipeId,
Expand All @@ -125,7 +127,9 @@ export default function ReviewModal({
}
handleSubmitReview(reviewData);
}}
/>
>
<span className="text-xl font-semibold leading-[22px]">등록</span>
</Button>
</div>
</div>
</div>
Expand Down
23 changes: 9 additions & 14 deletions src/components/meal-plan/TodayMeal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,15 @@ export default function TodayMeal({ data }: { data: TodayMeal }) {
</div>
{!data.isReviewed && (
<div className="pt-6">
{!isDone ? (
<Button
type="button"
text="식사 완료"
onClick={() => setIsDone(true)}
/>
) : (
<Button
type="button"
text="리뷰 작성"
bgColor="white"
onClick={() => setIsOpen(true)}
/>
)}
<Button
onClick={isDone ? () => setIsOpen(true) : () => setIsDone(true)}
size="Btn_L"
variant="primary"
type="button"
className="w-[343px]"
>
{isDone ? "리뷰 작성" : "식사 완료"}
</Button>
</div>
)}
<div className="pt-11 pb-29">
Expand Down
22 changes: 20 additions & 2 deletions src/components/mypage/GetDateRangeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,15 @@ export default function GetDateRangeModal({
<DateBlock date={to} />
</div>
<div className="pt-[25px]">
<Button text={"적용"} type="button" onClick={handleFinalApply} />
<Button
size="Btn_L"
variant="primary"
type="button"
className="w-[343px]"
onClick={handleFinalApply}
>
<span className="text-xl font-semibold leading-[22px]">적용</span>
</Button>
</div>
</div>
</div>
Expand All @@ -163,7 +171,17 @@ export default function GetDateRangeModal({
onSelect={handleSelect}
/>
<div className="pt-4">
<Button text="선택" type="button" onClick={handleApplyDate} />
<Button
size="Btn_L"
variant="primary"
type="button"
className="w-[343px]"
onClick={handleApplyDate}
>
<span className="text-xl font-semibold leading-[22px]">
선택
</span>
</Button>
</div>
</div>
</div>
Expand Down
12 changes: 7 additions & 5 deletions src/components/onboarding/ThirdStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ export default function ThirdStep() {
</div>
<div className="pt-[50px] pb-8 flex justify-center">
<Button
text={"시작"}
size="Btn_L"
variant="primary"
onClick={() => navigate("/agreement")}
type="button"
onClick={() => {
navigate("../agreement");
}}
/>
className="w-full"
>
<span className="text-xl font-semibold leading-[22px]">시작</span>
</Button>
</div>
</div>
</>
Expand Down
10 changes: 8 additions & 2 deletions src/components/profile/ProfileDataForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,16 @@ export default function ProfileDataForm({

<div className="pt-[5px] pb-10">
<Button
text={profileMutation.isPending ? "처리 중..." : "완료"}
size="Btn_L"
variant="primary"
type="submit"
className="w-[343px]"
disabled={profileMutation.isPending}
/>
>
<span className="text-xl font-semibold leading-[22px]">
{profileMutation.isPending ? "처리 중..." : "완료"}
</span>
</Button>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
</div>
</form>
);
Expand Down
12 changes: 8 additions & 4 deletions src/pages/auth/terms-agreement-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,17 @@ export default function TermsAgreementPage() {
/>
</div>
</div>
<div className="fixed bottom-0 left-1/2 -translate-x-1/2 flex justify-center pb-10">
<div className="flex justify-center pt-[159px]">
<Button
text={`다음`}
size="Btn_L"
variant="primary"
onClick={handleSubmit}
type="button"
className="w-[343px]"
disabled={!isValid || isAgreeing}
onClick={handleSubmit}
/>
>
<span className="text-xl font-semibold leading-[22px]">다음</span>
</Button>
</div>
</div>
);
Expand Down
10 changes: 9 additions & 1 deletion src/pages/family/allergies-search-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,15 @@ export default function AllergiesSearchPage() {
</div>
</div>
<div className="pt-[420px]">
<Button text={"완료"} type="submit" onClick={handleComplete} />
<Button
size="Btn_L"
variant="primary"
onClick={handleComplete}
type="button"
className="w-[343px]"
>
<span className="text-xl font-semibold leading-[22px]">완료</span>
</Button>
</div>
</div>
</div>
Expand Down
10 changes: 7 additions & 3 deletions src/pages/family/family-create-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,15 @@ export default function FamilyCreatePage() {
</div>
<div className="fixed bottom-0 left-1/2 -translate-x-1/2 pb-10">
<Button
text="다음"
type="submit"
size="Btn_L"
variant="primary"
onClick={handleSubmit}
type="submit"
className="w-[343px]"
disabled={isCreating}
/>
>
<span className="text-xl font-semibold leading-[22px]">다음</span>
</Button>
</div>
</div>
</div>
Expand Down
10 changes: 7 additions & 3 deletions src/pages/family/family-invite-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,17 @@ export default function FamilyInvitePage() {
</div>
<div className="pt-[156px]">
<Button
text="다음"
type="submit"
size="Btn_L"
variant="primary"
onClick={() => {
navigate("/");
}}
type="button"
className="w-[343px]"
disabled={isInviting}
/>
>
<span className="text-xl font-semibold leading-[22px]">다음</span>
</Button>
</div>
</div>
</div>
Expand Down
10 changes: 8 additions & 2 deletions src/pages/meal-plan/meal-plan-create-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,16 @@ const MealPlanCreatePage = () => {
</div>
<div className="fixed bottom-0 left-1/2 -translate-x-1/2 flex justify-center pb-10">
<Button
text="식단 생성"
size="Btn_L"
variant="primary"
type="button"
className="w-[343px]"
onClick={() => handleCreate()}
/>
>
<span className="text-xl font-semibold leading-[22px]">
식단 생성
</span>
</Button>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
</div>
</div>
</>
Expand Down