diff --git a/app/page.tsx b/app/page.tsx
index 85d202e7..f3a20615 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,63 +1,7 @@
-import { BackwardButton } from "#/components/backwardButton";
-import { Layout } from "#/components/layout";
-import { StepHeader } from "#/components/stepHeader";
-import { colors } from "#/constants/color";
-
export default function Home() {
return (
-
-
-
-
- Header
-
-
- 스텝 헤더 제목
-
- 스텝 헤더 설명 문구가 여기에 들어갑니다.
-
-
-
-
-
-
- section 1
-
-
-
-
- section 2
-
-
-
-
- section 3
-
-
-
-
- section 4
-
-
-
- {/* color 변수 기반 예시 */}
-
-
- section 5 (colors 변수 사용)
-
-
-
-
-
- Footer
-
-
-
+
+
Hello World
+
);
}
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 05e726d1..d7c37821 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,18 +1,26 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";
+import prettier from "eslint-plugin-prettier";
+import prettierConfig from "eslint-config-prettier";
const eslintConfig = defineConfig([
- ...nextVitals,
- ...nextTs,
- // Override default ignores of eslint-config-next.
- globalIgnores([
- // Default ignores of eslint-config-next:
- ".next/**",
- "out/**",
- "build/**",
- "next-env.d.ts",
- ]),
+ ...nextVitals,
+ ...nextTs,
+ prettierConfig,
+ {
+ plugins: {
+ prettier,
+ },
+ },
+ // Override default ignores of eslint-config-next.
+ globalIgnores([
+ // Default ignores of eslint-config-next:
+ ".next/**",
+ "out/**",
+ "build/**",
+ "next-env.d.ts",
+ ]),
]);
export default eslintConfig;
diff --git a/package.json b/package.json
index eb6f909c..8e72017f 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,7 @@
"build": "next build",
"start": "next start",
"lint": "eslint",
- "format": "prettier --write \"src/**/*.{ts,tsx}\" --ignore-unknown",
+ "format": "prettier --write \"src/**/*.{ts,tsx}\" \"app/**/*.{ts,tsx}\" --ignore-unknown",
"generate:colors": "node scripts/colors/generate.js"
},
"dependencies": {
@@ -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": {
@@ -30,6 +31,8 @@
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "16.1.1",
+ "eslint-config-prettier": "^10.1.8",
+ "eslint-plugin-prettier": "^5.5.5",
"prettier": "^3.8.0",
"prettier-plugin-tailwindcss": "^0.7.2",
"tailwindcss": "^4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ef8e24e9..60865e79 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -38,6 +38,9 @@ importers:
react-hook-form:
specifier: ^7.71.0
version: 7.71.0(react@19.2.3)
+ sonner:
+ specifier: ^2.0.7
+ version: 2.0.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
tailwind-merge:
specifier: ^3.4.0
version: 3.4.0
@@ -60,6 +63,12 @@ importers:
eslint-config-next:
specifier: 16.1.1
version: 16.1.1(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ eslint-config-prettier:
+ specifier: ^10.1.8
+ version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ eslint-plugin-prettier:
+ specifier: ^5.5.5
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.0)
prettier:
specifier: ^3.8.0
version: 3.8.0
@@ -435,6 +444,10 @@ packages:
resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
engines: {node: '>=12.4.0'}
+ '@pkgr/core@0.2.9':
+ resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==}
+ engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+
'@radix-ui/react-compose-refs@1.1.2':
resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==}
peerDependencies:
@@ -999,6 +1012,12 @@ packages:
typescript:
optional: true
+ eslint-config-prettier@10.1.8:
+ resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==}
+ hasBin: true
+ peerDependencies:
+ eslint: '>=7.0.0'
+
eslint-import-resolver-node@0.3.9:
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
@@ -1052,6 +1071,20 @@ packages:
peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9
+ eslint-plugin-prettier@5.5.5:
+ resolution: {integrity: sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ '@types/eslint': '>=8.0.0'
+ eslint: '>=8.0.0'
+ eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0'
+ prettier: '>=3.0.0'
+ peerDependenciesMeta:
+ '@types/eslint':
+ optional: true
+ eslint-config-prettier:
+ optional: true
+
eslint-plugin-react-hooks@7.0.1:
resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==}
engines: {node: '>=18'}
@@ -1109,6 +1142,9 @@ packages:
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+ fast-diff@1.3.0:
+ resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
+
fast-glob@3.3.1:
resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
engines: {node: '>=8.6.0'}
@@ -1709,6 +1745,10 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
+ prettier-linter-helpers@1.0.1:
+ resolution: {integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==}
+ engines: {node: '>=6.0.0'}
+
prettier-plugin-tailwindcss@0.7.2:
resolution: {integrity: sha512-LkphyK3Fw+q2HdMOoiEHWf93fNtYJwfamoKPl7UwtjFQdei/iIBoX11G6j706FzN3ymX9mPVi97qIY8328vdnA==}
engines: {node: '>=20.19'}
@@ -1892,6 +1932,12 @@ packages:
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
engines: {node: '>= 0.4'}
+ sonner@2.0.7:
+ resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==}
+ peerDependencies:
+ react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
@@ -1955,6 +2001,10 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ synckit@0.11.12:
+ resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+
tailwind-merge@3.4.0:
resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==}
@@ -2421,6 +2471,8 @@ snapshots:
'@nolyfill/is-core-module@1.0.39': {}
+ '@pkgr/core@0.2.9': {}
+
'@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.8)(react@19.2.3)':
dependencies:
react: 19.2.3
@@ -3056,6 +3108,10 @@ snapshots:
- eslint-plugin-import-x
- supports-color
+ eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)):
+ dependencies:
+ eslint: 9.39.2(jiti@2.6.1)
+
eslint-import-resolver-node@0.3.9:
dependencies:
debug: 3.2.7
@@ -3138,6 +3194,15 @@ snapshots:
safe-regex-test: 1.1.0
string.prototype.includes: 2.0.1
+ eslint-plugin-prettier@5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.0):
+ dependencies:
+ eslint: 9.39.2(jiti@2.6.1)
+ prettier: 3.8.0
+ prettier-linter-helpers: 1.0.1
+ synckit: 0.11.12
+ optionalDependencies:
+ eslint-config-prettier: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+
eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@2.6.1)):
dependencies:
'@babel/core': 7.28.6
@@ -3241,6 +3306,8 @@ snapshots:
fast-deep-equal@3.1.3: {}
+ fast-diff@1.3.0: {}
+
fast-glob@3.3.1:
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -3807,6 +3874,10 @@ snapshots:
prelude-ls@1.2.1: {}
+ prettier-linter-helpers@1.0.1:
+ dependencies:
+ fast-diff: 1.3.0
+
prettier-plugin-tailwindcss@0.7.2(prettier@3.8.0):
dependencies:
prettier: 3.8.0
@@ -3991,6 +4062,11 @@ snapshots:
side-channel-map: 1.0.1
side-channel-weakmap: 1.0.2
+ sonner@2.0.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+
source-map-js@1.2.1: {}
stable-hash@0.0.5: {}
@@ -4067,6 +4143,10 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
+ synckit@0.11.12:
+ dependencies:
+ '@pkgr/core': 0.2.9
+
tailwind-merge@3.4.0: {}
tailwindcss@4.1.18: {}
diff --git a/src/components/toast/Toaster.tsx b/src/components/toast/Toaster.tsx
new file mode 100644
index 00000000..2a1b3ec7
--- /dev/null
+++ b/src/components/toast/Toaster.tsx
@@ -0,0 +1,28 @@
+"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 (
+
+ );
+};
diff --git a/src/components/toast/index.ts b/src/components/toast/index.ts
new file mode 100644
index 00000000..59ad5ca2
--- /dev/null
+++ b/src/components/toast/index.ts
@@ -0,0 +1 @@
+export { Toaster, type ToasterProps } from "./Toaster";
diff --git a/src/icons/alertCircleIcon/AlertCircleIcon.tsx b/src/icons/alertCircleIcon/AlertCircleIcon.tsx
new file mode 100644
index 00000000..d326ee12
--- /dev/null
+++ b/src/icons/alertCircleIcon/AlertCircleIcon.tsx
@@ -0,0 +1,24 @@
+import { IconBase, type IconBaseProps } from "../iconBase";
+
+export type AlertCircleIconProps = Omit;
+
+export const AlertCircleIcon = ({
+ size = 20,
+ ...props
+}: AlertCircleIconProps) => {
+ return (
+
+
+
+
+
+ );
+};
diff --git a/src/icons/alertCircleIcon/index.ts b/src/icons/alertCircleIcon/index.ts
new file mode 100644
index 00000000..672b3907
--- /dev/null
+++ b/src/icons/alertCircleIcon/index.ts
@@ -0,0 +1 @@
+export { AlertCircleIcon, type AlertCircleIconProps } from "./AlertCircleIcon";
diff --git a/src/utils/toast.ts b/src/utils/toast.ts
new file mode 100644
index 00000000..317f8456
--- /dev/null
+++ b/src/utils/toast.ts
@@ -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!",
+ },
+ duration: options?.duration,
+ });
+ },
+};