Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions app/_test/ToastTest.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"use client";

import { Button } from "#/components/button";
import { toast } from "#/utils/toast";

export const ToastTest = () => {
return (
<Button
onClick={() =>
toast.warning("이미 선택되었어요. 다른 메뉴를 골라주세요!")
}
>
Toast 테스트
</Button>
);
};
1 change: 1 addition & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Metadata, Viewport } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import { Toaster } from "#/components/toast";

Check warning on line 4 in app/layout.tsx

View workflow job for this annotation

GitHub Actions / ESLint

'Toaster' is defined but never used

Check warning on line 4 in app/layout.tsx

View workflow job for this annotation

GitHub Actions / ESLint

'Toaster' is defined but never used

const geistSans = Geist({
variable: "--font-geist-sans",
Expand Down
5 changes: 3 additions & 2 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { BackwardButton } from "#/components/backwardButton";
import { Layout } from "#/components/layout";
import { StepHeader } from "#/components/stepHeader";
import { colors } from "#/constants/color";
import { ToastTest } from "./_test/ToastTest";
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.

medium

ToastTest 컴포넌트는 테스트 목적으로 보이며, app/page.tsx에 직접 import 되어 있습니다. 프로덕션 코드에 테스트용 코드가 포함되는 것은 불필요한 코드와 잠재적인 부작용을 일으킬 수 있으므로, 프로덕션 병합 전에 이 import 문을 제거하는 것이 좋습니다. 개발 환경에서만 필요한 경우, 환경 변수를 사용하여 조건부로 import 하거나 별도의 테스트 페이지에서만 사용하도록 분리하는 것을 고려해볼 수 있습니다.


export default function Home() {
return (
Expand Down Expand Up @@ -54,8 +55,8 @@ export default function Home() {
</div>
</Layout.Content>
<Layout.Footer>
<div className="ygi:flex ygi:h-layout-footer-height ygi:w-full ygi:items-center ygi:justify-center ygi:bg-surface-gray">
Footer
<div className="ygi:flex ygi:h-layout-footer-height ygi:w-full ygi:items-center ygi:justify-center ygi:gap-md ygi:bg-surface-gray">
<ToastTest />
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.

medium

ToastTest 컴포넌트가 Layout.Footer 내부에 직접 렌더링되고 있습니다. 이 컴포넌트는 테스트 목적으로 보이므로, 프로덕션 빌드에는 포함되지 않도록 제거해야 합니다. 만약 개발 중에만 필요하다면, process.env.NODE_ENV === 'development'와 같은 환경 변수 체크를 통해 조건부로 렌더링하는 것을 고려해볼 수 있습니다.

</div>
</Layout.Footer>
</Layout.Root>
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"react": "19.2.3",
"react-dom": "19.2.3",
"react-hook-form": "^7.71.0",
"sonner": "^2.0.7",
"tailwind-merge": "^3.4.0"
},
"devDependencies": {
Expand Down
14 changes: 14 additions & 0 deletions pnpm-lock.yaml

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

23 changes: 23 additions & 0 deletions src/components/toast/Toaster.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"use client";

import {
Toaster as SonnerToaster,
type ToasterProps as SonnerToasterProps,
} from "sonner";

export type ToasterProps = Pick<
SonnerToasterProps,
"offset" | "mobileOffset" | "gap" | "toastOptions"
>;

export const Toaster = ({ offset, mobileOffset, gap, toastOptions = { duration: 3000 } }: ToasterProps) => {
return (
<SonnerToaster
position="bottom-center"
offset={offset}
mobileOffset={mobileOffset}
gap={gap}
toastOptions={toastOptions}
/>
);
};
1 change: 1 addition & 0 deletions src/components/toast/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Toaster, type ToasterProps } from "./Toaster";
24 changes: 24 additions & 0 deletions src/icons/alertCircleIcon/AlertCircleIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { IconBase, type IconBaseProps } from "../iconBase";

export type AlertCircleIconProps = Omit<IconBaseProps, "children">;

export const AlertCircleIcon = ({
size = 20,
...props
}: AlertCircleIconProps) => {
return (
<IconBase size={size} viewBox="-1 -1 20 20" {...props}>
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.

medium

viewBox 속성이 "-1 -1 20 20"으로 설정되어 있습니다. SVG 아이콘의 viewBox가 음수 좌표로 시작하는 것은 일반적이지 않으며, 아이콘이 스케일되거나 다른 컨텍스트에서 사용될 때 예상치 못한 렌더링 또는 클리핑 문제를 일으킬 수 있습니다. 아이콘의 실제 내용이 18x18 그리드 내에 있다고 가정할 때, viewBox="0 0 18 18"과 같이 0,0에서 시작하는 표준 viewBox를 사용하는 것이 더 견고하고 예측 가능합니다.

Suggested change
<IconBase size={size} viewBox="-1 -1 20 20" {...props}>
<IconBase size={size} viewBox="0 0 18 18" {...props}>

<path
d="M0 9C0 4.02944 4.02944 0 9 0C13.9706 0 18 4.02944 18 9C18 13.9706 13.9706 18 9 18C4.02944 18 0 13.9706 0 9Z"
fill="currentColor"
/>
<path
d="M9 5V9"
stroke="#E5E7EB"
strokeWidth="2"
strokeLinecap="round"
/>
<circle cx="9" cy="13" r="1.5" fill="#E5E7EB" />
Comment on lines +17 to +21
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.

medium

아이콘 내부 요소(path의 stroke와 circle의 fill)에 #E5E7EB와 같은 하드코딩된 색상 값이 사용되었습니다. 이는 디자인 시스템의 색상 토큰을 우회하여 테마 관리 및 일관성 유지에 어려움을 줄 수 있습니다. IconBase 컴포넌트의 color prop을 활용하여 currentColor를 사용하면 아이콘의 색상을 외부에서 유연하게 제어할 수 있습니다. toast.ts에서 ygi:text-palette-primary-500 클래스를 통해 아이콘 색상을 동적으로 설정하고 있으므로, 내부 요소도 currentColor를 따르도록 변경하는 것이 좋습니다.

Suggested change
stroke="#E5E7EB"
strokeWidth="2"
strokeLinecap="round"
/>
<circle cx="9" cy="13" r="1.5" fill="#E5E7EB" />
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
/>
<circle cx="9" cy="13" r="1.5" fill="currentColor" />

</IconBase>
);
};
1 change: 1 addition & 0 deletions src/icons/alertCircleIcon/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { AlertCircleIcon, type AlertCircleIconProps } from "./AlertCircleIcon";
22 changes: 22 additions & 0 deletions src/utils/toast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { toast as sonnerToast } from "sonner";
import { AlertCircleIcon } from "#/icons/alertCircleIcon";

interface ToastOptions {
duration?: number;
className?: string;
}

export const toast = {
warning: (message: string, options?: ToastOptions) => {
sonnerToast(message, {
icon: AlertCircleIcon({
size: 20,
className: "ygi:text-palette-primary-500 ygi:mx-auto!",
}),
classNames: {
toast: "ygi:bg-button-primary! ygi:text-text-inverse! ygi:body-14-md! ygi:rounded-sm! ygi:py-3! ygi:pl-4! ygi:pr-5! ygi:gap-2! ygi:flex! ygi:items-center! ygi:border-none!",
Comment on lines +16 to +17
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.

medium

classNames.toast 속성에 Tailwind 클래스 문자열이 길게 하드코딩되어 있습니다. 이 방식은 토스트의 스타일을 동적으로 변경하거나(예: 성공, 오류 등 다양한 토스트 유형에 따라) 디자인 시스템 내에서 효과적으로 관리하기 어렵게 만듭니다. Button 컴포넌트에서 사용된 cva (class-variance-authority)와 같은 유틸리티를 사용하여 스타일을 정의하고 적용하면, 다양한 변형을 지원하고 재사용성을 높여 더 구조적이고 유지보수하기 쉬운 코드를 만들 수 있습니다. 현재는 warning 타입만 있지만, 향후 success, error 등 다른 타입의 토스트가 추가될 경우 cva를 활용하는 것이 훨씬 효율적입니다.

},
duration: options?.duration,
});
},
};
Loading