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, + }); + }, +};