diff --git a/apps/timo-web/app/fonts/PretendardVariable.woff2 b/apps/timo-web/app/fonts/PretendardVariable.woff2 new file mode 100644 index 00000000..49c54b51 Binary files /dev/null and b/apps/timo-web/app/fonts/PretendardVariable.woff2 differ diff --git a/apps/timo-web/app/globals.css b/apps/timo-web/app/globals.css index 296d977e..73d2a0de 100644 --- a/apps/timo-web/app/globals.css +++ b/apps/timo-web/app/globals.css @@ -1,2 +1,3 @@ @import "tailwindcss"; @import "@repo/tailwind-config/theme.css"; +@import "@repo/timo-design-system/styles"; diff --git a/apps/timo-web/app/layout.tsx b/apps/timo-web/app/layout.tsx index 6ec5f29e..a3ea990f 100644 --- a/apps/timo-web/app/layout.tsx +++ b/apps/timo-web/app/layout.tsx @@ -1,8 +1,17 @@ import "./globals.css"; +import localFont from "next/font/local"; + import type { Metadata } from "next"; import { QueryProvider } from "@/providers/QueryProvider"; +const pretendard = localFont({ + src: "./fonts/PretendardVariable.woff2", + variable: "--font-family-pretendard", + weight: "45 920", + display: "swap", +}); + export const metadata: Metadata = { title: "Timo", description: "Timo web", @@ -14,7 +23,7 @@ interface RootLayoutProps { export default function RootLayout({ children }: Readonly) { return ( - + {children} diff --git a/packages/tailwind-config/theme.css b/packages/tailwind-config/theme.css index 4a2eeeba..528ad949 100644 --- a/packages/tailwind-config/theme.css +++ b/packages/tailwind-config/theme.css @@ -1,5 +1,3 @@ -@theme { - --color-primary: #111111; - --color-background: #ffffff; - --color-foreground: #171717; -} +@import "./tokens/colors.css"; +@import "./tokens/typography.css"; +@import "./tokens/radius.css"; \ No newline at end of file diff --git a/packages/tailwind-config/tokens/colors.css b/packages/tailwind-config/tokens/colors.css new file mode 100644 index 00000000..1deec929 --- /dev/null +++ b/packages/tailwind-config/tokens/colors.css @@ -0,0 +1,21 @@ +@theme { + --color-timo-blue-50: #F1F6FE; + --color-timo-blue-75: #C6D8FC; + --color-timo-blue-100: #AEC8FB; + --color-timo-blue-200: #8CB0F9; + --color-timo-blue-300: #74A0F8; + + --color-timo-gray-300: #F5F5F5; + --color-timo-gray-500: #E6E8E8; + --color-timo-gray-600: #D8D8D8; + --color-timo-gray-700: #9F9F9F; + --color-timo-gray-800: #757575; + --color-timo-gray-900: #3F3F3F; + + --color-timo-yellow-300: #F2FC9F; + + --color-timo-black: #121212; + --color-timo-red: #FF6650; + --color-timo-orange: #FFB157; + --color-timo-green: #9FDDA9; +} \ No newline at end of file diff --git a/packages/tailwind-config/tokens/radius.css b/packages/tailwind-config/tokens/radius.css new file mode 100644 index 00000000..d4d9e85f --- /dev/null +++ b/packages/tailwind-config/tokens/radius.css @@ -0,0 +1,5 @@ +@theme { + --radius-4: 4px; + --radius-8: 8px; + --radius-12: 12px; +} diff --git a/packages/tailwind-config/tokens/typography.css b/packages/tailwind-config/tokens/typography.css new file mode 100644 index 00000000..83e5b15e --- /dev/null +++ b/packages/tailwind-config/tokens/typography.css @@ -0,0 +1,93 @@ +@theme { + --font-pretendard: var(--font-family-pretendard), sans-serif; + + /* Headline */ + --typo-size-headline-b-30: 30px; + --typo-line-height-headline-b-30: 1.5; + --typo-letter-spacing-headline-b-30: -0.03em; + --typo-font-weight-headline-b-30: 700; + + --typo-size-headline-b-24: 24px; + --typo-line-height-headline-b-24: 1.5; + --typo-letter-spacing-headline-b-24: -0.03em; + --typo-font-weight-headline-b-24: 700; + + --typo-size-headline-b-22: 22px; + --typo-line-height-headline-b-22: 1.5; + --typo-letter-spacing-headline-b-22: -0.03em; + --typo-font-weight-headline-b-22: 700; + + --typo-size-headline-b-20: 20px; + --typo-line-height-headline-b-20: 1.5; + --typo-letter-spacing-headline-b-20: -0.03em; + --typo-font-weight-headline-b-20: 700; + + --typo-size-headline-b-18: 18px; + --typo-line-height-headline-b-18: 1.5; + --typo-letter-spacing-headline-b-18: -0.03em; + --typo-font-weight-headline-b-18: 700; + + --typo-size-headline-b-16: 16px; + --typo-line-height-headline-b-16: 1.5; + --typo-letter-spacing-headline-b-16: -0.03em; + --typo-font-weight-headline-b-16: 700; + + --typo-size-headline-m-16: 16px; + --typo-line-height-headline-m-16: 1.5; + --typo-letter-spacing-headline-m-16: -0.03em; + --typo-font-weight-headline-m-16: 500; + + --typo-size-headline-b-14: 14px; + --typo-line-height-headline-b-14: 1.5; + --typo-letter-spacing-headline-b-14: -0.03em; + --typo-font-weight-headline-b-14: 700; + + --typo-size-headline-m-14: 14px; + --typo-line-height-headline-m-14: 1.5; + --typo-letter-spacing-headline-m-14: -0.03em; + --typo-font-weight-headline-m-14: 500; + + --typo-size-headline-r-14: 14px; + --typo-line-height-headline-r-14: 1.5; + --typo-letter-spacing-headline-r-14: -0.03em; + --typo-font-weight-headline-r-14: 400; + + /* Body */ + --typo-size-body-b-12: 12px; + --typo-line-height-body-b-12: 1.5; + --typo-letter-spacing-body-b-12: -0.03em; + --typo-font-weight-body-b-12: 700; + + --typo-size-body-sb-12: 12px; + --typo-line-height-body-sb-12: 1.5; + --typo-letter-spacing-body-sb-12: -0.03em; + --typo-font-weight-body-sb-12: 600; + + --typo-size-body-m-12: 12px; + --typo-line-height-body-m-12: 1.5; + --typo-letter-spacing-body-m-12: -0.03em; + --typo-font-weight-body-m-12: 500; + + --typo-size-body-r-12: 12px; + --typo-line-height-body-r-12: 1.5; + --typo-letter-spacing-body-r-12: -0.03em; + --typo-font-weight-body-r-12: 400; + + --typo-size-body-sb-11: 11px; + --typo-line-height-body-sb-11: 1.5; + --typo-letter-spacing-body-sb-11: -0.03em; + --typo-font-weight-body-sb-11: 600; + + /* Caption */ + --typo-size-caption-r-10: 10px; + --typo-line-height-caption-r-10: 1.5; + --typo-letter-spacing-caption-r-10: -0.03em; + --typo-font-weight-caption-r-10: 400; +} + +@utility typo-* { + font-size: --value(--typo-size-*); + line-height: --value(--typo-line-height-*); + letter-spacing: --value(--typo-letter-spacing-*); + font-weight: --value(--typo-font-weight-*); +} \ No newline at end of file diff --git a/packages/timo-design-system/.storybook/preview.ts b/packages/timo-design-system/.storybook/preview.ts index 4313c5d2..10bd36ee 100644 --- a/packages/timo-design-system/.storybook/preview.ts +++ b/packages/timo-design-system/.storybook/preview.ts @@ -1,3 +1,4 @@ +import "../src/styles/globals.css"; import type { Preview } from "@storybook/react-vite"; const preview: Preview = { diff --git a/packages/timo-design-system/eslint.config.mjs b/packages/timo-design-system/eslint.config.mjs index 19170f88..e6b0b4cd 100644 --- a/packages/timo-design-system/eslint.config.mjs +++ b/packages/timo-design-system/eslint.config.mjs @@ -1,4 +1,9 @@ import { config } from "@repo/eslint-config/react-internal"; /** @type {import("eslint").Linter.Config} */ -export default config; +export default [ + { + ignores: ["storybook-static/**"], + }, + ...config, +]; diff --git a/packages/timo-design-system/package.json b/packages/timo-design-system/package.json index 95839115..092c37b2 100644 --- a/packages/timo-design-system/package.json +++ b/packages/timo-design-system/package.json @@ -5,7 +5,8 @@ "exports": { "./ui": "./src/components/index.ts", "./icons": "./src/icons/index.ts", - "./utils": "./src/lib/index.ts" + "./utils": "./src/lib/index.ts", + "./styles": "./src/styles/components.css" }, "scripts": { "lint": "eslint . --max-warnings 0", @@ -17,6 +18,7 @@ }, "devDependencies": { "@repo/eslint-config": "workspace:*", + "@repo/tailwind-config": "workspace:*", "@repo/typescript-config": "workspace:*", "@storybook/addon-a11y": "^8.6.14", "@storybook/addon-docs": "8.6.14", @@ -25,12 +27,14 @@ "@storybook/addon-links": "^8.6.14", "@storybook/react": "8.6.14", "@storybook/react-vite": "^8.6.14", + "@tailwindcss/postcss": "^4.3.1", "@types/node": "^22.15.3", "@types/react": "19.2.2", "@types/react-dom": "19.2.2", "chromatic": "^17.7.2", "eslint": "^9.39.1", "storybook": "^8.6.14", + "tailwindcss": "^4.3.1", "typescript": "5.9.2" }, "dependencies": { diff --git a/packages/timo-design-system/postcss.config.mjs b/packages/timo-design-system/postcss.config.mjs new file mode 100644 index 00000000..61e36849 --- /dev/null +++ b/packages/timo-design-system/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; + +export default config; diff --git a/packages/timo-design-system/src/assets/fonts/PretendardVariable.woff2 b/packages/timo-design-system/src/assets/fonts/PretendardVariable.woff2 new file mode 100644 index 00000000..49c54b51 Binary files /dev/null and b/packages/timo-design-system/src/assets/fonts/PretendardVariable.woff2 differ diff --git a/packages/timo-design-system/src/components/color/Color.stories.tsx b/packages/timo-design-system/src/components/color/Color.stories.tsx index ef2ac235..5065cb3f 100644 --- a/packages/timo-design-system/src/components/color/Color.stories.tsx +++ b/packages/timo-design-system/src/components/color/Color.stories.tsx @@ -1,6 +1,5 @@ - import { Color } from "./Color"; -import { COLOR_TOKENS } from "../../tokens/colort-token"; +import { COLOR_TOKENS } from "../../tokens/color-token"; import type { Meta, StoryObj } from "@storybook/react"; @@ -17,10 +16,10 @@ type Story = StoryObj; export const All: Story = { name: "All Colors", render: () => ( -
-

- ⚠️ 피그마 MCP 연동 후 실제 값으로 업데이트 예정입니다. -

+
+

{COLOR_TOKENS.map((token) => ( ))} diff --git a/packages/timo-design-system/src/components/color/Color.tsx b/packages/timo-design-system/src/components/color/Color.tsx index 9f771d92..0f00b157 100644 --- a/packages/timo-design-system/src/components/color/Color.tsx +++ b/packages/timo-design-system/src/components/color/Color.tsx @@ -1,6 +1,6 @@ -import { ColorToken } from "../../tokens/colort-token"; +import { ColorToken } from "../../tokens/color-token"; -export const Color = ({ name, cssVar, value, usage }: ColorToken) => { +export const Color = ({ name, cssVar, value }: ColorToken) => { return (

{ > {value}
-
- {usage} -
); diff --git a/packages/timo-design-system/src/components/index.ts b/packages/timo-design-system/src/components/index.ts index cb0ff5c3..ef907737 100644 --- a/packages/timo-design-system/src/components/index.ts +++ b/packages/timo-design-system/src/components/index.ts @@ -1 +1,2 @@ -export {}; +export { Color } from "./color/Color"; +export { Typography } from "./typography/Typography"; diff --git a/packages/timo-design-system/src/components/typography/Typography.stories.tsx b/packages/timo-design-system/src/components/typography/Typography.stories.tsx index 87b3d1c2..9b81fef5 100644 --- a/packages/timo-design-system/src/components/typography/Typography.stories.tsx +++ b/packages/timo-design-system/src/components/typography/Typography.stories.tsx @@ -1,4 +1,3 @@ - import { Typography } from "./Typography"; import { TYPOGRAPHY_TOKENS } from "../../tokens/typography-token"; @@ -16,10 +15,10 @@ type Story = StoryObj; export const Scale: Story = { render: () => ( -
-

- ⚠️ 피그마 MCP 연동 후 실제 값으로 업데이트 예정입니다. -

+
+

{TYPOGRAPHY_TOKENS.map((row) => ( ))} diff --git a/packages/timo-design-system/src/components/typography/Typography.tsx b/packages/timo-design-system/src/components/typography/Typography.tsx index f39ea7ec..d4c42514 100644 --- a/packages/timo-design-system/src/components/typography/Typography.tsx +++ b/packages/timo-design-system/src/components/typography/Typography.tsx @@ -1,6 +1,12 @@ import { TypographyToken } from "../../tokens/typography-token"; -export const Typography = ({ token, size, weight, usage }: TypographyToken) => { +export const Typography = ({ + token, + size, + weight, + lineHeight, + letterSpacing, +}: TypographyToken) => { return (

{ borderBottom: "1px solid #f0f0f0", }} > -
+
가나다라마 Aa
@@ -28,7 +27,7 @@ export const Typography = ({ token, size, weight, usage }: TypographyToken) => { {token}
- {size} / {weight} — {usage} + {size} / {weight} / {lineHeight} / {letterSpacing}
diff --git a/packages/timo-design-system/src/styles/components.css b/packages/timo-design-system/src/styles/components.css new file mode 100644 index 00000000..d17815d5 --- /dev/null +++ b/packages/timo-design-system/src/styles/components.css @@ -0,0 +1 @@ +@source "../components"; diff --git a/packages/timo-design-system/src/styles/globals.css b/packages/timo-design-system/src/styles/globals.css new file mode 100644 index 00000000..d2ca25af --- /dev/null +++ b/packages/timo-design-system/src/styles/globals.css @@ -0,0 +1,19 @@ +@import "tailwindcss"; +@import "@repo/tailwind-config/theme.css"; + +@font-face { + font-family: "Pretendard"; + src: url("../assets/fonts/PretendardVariable.woff2") format("woff2"); + font-weight: 45 920; + font-style: normal; + font-display: swap; +} +@layer base { + * { + font-family: var(--font-family-pretendard), sans-serif; + } +} + +:root { + --font-family-pretendard: "Pretendard"; +} \ No newline at end of file diff --git a/packages/timo-design-system/src/tokens/color-token.ts b/packages/timo-design-system/src/tokens/color-token.ts new file mode 100644 index 00000000..819cde2f --- /dev/null +++ b/packages/timo-design-system/src/tokens/color-token.ts @@ -0,0 +1,30 @@ +export interface ColorToken { + name: string; + cssVar: string; + value: string; +} + +export const COLOR_TOKENS: ColorToken[] = [ + { name: "timo-blue-50", cssVar: "--color-timo-blue-50", value: "#F1F6FE" }, + { name: "timo-blue-75", cssVar: "--color-timo-blue-75", value: "#C6D8FC" }, + { name: "timo-blue-100", cssVar: "--color-timo-blue-100", value: "#AEC8FB" }, + { name: "timo-blue-200", cssVar: "--color-timo-blue-200", value: "#8CB0F9" }, + { name: "timo-blue-300", cssVar: "--color-timo-blue-300", value: "#74A0F8" }, + + { name: "timo-gray-300", cssVar: "--color-timo-gray-300", value: "#F5F5F5" }, + { name: "timo-gray-500", cssVar: "--color-timo-gray-500", value: "#E6E8E8" }, + { name: "timo-gray-600", cssVar: "--color-timo-gray-600", value: "#D8D8D8" }, + { name: "timo-gray-700", cssVar: "--color-timo-gray-700", value: "#9F9F9F" }, + { name: "timo-gray-800", cssVar: "--color-timo-gray-800", value: "#757575" }, + { name: "timo-gray-900", cssVar: "--color-timo-gray-900", value: "#3F3F3F" }, + + { + name: "timo-yellow-300", + cssVar: "--color-timo-yellow-300", + value: "#F2FC9F", + }, + { name: "timo-black", cssVar: "--color-timo-black", value: "#121212" }, + { name: "timo-red", cssVar: "--color-timo-red", value: "#FF6650" }, + { name: "timo-orange", cssVar: "--color-timo-orange", value: "#FFB157" }, + { name: "timo-green", cssVar: "--color-timo-green", value: "#9FDDA9" }, +]; diff --git a/packages/timo-design-system/src/tokens/colort-token.ts b/packages/timo-design-system/src/tokens/colort-token.ts deleted file mode 100644 index 63ff149e..00000000 --- a/packages/timo-design-system/src/tokens/colort-token.ts +++ /dev/null @@ -1,27 +0,0 @@ -export interface ColorToken { - name: string; - cssVar: string; - value: string; - usage: string; -} - -export const COLOR_TOKENS: ColorToken[] = [ - { - name: "primary", - cssVar: "--color-primary", - value: "#111111", - usage: "브랜드 메인 (버튼, 강조)", - }, - { - name: "background", - cssVar: "--color-background", - value: "#ffffff", - usage: "페이지 배경", - }, - { - name: "foreground", - cssVar: "--color-foreground", - value: "#171717", - usage: "텍스트 기본", - }, -]; diff --git a/packages/timo-design-system/src/tokens/typography-token.ts b/packages/timo-design-system/src/tokens/typography-token.ts index 336371c5..05af721f 100644 --- a/packages/timo-design-system/src/tokens/typography-token.ts +++ b/packages/timo-design-system/src/tokens/typography-token.ts @@ -2,14 +2,121 @@ export interface TypographyToken { token: string; size: string; weight: string; - usage: string; + lineHeight: string; + letterSpacing: string; } export const TYPOGRAPHY_TOKENS: TypographyToken[] = [ - { token: "text-2xl", size: "24px", weight: "700", usage: "페이지 제목" }, - { token: "text-xl", size: "20px", weight: "600", usage: "섹션 제목" }, - { token: "text-lg", size: "18px", weight: "500", usage: "카드 제목" }, - { token: "text-base", size: "16px", weight: "400", usage: "본문 기본" }, - { token: "text-sm", size: "14px", weight: "400", usage: "보조 텍스트" }, - { token: "text-xs", size: "12px", weight: "400", usage: "캡션·레이블" }, + { + token: "typo-headline-b-30", + size: "30px", + weight: "700", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-headline-b-24", + size: "24px", + weight: "700", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-headline-b-22", + size: "22px", + weight: "700", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-headline-b-20", + size: "20px", + weight: "700", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-headline-b-18", + size: "18px", + weight: "700", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-headline-b-16", + size: "16px", + weight: "700", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-headline-m-16", + size: "16px", + weight: "500", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-headline-b-14", + size: "14px", + weight: "700", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-headline-m-14", + size: "14px", + weight: "500", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-headline-r-14", + size: "14px", + weight: "400", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-body-b-12", + size: "12px", + weight: "700", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-body-sb-12", + size: "12px", + weight: "600", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-body-m-12", + size: "12px", + weight: "500", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-body-r-12", + size: "12px", + weight: "400", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-body-sb-11", + size: "11px", + weight: "600", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, + { + token: "typo-caption-r-10", + size: "10px", + weight: "400", + lineHeight: "150%", + letterSpacing: "-0.03em", + }, ]; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1dcfc8b8..85c8e050 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -151,6 +151,9 @@ importers: '@repo/eslint-config': specifier: workspace:* version: link:../eslint-config + '@repo/tailwind-config': + specifier: workspace:* + version: link:../tailwind-config '@repo/typescript-config': specifier: workspace:* version: link:../typescript-config @@ -175,6 +178,9 @@ importers: '@storybook/react-vite': specifier: ^8.6.14 version: 8.6.14(@storybook/test@8.6.14(storybook@8.6.14(prettier@3.7.4)))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.62.2)(storybook@8.6.14(prettier@3.7.4))(typescript@5.9.2)(vite@8.1.0(@types/node@22.15.3)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + '@tailwindcss/postcss': + specifier: ^4.3.1 + version: 4.3.1 '@types/node': specifier: ^22.15.3 version: 22.15.3 @@ -193,6 +199,9 @@ importers: storybook: specifier: ^8.6.14 version: 8.6.14(prettier@3.7.4) + tailwindcss: + specifier: ^4.3.1 + version: 4.3.1 typescript: specifier: 5.9.2 version: 5.9.2