diff --git a/.github/workflows/tokens.yaml b/.github/workflows/tokens.yaml index b9abf39e..793cd963 100644 --- a/.github/workflows/tokens.yaml +++ b/.github/workflows/tokens.yaml @@ -34,11 +34,6 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile - # Tokens Studio 포맷(value/type) → W3C DTCG($value/$type) 변환 - # 현재 tokens/ 파일이 이미 DTCG 포맷이면 변환 없이 통과 - - name: Transform (Tokens Studio → W3C DTCG) - run: pnpm --filter @sipe-team/tokens transform:tokens - # PR 리뷰용: base 브랜치 빌드 결과를 먼저 저장해 diff 비교 - name: Build base tokens id: base-build @@ -145,9 +140,8 @@ jobs: ### 파이프라인 1. Tokens Studio → `tokens/figma-sync` Push - 2. token-transformer: Tokens Studio 포맷 → W3C DTCG 변환 - 3. Style Dictionary: CSS 빌드 - 4. 이 PR → main 머지 후 VE codegen(추후 추가) + 2. Style Dictionary + @tokens-studio/sd-transforms: 변환 및 CSS/TS 빌드 + 3. 이 PR → main 머지 ### Review checklist - [ ] `validate` 잡 Step Summary에서 CSS diff 확인 diff --git a/.gitignore b/.gitignore index 4f3006f7..f2dc14e7 100644 --- a/.gitignore +++ b/.gitignore @@ -184,4 +184,7 @@ build/ .claude/settings.local.json # oh-my-claudecode local state -.omc/ \ No newline at end of file +.omc/ + +# Style Dictionary intermediate artifacts +**/tokens-transformed.json \ No newline at end of file diff --git a/packages/tokens/config.js b/packages/tokens/config.js index 7caf870b..c5c68533 100644 --- a/packages/tokens/config.js +++ b/packages/tokens/config.js @@ -1,19 +1,37 @@ -import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'; +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'; import { chdir } from 'node:process'; +import { register } from '@tokens-studio/sd-transforms'; import StyleDictionary from 'style-dictionary'; chdir(import.meta.dirname); +// Register Tokens Studio transforms and preprocessor into Style Dictionary +register(StyleDictionary, { excludeParentKeys: true }); + const DIST = 'dist/css'; const DIST_TS = 'dist/ts'; -const SEMANTIC_LIGHT_DIR = '../../tokens/semantic/light'; -/** @param {string} dir */ -function hasJsonFiles(dir) { - if (!existsSync(dir)) return false; - const entries = readdirSync(dir, { recursive: true }); - return entries.some((f) => f.toString().endsWith('.json')); +const allTokens = JSON.parse(readFileSync('../../tokens/tokens.json', 'utf-8')); +const setOrder = allTokens.$metadata?.tokenSetOrder ?? []; + +/** + * Build a token dict scoped to the given sets, preserving the multi-set wrapper + * so the tokens-studio preprocessor can strip the parent keys and merge sets. + * @param {string[]} setNames + */ +function buildSetDict(setNames) { + const dict = {}; + for (const name of setNames) { + if (allTokens[name]) dict[name] = allTokens[name]; + } + dict.$metadata = { tokenSetOrder: setNames.filter((n) => allTokens[n]) }; + return dict; +} + +/** @param {string} prefix */ +function hasSetsByPrefix(prefix) { + return setOrder.some((key) => key.startsWith(prefix) && allTokens[key] && Object.keys(allTokens[key]).length > 0); } /** @param {string} str */ @@ -24,9 +42,72 @@ function toPascalCase(str) { .join(''); } +/** + * Recursively collect all leaf token paths within the given sets. + * Used to compute which tokens belong exclusively to the semantic layer. + * @param {string[]} setNames + * @returns {Set} + */ +function getLeafPaths(setNames) { + const paths = new Set(); + function walk(obj, segments) { + if (obj && '$value' in obj) { + paths.add(segments.join('.')); + return; + } + for (const [k, v] of Object.entries(obj ?? {})) { + if (!k.startsWith('$') && v && typeof v === 'object') walk(v, [...segments, k]); + } + } + for (const name of setNames) { + if (allTokens[name]) walk(allTokens[name], []); + } + return paths; +} + +/** + * Recursively strip tokens that would create a circular reference when merged with primitives. + * @param {object} setContent + * @param {Set} primLeafPaths + * @returns {object} + */ +function _stripCircularAliases(setContent, primLeafPaths) { + function clean(obj, segments) { + if (!obj || typeof obj !== 'object') return obj; + if ('$value' in obj) { + const path = segments.join('.'); + if (primLeafPaths.has(path) && typeof obj.$value === 'string') { + const ref = obj.$value.match(/^\{([^}]+)\}$/)?.[1]; + if (ref === path) return null; + } + return obj; + } + const result = {}; + for (const [k, v] of Object.entries(obj)) { + if (k.startsWith('$')) { + result[k] = v; + continue; + } + const cleaned = clean(v, [...segments, k]); + if (cleaned !== null) result[k] = cleaned; + } + return result; + } + return clean(setContent, []); +} + +const primitiveSets = setOrder.filter((k) => k.startsWith('primitive/')); +// @INFO: All semantic sets contribute to the dark theme (dark is the default) +const darkSets = setOrder.filter((k) => k.startsWith('semantic/')); + +const primitiveLeafPaths = getLeafPaths(primitiveSets); +const darkLeafPaths = getLeafPaths(darkSets); +const semanticOnlyPaths = new Set([...darkLeafPaths].filter((p) => !primitiveLeafPaths.has(p))); + // Build primitive tokens (CSS + TypeScript types) const primitive = new StyleDictionary({ - source: ['../../tokens/primitive/**/*.json'], + tokens: buildSetDict(primitiveSets), + preprocessors: ['tokens-studio'], hooks: { formats: { 'typescript/token-names-dts': ({ dictionary }) => { @@ -48,14 +129,9 @@ const primitive = new StyleDictionary({ lines.push(`${names.map((n) => ` | '${n}'`).join('\n')};\n`); } - lines.push('export type DesignToken ='); + lines.push('export type PrimitiveToken ='); lines.push(`${typeNames.map((t) => ` | ${t}`).join('\n')};\n`); - lines.push( - '/** Wraps a design token name in `var()` for use in inline styles. */', - 'export declare function cssVar(token: T): `var(--${T})`;\n', - ); - return lines.join('\n'); }, 'typescript/token-names-js': () => @@ -78,7 +154,8 @@ const primitive = new StyleDictionary({ }, platforms: { css: { - transformGroup: 'css', + transformGroup: 'tokens-studio', + transforms: ['name/kebab'], buildPath: `${DIST}/`, files: [ { @@ -114,32 +191,87 @@ const primitive = new StyleDictionary({ }); await primitive.buildAllPlatforms(); -// Build semantic/light tokens — graceful no-op if directory is empty -if (hasJsonFiles(SEMANTIC_LIGHT_DIR)) { - const semanticLight = new StyleDictionary({ - source: [`${SEMANTIC_LIGHT_DIR}/**/*.json`], +// Build semantic/dark tokens — dark is the default theme, output to :root +// @NOTE: semantic/light is not yet developed; add a symmetric block when light sets are defined +if (hasSetsByPrefix('semantic/dark')) { + const semanticDarkDict = buildSetDict(primitiveSets); + for (const name of darkSets) { + if (allTokens[name]) semanticDarkDict[name] = _stripCircularAliases(allTokens[name], primitiveLeafPaths); + } + semanticDarkDict.$metadata = { tokenSetOrder: [...primitiveSets, ...darkSets].filter((n) => allTokens[n]) }; + + const semanticDark = new StyleDictionary({ + // @ts-expect-error - Style Dictionary's type definitions don't allow for the multi-set wrapper structure used by tokens-studio + tokens: semanticDarkDict, + preprocessors: ['tokens-studio'], + hooks: { + formats: { + 'typescript/semantic-token-names-dts': ({ dictionary }) => { + /** @type {Map} */ + const groups = new Map(); + for (const token of dictionary.allTokens) { + if (!semanticOnlyPaths.has(token.path.join('.'))) continue; + const category = token.path[0]; + if (!groups.has(category)) groups.set(category, []); + groups.get(category).push(token.name); + } + + const lines = ['/** Auto-generated — do not edit directly. */\n']; + const typeNames = []; + + for (const [category, names] of groups) { + const typeName = `Semantic${toPascalCase(category)}Token`; + typeNames.push(typeName); + lines.push(`export type ${typeName} =`); + lines.push(`${names.map((n) => ` | '${n}'`).join('\n')};\n`); + } + + lines.push('export type SemanticToken ='); + lines.push(`${typeNames.map((t) => ` | ${t}`).join('\n')};\n`); + + return lines.join('\n'); + }, + }, + }, platforms: { css: { - transformGroup: 'css', + transformGroup: 'tokens-studio', + transforms: ['name/kebab'], buildPath: `${DIST}/`, files: [ { - destination: 'semantic-light.css', + destination: 'semantic-dark.css', format: 'css/variables', + // Only emit tokens that are unique to the semantic layer. + filter: (token) => semanticOnlyPaths.has(token.path.join('.')), options: { selector: ':root', outputReferences: true }, }, ], }, + ts: { + transforms: ['name/kebab'], + buildPath: `${DIST_TS}/`, + files: [ + { + destination: 'semantic.d.ts', + format: 'typescript/semantic-token-names-dts', + }, + { + destination: 'semantic.d.cts', + format: 'typescript/semantic-token-names-dts', + }, + ], + }, }, }); - await semanticLight.buildAllPlatforms(); + await semanticDark.buildAllPlatforms(); } else { mkdirSync(DIST, { recursive: true }); - writeFileSync(`${DIST}/semantic-light.css`, '/* semantic/light tokens not yet defined */\n'); + writeFileSync(`${DIST}/semantic-dark.css`, '/* semantic/dark tokens not yet defined */\n'); } // Concatenate all CSS into index.css -const parts = [readFileSync(`${DIST}/primitive.css`, 'utf-8'), readFileSync(`${DIST}/semantic-light.css`, 'utf-8')]; +const parts = [readFileSync(`${DIST}/primitive.css`, 'utf-8'), readFileSync(`${DIST}/semantic-dark.css`, 'utf-8')]; writeFileSync(`${DIST}/index.css`, parts.join('\n')); console.log(`✓ ${DIST}/index.css generated`); @@ -149,13 +281,19 @@ writeFileSync( `${DIST_TS}/index.js`, "/** Auto-generated — do not edit directly. */\nexport * from './primitive.js';\n", ); -writeFileSync(`${DIST_TS}/index.d.ts`, "/** Auto-generated — do not edit directly. */\nexport * from './primitive';\n"); writeFileSync( `${DIST_TS}/index.cjs`, "/** Auto-generated — do not edit directly. */\n'use strict';\nmodule.exports = require('./primitive.cjs');\n", ); -writeFileSync( - `${DIST_TS}/index.d.cts`, - "/** Auto-generated — do not edit directly. */\nexport * from './primitive';\n", -); + +const barrelDts = [ + '/** Auto-generated — do not edit directly. */', + "export * from './primitive';", + "export * from './semantic';", + 'export type DesignToken = PrimitiveToken | SemanticToken;', + '/** Wraps a design token name in `var()` for use in inline styles. */', + 'export declare function cssVar(token: T): `var(--${T})`;\n', +].join('\n'); +writeFileSync(`${DIST_TS}/index.d.ts`, barrelDts); +writeFileSync(`${DIST_TS}/index.d.cts`, barrelDts); console.log(`✓ ${DIST_TS}/index.js + index.cjs generated`); diff --git a/packages/tokens/package.json b/packages/tokens/package.json index feb27209..8b74644a 100644 --- a/packages/tokens/package.json +++ b/packages/tokens/package.json @@ -18,7 +18,6 @@ "scripts": { "build": "tsup && pnpm build:tokens", "build:tokens": "node config.js", - "transform:tokens": "token-transformer ../../tokens /tmp/tokens-transformed.json", "lint": "pnpm exec biome lint", "typecheck": "tsc", "prepack": "pnpm run build", @@ -32,8 +31,8 @@ "@types/react": "catalog:react", "react": "catalog:react", "react-dom": "catalog:react", + "@tokens-studio/sd-transforms": "^2.0.0", "style-dictionary": "^5.4.0", - "token-transformer": "^0.0.33", "tsup": "catalog:", "typescript": "catalog:" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 30525b4e..b8941032 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1092,6 +1092,9 @@ importers: specifier: 'catalog:' version: 1.20.1 devDependencies: + '@tokens-studio/sd-transforms': + specifier: ^2.0.0 + version: 2.0.3(style-dictionary@5.4.0(tslib@2.8.1)) '@types/node': specifier: ^22 version: 22.10.1 @@ -1107,9 +1110,6 @@ importers: style-dictionary: specifier: ^5.4.0 version: 5.4.0(tslib@2.8.1) - token-transformer: - specifier: ^0.0.33 - version: 0.0.33 tsup: specifier: 'catalog:' version: 8.5.1(jiti@2.4.1)(postcss@8.5.9)(tsx@4.19.2)(typescript@5.6.3)(yaml@2.6.1) @@ -2024,6 +2024,9 @@ packages: '@bundled-es-modules/memfs@4.17.0': resolution: {integrity: sha512-ykdrkEmQr9BV804yd37ikXfNnvxrwYfY9Z2/EtMHFEFadEjsQXJ1zL9bVZrKNLDtm91UdUOEHso6Aweg93K6xQ==} + '@bundled-es-modules/postcss-calc-ast-parser@0.1.6': + resolution: {integrity: sha512-y65TM5zF+uaxo9OeekJ3rxwTINlQvrkbZLogYvQYVoLtxm4xEiHfZ7e/MyiWbStYyWZVZkVqsaVU6F4SUK5XUA==} + '@changesets/apply-release-plan@7.0.6': resolution: {integrity: sha512-TKhVLtiwtQOgMAC0fCJfmv93faiViKSDqr8oMEqrnNs99gtSC1sZh/aEMS9a+dseU1ESZRCK+ofLgGY7o0fw/Q==} @@ -3893,6 +3896,15 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' + '@tokens-studio/sd-transforms@2.0.3': + resolution: {integrity: sha512-PyrmRb7FuJBHzsbuWNk/O06hJbaZ+RL7chmK7PRbEptaSruhANai7Kxja5CiYnTcxOj373uRMDPxoFwCHaVpvA==} + engines: {node: '>=18.0.0'} + peerDependencies: + style-dictionary: ^5.0.0 + + '@tokens-studio/types@0.5.2': + resolution: {integrity: sha512-rzMcZP0bj2E5jaa7Fj0LGgYHysoCrbrxILVbT0ohsCUH5uCHY/u6J7Qw/TE0n6gR9Js/c9ZO9T8mOoz0HdLMbA==} + '@trysound/sax@0.2.0': resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -5521,6 +5533,10 @@ packages: resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==} engines: {node: '>=12.0.0'} + expr-eval-fork@3.0.3: + resolution: {integrity: sha512-BhC+hbc5lIVjygr840n5DEkW3MQq7H9o+mc1/N7Z5uIiCFVyESLL5DIE7LNq4CYUNxy+XjA+3jRrL/h0Kt2xcg==} + engines: {node: '>=16.9.0'} + express@4.21.2: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} @@ -6226,6 +6242,9 @@ packages: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} + is-mergeable-object@1.1.1: + resolution: {integrity: sha512-CPduJfuGg8h8vW74WOxHtHmtQutyQBzR+3MjQ6iDHIYdbOnm1YC7jv43SqCoU8OPGTJD4nibmiryA4kmogbGrA==} + is-nan@1.3.2: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} @@ -7416,6 +7435,10 @@ packages: peerDependencies: postcss: ^8.4 + postcss-calc-ast-parser@0.1.4: + resolution: {integrity: sha512-CebpbHc96zgFjGgdQ6BqBy6XIUgRx1xXWCAAk6oke02RZ5nxwo9KQejTg8y7uYEeI9kv8jKQPYjoe6REsY23vw==} + engines: {node: '>=6.5'} + postcss-calc@9.0.1: resolution: {integrity: sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==} engines: {node: ^14 || ^16 || >=18.0} @@ -7806,6 +7829,9 @@ packages: peerDependencies: postcss: ^8.4.31 + postcss-value-parser@3.3.1: + resolution: {integrity: sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==} + postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} @@ -8732,11 +8758,6 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - token-transformer@0.0.33: - resolution: {integrity: sha512-0h7Cvo8trUcv6sZPyA+iNHsFEwIhN4FhXtYqgndHQNYub+dTDW8ZCQURBNDNa0PvJ8Xg2wqG1V/5WSwV0l6yOw==} - deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. - hasBin: true - totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} @@ -10336,6 +10357,10 @@ snapshots: transitivePeerDependencies: - tslib + '@bundled-es-modules/postcss-calc-ast-parser@0.1.6': + dependencies: + postcss-calc-ast-parser: 0.1.4 + '@changesets/apply-release-plan@7.0.6': dependencies: '@changesets/config': 3.0.4 @@ -12883,6 +12908,18 @@ snapshots: dependencies: '@testing-library/dom': 10.4.0 + '@tokens-studio/sd-transforms@2.0.3(style-dictionary@5.4.0(tslib@2.8.1))': + dependencies: + '@bundled-es-modules/deepmerge': 4.3.1 + '@bundled-es-modules/postcss-calc-ast-parser': 0.1.6 + '@tokens-studio/types': 0.5.2 + colorjs.io: 0.5.2 + expr-eval-fork: 3.0.3 + is-mergeable-object: 1.1.1 + style-dictionary: 5.4.0(tslib@2.8.1) + + '@tokens-studio/types@0.5.2': {} + '@trysound/sax@0.2.0': {} '@tsconfig/strictest@2.0.5': {} @@ -14804,6 +14841,8 @@ snapshots: expect-type@1.1.0: {} + expr-eval-fork@3.0.3: {} + express@4.21.2: dependencies: accepts: 1.3.8 @@ -15665,6 +15704,8 @@ snapshots: is-interactive@1.0.0: {} + is-mergeable-object@1.1.1: {} + is-nan@1.3.2: dependencies: call-bind: 1.0.8 @@ -17074,6 +17115,10 @@ snapshots: postcss: 8.4.49 postcss-selector-parser: 7.0.0 + postcss-calc-ast-parser@0.1.4: + dependencies: + postcss-value-parser: 3.3.1 + postcss-calc@9.0.1(postcss@8.4.49): dependencies: postcss: 8.4.49 @@ -17499,6 +17544,8 @@ snapshots: postcss: 8.4.49 postcss-selector-parser: 6.1.2 + postcss-value-parser@3.3.1: {} + postcss-value-parser@4.2.0: {} postcss-zindex@6.0.2(postcss@8.4.49): @@ -18632,10 +18679,6 @@ snapshots: toidentifier@1.0.1: {} - token-transformer@0.0.33: - dependencies: - yargs: 17.7.2 - totalist@3.0.1: {} tough-cookie@5.1.2: diff --git a/tokens/primitive/color.json b/tokens/primitive/color.json deleted file mode 100644 index f9ad9271..00000000 --- a/tokens/primitive/color.json +++ /dev/null @@ -1,141 +0,0 @@ -{ - "color": { - "black": { "$value": "#131518", "$type": "color" }, - "white": { "$value": "#ffffff", "$type": "color" }, - "gray": { - "50": { "$value": "#fafafa", "$type": "color" }, - "100": { "$value": "#f4f4f5", "$type": "color" }, - "200": { "$value": "#e4e4e7", "$type": "color" }, - "300": { "$value": "#d4d4d8", "$type": "color" }, - "400": { "$value": "#a1a1aa", "$type": "color" }, - "500": { "$value": "#71717a", "$type": "color" }, - "600": { "$value": "#52525b", "$type": "color" }, - "700": { "$value": "#3f3f46", "$type": "color" }, - "800": { "$value": "#27272a", "$type": "color" }, - "900": { "$value": "#18181b", "$type": "color" }, - "950": { "$value": "#111111", "$type": "color" } - }, - "red": { - "50": { "$value": "#fef2f2", "$type": "color" }, - "100": { "$value": "#fee2e2", "$type": "color" }, - "200": { "$value": "#fecaca", "$type": "color" }, - "300": { "$value": "#fca5a5", "$type": "color" }, - "400": { "$value": "#f87171", "$type": "color" }, - "500": { "$value": "#ef4444", "$type": "color" }, - "600": { "$value": "#dc2626", "$type": "color" }, - "700": { "$value": "#991919", "$type": "color" }, - "800": { "$value": "#511111", "$type": "color" }, - "900": { "$value": "#300c0c", "$type": "color" }, - "950": { "$value": "#1f0808", "$type": "color" } - }, - "orange": { - "50": { "$value": "#fff7ed", "$type": "color" }, - "100": { "$value": "#ffedd5", "$type": "color" }, - "200": { "$value": "#fed7aa", "$type": "color" }, - "300": { "$value": "#fdba74", "$type": "color" }, - "400": { "$value": "#fb923c", "$type": "color" }, - "500": { "$value": "#f97316", "$type": "color" }, - "600": { "$value": "#ea580c", "$type": "color" }, - "700": { "$value": "#92310a", "$type": "color" }, - "800": { "$value": "#6c2710", "$type": "color" }, - "900": { "$value": "#3b1106", "$type": "color" }, - "950": { "$value": "#220a04", "$type": "color" } - }, - "brand": { - "default": { "$value": "#ffb24d", "$type": "color", "$description": "브랜드 기본 강조색 (기수별 교체)" }, - "hover": { "$value": "#d9963f", "$type": "color", "$description": "브랜드 hover 상태색 (기수별 교체)" }, - "subtle": { "$value": "#3b2005", "$type": "color", "$description": "브랜드 배경용 어두운 색 (기수별 교체)" } - }, - "yellow": { - "50": { "$value": "#fefce8", "$type": "color" }, - "100": { "$value": "#fef9c3", "$type": "color" }, - "200": { "$value": "#fef08a", "$type": "color" }, - "300": { "$value": "#fde047", "$type": "color" }, - "400": { "$value": "#facc15", "$type": "color" }, - "500": { "$value": "#eab308", "$type": "color" }, - "600": { "$value": "#ca8a04", "$type": "color" }, - "700": { "$value": "#845209", "$type": "color" }, - "800": { "$value": "#713f12", "$type": "color" }, - "900": { "$value": "#422006", "$type": "color" }, - "950": { "$value": "#281304", "$type": "color" } - }, - "green": { - "50": { "$value": "#f0fdf4", "$type": "color" }, - "100": { "$value": "#dcfce7", "$type": "color" }, - "200": { "$value": "#bbf7d0", "$type": "color" }, - "300": { "$value": "#86efac", "$type": "color" }, - "400": { "$value": "#4ade80", "$type": "color" }, - "500": { "$value": "#22c55e", "$type": "color" }, - "600": { "$value": "#16a34a", "$type": "color" }, - "700": { "$value": "#116932", "$type": "color" }, - "800": { "$value": "#124a28", "$type": "color" }, - "900": { "$value": "#042713", "$type": "color" }, - "950": { "$value": "#03190c", "$type": "color" } - }, - "teal": { - "50": { "$value": "#f0fdfa", "$type": "color" }, - "100": { "$value": "#ccfbf1", "$type": "color" }, - "200": { "$value": "#99f6e4", "$type": "color" }, - "300": { "$value": "#5eead4", "$type": "color" }, - "400": { "$value": "#2dd4bf", "$type": "color" }, - "500": { "$value": "#14b8a6", "$type": "color" }, - "600": { "$value": "#0d9488", "$type": "color" }, - "700": { "$value": "#0c5d56", "$type": "color" }, - "800": { "$value": "#114240", "$type": "color" }, - "900": { "$value": "#032726", "$type": "color" }, - "950": { "$value": "#021716", "$type": "color" } - }, - "blue": { - "50": { "$value": "#eff6ff", "$type": "color" }, - "100": { "$value": "#dbeafe", "$type": "color" }, - "200": { "$value": "#bfdbfe", "$type": "color" }, - "300": { "$value": "#a3cfff", "$type": "color" }, - "400": { "$value": "#60a5fa", "$type": "color" }, - "500": { "$value": "#3b82f6", "$type": "color" }, - "600": { "$value": "#2563eb", "$type": "color" }, - "700": { "$value": "#173da6", "$type": "color" }, - "800": { "$value": "#1a3478", "$type": "color" }, - "900": { "$value": "#14204a", "$type": "color" }, - "950": { "$value": "#0c142e", "$type": "color" } - }, - "cyan": { - "50": { "$value": "#ecfeff", "$type": "color" }, - "100": { "$value": "#cffafe", "$type": "color" }, - "200": { "$value": "#a5f3fc", "$type": "color" }, - "300": { "$value": "#00ffff", "$type": "color" }, - "400": { "$value": "#22d3ee", "$type": "color" }, - "500": { "$value": "#06b6d4", "$type": "color" }, - "600": { "$value": "#0891b2", "$type": "color" }, - "700": { "$value": "#0c5c72", "$type": "color" }, - "800": { "$value": "#134152", "$type": "color" }, - "900": { "$value": "#072a38", "$type": "color" }, - "950": { "$value": "#051b24", "$type": "color" } - }, - "purple": { - "50": { "$value": "#faf5ff", "$type": "color" }, - "100": { "$value": "#f3e8ff", "$type": "color" }, - "200": { "$value": "#e9d5ff", "$type": "color" }, - "300": { "$value": "#d8b4fe", "$type": "color" }, - "400": { "$value": "#c084fc", "$type": "color" }, - "500": { "$value": "#a855f7", "$type": "color" }, - "600": { "$value": "#9333ea", "$type": "color" }, - "700": { "$value": "#641ba3", "$type": "color" }, - "800": { "$value": "#4a1772", "$type": "color" }, - "900": { "$value": "#2f0553", "$type": "color" }, - "950": { "$value": "#1a032e", "$type": "color" } - }, - "pink": { - "50": { "$value": "#fdf2f8", "$type": "color" }, - "100": { "$value": "#fce7f3", "$type": "color" }, - "200": { "$value": "#fbcfe8", "$type": "color" }, - "300": { "$value": "#f9a8d4", "$type": "color" }, - "400": { "$value": "#f472b6", "$type": "color" }, - "500": { "$value": "#ec4899", "$type": "color" }, - "600": { "$value": "#db2777", "$type": "color" }, - "700": { "$value": "#a41752", "$type": "color" }, - "800": { "$value": "#6d0e34", "$type": "color" }, - "900": { "$value": "#45061f", "$type": "color" }, - "950": { "$value": "#2c0514", "$type": "color" } - } - } -} diff --git a/tokens/primitive/radius.json b/tokens/primitive/radius.json deleted file mode 100644 index 22d38bf8..00000000 --- a/tokens/primitive/radius.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "radius": { - "2": { "$value": "2px", "$type": "dimension" }, - "4": { "$value": "4px", "$type": "dimension" }, - "8": { "$value": "8px", "$type": "dimension" }, - "12": { "$value": "12px", "$type": "dimension" }, - "full": { "$value": "9999px", "$type": "dimension" } - } -} diff --git a/tokens/primitive/spacing.json b/tokens/primitive/spacing.json deleted file mode 100644 index 7c9b97f6..00000000 --- a/tokens/primitive/spacing.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "spacing": { - "4": { "$value": "4px", "$type": "dimension" }, - "8": { "$value": "8px", "$type": "dimension" }, - "12": { "$value": "12px", "$type": "dimension" }, - "16": { "$value": "16px", "$type": "dimension" }, - "20": { "$value": "20px", "$type": "dimension" }, - "24": { "$value": "24px", "$type": "dimension" }, - "32": { "$value": "32px", "$type": "dimension" }, - "40": { "$value": "40px", "$type": "dimension" }, - "48": { "$value": "48px", "$type": "dimension" }, - "64": { "$value": "64px", "$type": "dimension" } - } -} diff --git a/tokens/primitive/typography.json b/tokens/primitive/typography.json deleted file mode 100644 index 790a555e..00000000 --- a/tokens/primitive/typography.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "typography": { - "fontFamily": { - "base": { "$value": "'Pretendard', sans-serif", "$type": "fontFamily" } - }, - "fontSize": { - "12": { "$value": "12px", "$type": "dimension" }, - "14": { "$value": "14px", "$type": "dimension" }, - "16": { "$value": "16px", "$type": "dimension" }, - "18": { "$value": "18px", "$type": "dimension" }, - "20": { "$value": "20px", "$type": "dimension" }, - "24": { "$value": "24px", "$type": "dimension" }, - "28": { "$value": "28px", "$type": "dimension" }, - "32": { "$value": "32px", "$type": "dimension" }, - "36": { "$value": "36px", "$type": "dimension" }, - "48": { "$value": "48px", "$type": "dimension" } - }, - "fontWeight": { - "regular": { "$value": "400", "$type": "fontWeight" }, - "medium": { "$value": "500", "$type": "fontWeight" }, - "semiBold": { "$value": "600", "$type": "fontWeight" }, - "bold": { "$value": "700", "$type": "fontWeight" } - }, - "lineHeight": { - "compact": { "$value": "1.3", "$type": "number" }, - "regular": { "$value": "1.5", "$type": "number" } - } - } -} diff --git a/tokens/semantic/dark/color.json b/tokens/semantic/dark/color.json deleted file mode 100644 index 6b16490d..00000000 --- a/tokens/semantic/dark/color.json +++ /dev/null @@ -1,147 +0,0 @@ -{ - "color": { - "background": { - "base": { - "$value": "{color.gray.950}", - "$type": "color", - "$description": "1. 페이지 전체 기본 배경 / 2. 모달·시트 내부 배경" - }, - "subtle": { - "$value": "{color.gray.900}", - "$type": "color", - "$description": "1. 카드·섹션 표면 배경 / 2. 사이드바·패널 배경" - }, - "muted": { - "$value": "{color.gray.800}", - "$type": "color", - "$description": "1. 비활성(disabled) 입력 필드 배경 / 2. 스켈레톤 로딩 배경" - } - }, - "foreground": { - "default": { - "$value": "{color.white}", - "$type": "color", - "$description": "1. 본문 텍스트 / 2. 헤딩·레이블 기본 색상" - }, - "subtle": { - "$value": "{color.gray.400}", - "$type": "color", - "$description": "1. 보조 설명 텍스트 / 2. 인풋 힌트·캡션" - }, - "muted": { - "$value": "{color.gray.500}", - "$type": "color", - "$description": "1. 인풋 placeholder 텍스트 / 2. 비활성 아이콘 (장식적 요소 전용, 읽기용 텍스트 사용 금지)" - }, - "onAccent": { - "$value": "{color.white}", - "$type": "color", - "$description": "1. 강조색 배경 위 버튼 레이블 / 2. 배지·칩 내부 텍스트" - } - }, - "border": { - "default": { - "$value": "{color.gray.700}", - "$type": "color", - "$description": "1. 인풋·셀렉트 기본 테두리 / 2. 카드·구분선 보더" - }, - "strong": { - "$value": "{color.gray.500}", - "$type": "color", - "$description": "1. 호버 상태 인풋 테두리 강조 / 2. 구분 구역 강조 선" - }, - "focus": { - "$value": "{color.blue.400}", - "$type": "color", - "$description": "1. 키보드 포커스 링 색상 / 2. 활성 탭 언더라인" - } - }, - "accent": { - "default": { - "$value": "{color.brand.default}", - "$type": "color", - "$description": "1. Primary CTA 버튼 배경 / 2. 인터랙티브 링크 텍스트 (테마별 재정의됨)" - }, - "hover": { - "$value": "{color.brand.hover}", - "$type": "color", - "$description": "1. Primary 버튼 호버·프레스 배경 / 2. 링크 호버 색상" - }, - "subtle": { - "$value": "{color.brand.subtle}", - "$type": "color", - "$description": "1. 선택된 칩·태그 배경 / 2. 인포 배너 배경" - } - }, - "status": { - "success": { - "foreground": { - "$value": "{color.green.400}", - "$type": "color", - "$description": "1. 성공 상태 텍스트·아이콘 / 2. 완료 배지 레이블" - }, - "background": { - "$value": "{color.green.900}", - "$type": "color", - "$description": "1. 성공 토스트·배너 배경 / 2. 완료 상태 인풋 배경" - }, - "border": { - "$value": "{color.green.700}", - "$type": "color", - "$description": "1. 성공 인풋 테두리 / 2. 성공 알림 카드 보더" - } - }, - "warning": { - "foreground": { - "$value": "{color.orange.400}", - "$type": "color", - "$description": "1. 경고 텍스트·아이콘 / 2. 주의 배지 레이블" - }, - "background": { - "$value": "{color.orange.900}", - "$type": "color", - "$description": "1. 경고 배너·토스트 배경 / 2. 주의 섹션 하이라이트" - }, - "border": { - "$value": "{color.orange.700}", - "$type": "color", - "$description": "1. 경고 인풋 테두리 / 2. 주의 알림 카드 보더" - } - }, - "danger": { - "foreground": { - "$value": "{color.red.400}", - "$type": "color", - "$description": "1. 오류 메시지 텍스트·아이콘 / 2. 삭제·위험 액션 레이블" - }, - "background": { - "$value": "{color.red.900}", - "$type": "color", - "$description": "1. 에러 토스트·배너 배경 / 2. 유효성 오류 인풋 배경" - }, - "border": { - "$value": "{color.red.700}", - "$type": "color", - "$description": "1. 에러 인풋 테두리 / 2. 위험 액션 확인 다이얼로그 보더" - } - }, - "info": { - "foreground": { - "$value": "{color.blue.400}", - "$type": "color", - "$description": "1. 정보 텍스트·아이콘 / 2. 도움말 툴팁 레이블" - }, - "background": { - "$value": "{color.blue.900}", - "$type": "color", - "$description": "1. 정보 배너 배경 / 2. 안내 섹션 배경" - }, - "border": { - "$value": "{color.blue.700}", - "$type": "color", - "$description": "1. 정보 알림 카드 보더 / 2. 도움말 박스 테두리" - } - } - } - } -} diff --git a/tokens/semantic/light/.gitkeep b/tokens/semantic/light/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/tokens/semantic/radius.json b/tokens/semantic/radius.json deleted file mode 100644 index 1b694e25..00000000 --- a/tokens/semantic/radius.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "radius": { - "component": { - "sm": { - "$value": "{radius.2}", - "$type": "dimension", - "$description": "1. 태그·배지 모서리 / 2. 툴팁 모서리" - }, - "md": { - "$value": "{radius.4}", - "$type": "dimension", - "$description": "1. 버튼 모서리 / 2. 인풋·셀렉트 모서리" - }, - "lg": { - "$value": "{radius.8}", - "$type": "dimension", - "$description": "1. 카드 모서리 / 2. 드롭다운·팝오버 모서리" - }, - "xl": { - "$value": "{radius.12}", - "$type": "dimension", - "$description": "1. 다이얼로그·모달 모서리 / 2. 바텀 시트 상단 모서리" - }, - "full": { - "$value": "{radius.full}", - "$type": "dimension", - "$description": "1. 아바타·프로필 이미지 원형 처리 / 2. 필(Pill) 스타일 버튼·칩" - } - }, - "layout": { - "sm": { - "$value": "{radius.4}", - "$type": "dimension", - "$description": "1. 페이지 레벨 인라인 박스(콜아웃·배너) 모서리 / 2. 레이아웃 그리드 셀 모서리" - }, - "md": { - "$value": "{radius.8}", - "$type": "dimension", - "$description": "1. 섹션 컨테이너·페이지 카드 모서리 / 2. 사이드바 패널 모서리" - }, - "lg": { - "$value": "{radius.12}", - "$type": "dimension", - "$description": "1. 히어로·피처 섹션 배경 모서리 / 2. 주요 콘텐츠 영역 래퍼 모서리" - } - } - } -} diff --git a/tokens/semantic/spacing.json b/tokens/semantic/spacing.json deleted file mode 100644 index 35880982..00000000 --- a/tokens/semantic/spacing.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "spacing": { - "component": { - "xs": { - "$value": "{spacing.4}", - "$type": "dimension", - "$description": "1. 아이콘-텍스트 사이 간격 / 2. 태그·배지 내부 상하 패딩" - }, - "sm": { - "$value": "{spacing.8}", - "$type": "dimension", - "$description": "1. 버튼 상하 패딩 / 2. 인풋 상하 패딩" - }, - "md": { - "$value": "{spacing.12}", - "$type": "dimension", - "$description": "1. 인풋 좌우 패딩 / 2. 셀렉트 내부 패딩" - }, - "lg": { - "$value": "{spacing.16}", - "$type": "dimension", - "$description": "1. 카드 내부 패딩 / 2. 드롭다운 메뉴 항목 패딩" - }, - "xl": { - "$value": "{spacing.24}", - "$type": "dimension", - "$description": "1. 모달 내부 패딩 / 2. 시트 상단 여백" - } - }, - "layout": { - "sm": { - "$value": "{spacing.32}", - "$type": "dimension", - "$description": "1. 섹션 간 수직 간격 / 2. 폼 그룹 사이 간격" - }, - "md": { - "$value": "{spacing.40}", - "$type": "dimension", - "$description": "1. 페이지 좌우 여백(모바일) / 2. 카드 그리드 간격" - }, - "lg": { - "$value": "{spacing.48}", - "$type": "dimension", - "$description": "1. 페이지 좌우 여백(태블릿) / 2. 대형 섹션 내부 패딩" - }, - "xl": { - "$value": "{spacing.64}", - "$type": "dimension", - "$description": "1. 페이지 콘텐츠 최대 좌우 여백(데스크탑) / 2. 히어로 섹션 상하 패딩" - } - } - } -} diff --git a/tokens/semantic/typography.json b/tokens/semantic/typography.json deleted file mode 100644 index 9a9f031b..00000000 --- a/tokens/semantic/typography.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "typography": { - "fontFamily": { - "base": { - "$value": "{typography.fontFamily.base}", - "$type": "fontFamily", - "$description": "1. 모든 UI 텍스트 기본 폰트 / 2. 코드 블록 외 전체 텍스트" - } - }, - "lineHeight": { - "default": { - "$value": "{typography.lineHeight.regular}", - "$type": "number", - "$description": "1. 본문 단락 행간 / 2. 멀티라인 인풋 텍스트 행간" - }, - "tight": { - "$value": "{typography.lineHeight.compact}", - "$type": "number", - "$description": "1. 헤딩·제목 행간 / 2. 버튼·레이블 단행 텍스트 행간" - } - }, - "display": { - "fontSize": { - "$value": "{typography.fontSize.48}", - "$type": "dimension", - "$description": "1. 랜딩 히어로 헤딩 / 2. 최상위 마케팅 카피" - }, - "fontWeight": { - "$value": "{typography.fontWeight.bold}", - "$type": "fontWeight", - "$description": "1. 랜딩 히어로 텍스트 강조 / 2. 기능 소개 대형 카피" - } - }, - "heading": { - "lg": { - "fontSize": { - "$value": "{typography.fontSize.32}", - "$type": "dimension", - "$description": "1. 페이지 제목(h1) / 2. 다이얼로그 메인 제목" - }, - "fontWeight": { - "$value": "{typography.fontWeight.bold}", - "$type": "fontWeight", - "$description": "1. 페이지 대제목 강조 / 2. 섹션 최상위 타이틀" - } - }, - "md": { - "fontSize": { - "$value": "{typography.fontSize.24}", - "$type": "dimension", - "$description": "1. 섹션 제목(h2) / 2. 카드 헤딩" - }, - "fontWeight": { - "$value": "{typography.fontWeight.semiBold}", - "$type": "fontWeight", - "$description": "1. 섹션 소제목 / 2. 모달 타이틀" - } - }, - "sm": { - "fontSize": { - "$value": "{typography.fontSize.20}", - "$type": "dimension", - "$description": "1. 서브섹션 제목(h3) / 2. 리스트 그룹 레이블" - }, - "fontWeight": { - "$value": "{typography.fontWeight.semiBold}", - "$type": "fontWeight", - "$description": "1. 서브 헤딩 강조 / 2. 사이드바 섹션 타이틀" - } - } - }, - "body": { - "lg": { - "fontSize": { - "$value": "{typography.fontSize.18}", - "$type": "dimension", - "$description": "1. 긴 형식 본문 텍스트 / 2. 소개 단락" - }, - "fontWeight": { - "$value": "{typography.fontWeight.regular}", - "$type": "fontWeight", - "$description": "1. 기사·블로그 본문 / 2. 제품 상세 설명 텍스트" - } - }, - "md": { - "fontSize": { - "$value": "{typography.fontSize.16}", - "$type": "dimension", - "$description": "1. 일반 UI 본문 텍스트 / 2. 폼 인풋 입력값" - }, - "fontWeight": { - "$value": "{typography.fontWeight.regular}", - "$type": "fontWeight", - "$description": "1. 기본 단락 텍스트 / 2. 드롭다운 항목 텍스트" - } - }, - "sm": { - "fontSize": { - "$value": "{typography.fontSize.14}", - "$type": "dimension", - "$description": "1. 보조 설명 텍스트 / 2. 테이블 셀 텍스트" - }, - "fontWeight": { - "$value": "{typography.fontWeight.regular}", - "$type": "fontWeight", - "$description": "1. 인풋 헬프 텍스트 / 2. 리스트 아이템 설명" - } - } - }, - "label": { - "fontSize": { - "$value": "{typography.fontSize.14}", - "$type": "dimension", - "$description": "1. 폼 필드 레이블 / 2. 버튼 텍스트" - }, - "fontWeight": { - "$value": "{typography.fontWeight.medium}", - "$type": "fontWeight", - "$description": "1. 인풋 레이블 / 2. 네비게이션 링크" - } - }, - "caption": { - "fontSize": { - "$value": "{typography.fontSize.12}", - "$type": "dimension", - "$description": "1. 이미지 캡션 / 2. 에러·힌트 메시지" - }, - "fontWeight": { - "$value": "{typography.fontWeight.regular}", - "$type": "fontWeight", - "$description": "1. 타임스탬프·날짜 표시 / 2. 메타 정보 텍스트" - } - } - } -} diff --git a/tokens/tokens.json b/tokens/tokens.json new file mode 100644 index 00000000..549b2e47 --- /dev/null +++ b/tokens/tokens.json @@ -0,0 +1,1035 @@ +{ + "primitive/color": { + "color": { + "black": { + "$type": "color", + "$value": "#131518" + }, + "white": { + "$type": "color", + "$value": "#ffffff" + }, + "gray": { + "50": { + "$type": "color", + "$value": "#fafafa" + }, + "100": { + "$type": "color", + "$value": "#f4f4f5" + }, + "200": { + "$type": "color", + "$value": "#e4e4e7" + }, + "300": { + "$type": "color", + "$value": "#d4d4d8" + }, + "400": { + "$type": "color", + "$value": "#a1a1aa" + }, + "500": { + "$type": "color", + "$value": "#71717a" + }, + "600": { + "$type": "color", + "$value": "#52525b" + }, + "700": { + "$type": "color", + "$value": "#3f3f46" + }, + "800": { + "$type": "color", + "$value": "#27272a" + }, + "900": { + "$type": "color", + "$value": "#18181b" + }, + "950": { + "$type": "color", + "$value": "#111111" + } + }, + "red": { + "50": { + "$type": "color", + "$value": "#fef2f2" + }, + "100": { + "$type": "color", + "$value": "#fee2e2" + }, + "200": { + "$type": "color", + "$value": "#fecaca" + }, + "300": { + "$type": "color", + "$value": "#fca5a5" + }, + "400": { + "$type": "color", + "$value": "#f87171" + }, + "500": { + "$type": "color", + "$value": "#ef4444" + }, + "600": { + "$type": "color", + "$value": "#dc2626" + }, + "700": { + "$type": "color", + "$value": "#991919" + }, + "800": { + "$type": "color", + "$value": "#511111" + }, + "900": { + "$type": "color", + "$value": "#300c0c" + }, + "950": { + "$type": "color", + "$value": "#1f0808" + } + }, + "orange": { + "50": { + "$type": "color", + "$value": "#fff7ed" + }, + "100": { + "$type": "color", + "$value": "#ffedd5" + }, + "200": { + "$type": "color", + "$value": "#fed7aa" + }, + "300": { + "$type": "color", + "$value": "#fdba74" + }, + "400": { + "$type": "color", + "$value": "#fb923c" + }, + "500": { + "$type": "color", + "$value": "#f97316" + }, + "600": { + "$type": "color", + "$value": "#ea580c" + }, + "700": { + "$type": "color", + "$value": "#92310a" + }, + "800": { + "$type": "color", + "$value": "#6c2710" + }, + "900": { + "$type": "color", + "$value": "#3b1106" + }, + "950": { + "$type": "color", + "$value": "#220a04" + } + }, + "brand": { + "default": { + "$type": "color", + "$value": "#ffb24d", + "$description": "브랜드 기본 강조색 (기수별 교체)" + }, + "hover": { + "$type": "color", + "$value": "#d9963f", + "$description": "브랜드 hover 상태색 (기수별 교체)" + }, + "subtle": { + "$type": "color", + "$value": "#3b2005", + "$description": "브랜드 배경용 어두운 색 (기수별 교체)" + } + }, + "yellow": { + "50": { + "$type": "color", + "$value": "#fefce8" + }, + "100": { + "$type": "color", + "$value": "#fef9c3" + }, + "200": { + "$type": "color", + "$value": "#fef08a" + }, + "300": { + "$type": "color", + "$value": "#fde047" + }, + "400": { + "$type": "color", + "$value": "#facc15" + }, + "500": { + "$type": "color", + "$value": "#eab308" + }, + "600": { + "$type": "color", + "$value": "#ca8a04" + }, + "700": { + "$type": "color", + "$value": "#845209" + }, + "800": { + "$type": "color", + "$value": "#713f12" + }, + "900": { + "$type": "color", + "$value": "#422006" + }, + "950": { + "$type": "color", + "$value": "#281304" + } + }, + "green": { + "50": { + "$type": "color", + "$value": "#f0fdf4" + }, + "100": { + "$type": "color", + "$value": "#dcfce7" + }, + "200": { + "$type": "color", + "$value": "#bbf7d0" + }, + "300": { + "$type": "color", + "$value": "#86efac" + }, + "400": { + "$type": "color", + "$value": "#4ade80" + }, + "500": { + "$type": "color", + "$value": "#22c55e" + }, + "600": { + "$type": "color", + "$value": "#16a34a" + }, + "700": { + "$type": "color", + "$value": "#116932" + }, + "800": { + "$type": "color", + "$value": "#124a28" + }, + "900": { + "$type": "color", + "$value": "#042713" + }, + "950": { + "$type": "color", + "$value": "#03190c" + } + }, + "teal": { + "50": { + "$type": "color", + "$value": "#f0fdfa" + }, + "100": { + "$type": "color", + "$value": "#ccfbf1" + }, + "200": { + "$type": "color", + "$value": "#99f6e4" + }, + "300": { + "$type": "color", + "$value": "#5eead4" + }, + "400": { + "$type": "color", + "$value": "#2dd4bf" + }, + "500": { + "$type": "color", + "$value": "#14b8a6" + }, + "600": { + "$type": "color", + "$value": "#0d9488" + }, + "700": { + "$type": "color", + "$value": "#0c5d56" + }, + "800": { + "$type": "color", + "$value": "#114240" + }, + "900": { + "$type": "color", + "$value": "#032726" + }, + "950": { + "$type": "color", + "$value": "#021716" + } + }, + "blue": { + "50": { + "$type": "color", + "$value": "#eff6ff" + }, + "100": { + "$type": "color", + "$value": "#dbeafe" + }, + "200": { + "$type": "color", + "$value": "#bfdbfe" + }, + "300": { + "$type": "color", + "$value": "#a3cfff" + }, + "400": { + "$type": "color", + "$value": "#60a5fa" + }, + "500": { + "$type": "color", + "$value": "#3b82f6" + }, + "600": { + "$type": "color", + "$value": "#2563eb" + }, + "700": { + "$type": "color", + "$value": "#173da6" + }, + "800": { + "$type": "color", + "$value": "#1a3478" + }, + "900": { + "$type": "color", + "$value": "#14204a" + }, + "950": { + "$type": "color", + "$value": "#0c142e" + } + }, + "cyan": { + "50": { + "$type": "color", + "$value": "#ecfeff" + }, + "100": { + "$type": "color", + "$value": "#cffafe" + }, + "200": { + "$type": "color", + "$value": "#a5f3fc" + }, + "300": { + "$type": "color", + "$value": "#00ffff" + }, + "400": { + "$type": "color", + "$value": "#22d3ee" + }, + "500": { + "$type": "color", + "$value": "#06b6d4" + }, + "600": { + "$type": "color", + "$value": "#0891b2" + }, + "700": { + "$type": "color", + "$value": "#0c5c72" + }, + "800": { + "$type": "color", + "$value": "#134152" + }, + "900": { + "$type": "color", + "$value": "#072a38" + }, + "950": { + "$type": "color", + "$value": "#051b24" + } + }, + "purple": { + "50": { + "$type": "color", + "$value": "#faf5ff" + }, + "100": { + "$type": "color", + "$value": "#f3e8ff" + }, + "200": { + "$type": "color", + "$value": "#e9d5ff" + }, + "300": { + "$type": "color", + "$value": "#d8b4fe" + }, + "400": { + "$type": "color", + "$value": "#c084fc" + }, + "500": { + "$type": "color", + "$value": "#a855f7" + }, + "600": { + "$type": "color", + "$value": "#9333ea" + }, + "700": { + "$type": "color", + "$value": "#641ba3" + }, + "800": { + "$type": "color", + "$value": "#4a1772" + }, + "900": { + "$type": "color", + "$value": "#2f0553" + }, + "950": { + "$type": "color", + "$value": "#1a032e" + } + }, + "pink": { + "50": { + "$type": "color", + "$value": "#fdf2f8" + }, + "100": { + "$type": "color", + "$value": "#fce7f3" + }, + "200": { + "$type": "color", + "$value": "#fbcfe8" + }, + "300": { + "$type": "color", + "$value": "#f9a8d4" + }, + "400": { + "$type": "color", + "$value": "#f472b6" + }, + "500": { + "$type": "color", + "$value": "#ec4899" + }, + "600": { + "$type": "color", + "$value": "#db2777" + }, + "700": { + "$type": "color", + "$value": "#a41752" + }, + "800": { + "$type": "color", + "$value": "#6d0e34" + }, + "900": { + "$type": "color", + "$value": "#45061f" + }, + "950": { + "$type": "color", + "$value": "#2c0514" + } + } + } + }, + "primitive/radius": { + "radius": { + "2": { + "$type": "dimension", + "$value": "2px" + }, + "4": { + "$type": "dimension", + "$value": "4px" + }, + "8": { + "$type": "dimension", + "$value": "8px" + }, + "12": { + "$type": "dimension", + "$value": "12px" + }, + "full": { + "$type": "dimension", + "$value": "9999px" + } + } + }, + "primitive/spacing": { + "spacing": { + "4": { + "$type": "dimension", + "$value": "4px" + }, + "8": { + "$type": "dimension", + "$value": "8px" + }, + "12": { + "$type": "dimension", + "$value": "12px" + }, + "16": { + "$type": "dimension", + "$value": "16px" + }, + "20": { + "$type": "dimension", + "$value": "20px" + }, + "24": { + "$type": "dimension", + "$value": "24px" + }, + "32": { + "$type": "dimension", + "$value": "32px" + }, + "40": { + "$type": "dimension", + "$value": "40px" + }, + "48": { + "$type": "dimension", + "$value": "48px" + }, + "64": { + "$type": "dimension", + "$value": "64px" + } + } + }, + "primitive/typography": { + "typography": { + "fontFamily": { + "base": { + "$type": "fontFamily", + "$value": "'Pretendard', sans-serif" + } + }, + "fontSize": { + "12": { + "$type": "dimension", + "$value": "12px" + }, + "14": { + "$type": "dimension", + "$value": "14px" + }, + "16": { + "$type": "dimension", + "$value": "16px" + }, + "18": { + "$type": "dimension", + "$value": "18px" + }, + "20": { + "$type": "dimension", + "$value": "20px" + }, + "24": { + "$type": "dimension", + "$value": "24px" + }, + "28": { + "$type": "dimension", + "$value": "28px" + }, + "32": { + "$type": "dimension", + "$value": "32px" + }, + "36": { + "$type": "dimension", + "$value": "36px" + }, + "48": { + "$type": "dimension", + "$value": "48px" + } + }, + "fontWeight": { + "regular": { + "$type": "fontWeight", + "$value": "400" + }, + "medium": { + "$type": "fontWeight", + "$value": "500" + }, + "semiBold": { + "$type": "fontWeight", + "$value": "600" + }, + "bold": { + "$type": "fontWeight", + "$value": "700" + } + }, + "lineHeight": { + "compact": { + "$type": "number", + "$value": "1.3" + }, + "regular": { + "$type": "number", + "$value": "1.5" + } + } + } + }, + "semantic/dark/color": { + "color": { + "background": { + "base": { + "$type": "color", + "$value": "{color.gray.950}", + "$description": "1. 페이지 전체 기본 배경 / 2. 모달·시트 내부 배경" + }, + "subtle": { + "$type": "color", + "$value": "{color.gray.900}", + "$description": "1. 카드·섹션 표면 배경 / 2. 사이드바·패널 배경" + }, + "muted": { + "$type": "color", + "$value": "{color.gray.800}", + "$description": "1. 비활성(disabled) 입력 필드 배경 / 2. 스켈레톤 로딩 배경" + } + }, + "foreground": { + "default": { + "$type": "color", + "$value": "{color.white}", + "$description": "1. 본문 텍스트 / 2. 헤딩·레이블 기본 색상" + }, + "subtle": { + "$type": "color", + "$value": "{color.gray.400}", + "$description": "1. 보조 설명 텍스트 / 2. 인풋 힌트·캡션" + }, + "muted": { + "$type": "color", + "$value": "{color.gray.500}", + "$description": "1. 인풋 placeholder 텍스트 / 2. 비활성 아이콘 (장식적 요소 전용, 읽기용 텍스트 사용 금지)" + }, + "onAccent": { + "$type": "color", + "$value": "{color.white}", + "$description": "1. 강조색 배경 위 버튼 레이블 / 2. 배지·칩 내부 텍스트" + } + }, + "border": { + "default": { + "$type": "color", + "$value": "{color.gray.700}", + "$description": "1. 인풋·셀렉트 기본 테두리 / 2. 카드·구분선 보더" + }, + "strong": { + "$type": "color", + "$value": "{color.gray.500}", + "$description": "1. 호버 상태 인풋 테두리 강조 / 2. 구분 구역 강조 선" + }, + "focus": { + "$type": "color", + "$value": "{color.blue.400}", + "$description": "1. 키보드 포커스 링 색상 / 2. 활성 탭 언더라인" + } + }, + "accent": { + "default": { + "$type": "color", + "$value": "{color.brand.default}", + "$description": "1. Primary CTA 버튼 배경 / 2. 인터랙티브 링크 텍스트 (테마별 재정의됨)" + }, + "hover": { + "$type": "color", + "$value": "{color.brand.hover}", + "$description": "1. Primary 버튼 호버·프레스 배경 / 2. 링크 호버 색상" + }, + "subtle": { + "$type": "color", + "$value": "{color.brand.subtle}", + "$description": "1. 선택된 칩·태그 배경 / 2. 인포 배너 배경" + } + }, + "status": { + "success": { + "foreground": { + "$type": "color", + "$value": "{color.green.400}", + "$description": "1. 성공 상태 텍스트·아이콘 / 2. 완료 배지 레이블" + }, + "background": { + "$type": "color", + "$value": "{color.green.900}", + "$description": "1. 성공 토스트·배너 배경 / 2. 완료 상태 인풋 배경" + }, + "border": { + "$type": "color", + "$value": "{color.green.700}", + "$description": "1. 성공 인풋 테두리 / 2. 성공 알림 카드 보더" + } + }, + "warning": { + "foreground": { + "$type": "color", + "$value": "{color.orange.400}", + "$description": "1. 경고 텍스트·아이콘 / 2. 주의 배지 레이블" + }, + "background": { + "$type": "color", + "$value": "{color.orange.900}", + "$description": "1. 경고 배너·토스트 배경 / 2. 주의 섹션 하이라이트" + }, + "border": { + "$type": "color", + "$value": "{color.orange.700}", + "$description": "1. 경고 인풋 테두리 / 2. 주의 알림 카드 보더" + } + }, + "danger": { + "foreground": { + "$type": "color", + "$value": "{color.red.400}", + "$description": "1. 오류 메시지 텍스트·아이콘 / 2. 삭제·위험 액션 레이블" + }, + "background": { + "$type": "color", + "$value": "{color.red.900}", + "$description": "1. 에러 토스트·배너 배경 / 2. 유효성 오류 인풋 배경" + }, + "border": { + "$type": "color", + "$value": "{color.red.700}", + "$description": "1. 에러 인풋 테두리 / 2. 위험 액션 확인 다이얼로그 보더" + } + }, + "info": { + "foreground": { + "$type": "color", + "$value": "{color.blue.400}", + "$description": "1. 정보 텍스트·아이콘 / 2. 도움말 툴팁 레이블" + }, + "background": { + "$type": "color", + "$value": "{color.blue.900}", + "$description": "1. 정보 배너 배경 / 2. 안내 섹션 배경" + }, + "border": { + "$type": "color", + "$value": "{color.blue.700}", + "$description": "1. 정보 알림 카드 보더 / 2. 도움말 박스 테두리" + } + } + } + } + }, + "semantic/radius": { + "radius": { + "component": { + "sm": { + "$type": "dimension", + "$value": "{radius.2}", + "$description": "1. 태그·배지 모서리 / 2. 툴팁 모서리" + }, + "md": { + "$type": "dimension", + "$value": "{radius.4}", + "$description": "1. 버튼 모서리 / 2. 인풋·셀렉트 모서리" + }, + "lg": { + "$type": "dimension", + "$value": "{radius.8}", + "$description": "1. 카드 모서리 / 2. 드롭다운·팝오버 모서리" + }, + "xl": { + "$type": "dimension", + "$value": "{radius.12}", + "$description": "1. 다이얼로그·모달 모서리 / 2. 바텀 시트 상단 모서리" + }, + "full": { + "$type": "dimension", + "$value": "{radius.full}", + "$description": "1. 아바타·프로필 이미지 원형 처리 / 2. 필(Pill) 스타일 버튼·칩" + } + }, + "layout": { + "sm": { + "$type": "dimension", + "$value": "{radius.4}", + "$description": "1. 페이지 레벨 인라인 박스(콜아웃·배너) 모서리 / 2. 레이아웃 그리드 셀 모서리" + }, + "md": { + "$type": "dimension", + "$value": "{radius.8}", + "$description": "1. 섹션 컨테이너·페이지 카드 모서리 / 2. 사이드바 패널 모서리" + }, + "lg": { + "$type": "dimension", + "$value": "{radius.12}", + "$description": "1. 히어로·피처 섹션 배경 모서리 / 2. 주요 콘텐츠 영역 래퍼 모서리" + } + } + } + }, + "semantic/spacing": { + "spacing": { + "component": { + "xs": { + "$type": "dimension", + "$value": "{spacing.4}", + "$description": "1. 아이콘-텍스트 사이 간격 / 2. 태그·배지 내부 상하 패딩" + }, + "sm": { + "$type": "dimension", + "$value": "{spacing.8}", + "$description": "1. 버튼 상하 패딩 / 2. 인풋 상하 패딩" + }, + "md": { + "$type": "dimension", + "$value": "{spacing.12}", + "$description": "1. 인풋 좌우 패딩 / 2. 셀렉트 내부 패딩" + }, + "lg": { + "$type": "dimension", + "$value": "{spacing.16}", + "$description": "1. 카드 내부 패딩 / 2. 드롭다운 메뉴 항목 패딩" + }, + "xl": { + "$type": "dimension", + "$value": "{spacing.24}", + "$description": "1. 모달 내부 패딩 / 2. 시트 상단 여백" + } + }, + "layout": { + "sm": { + "$type": "dimension", + "$value": "{spacing.32}", + "$description": "1. 섹션 간 수직 간격 / 2. 폼 그룹 사이 간격" + }, + "md": { + "$type": "dimension", + "$value": "{spacing.40}", + "$description": "1. 페이지 좌우 여백(모바일) / 2. 카드 그리드 간격" + }, + "lg": { + "$type": "dimension", + "$value": "{spacing.48}", + "$description": "1. 페이지 좌우 여백(태블릿) / 2. 대형 섹션 내부 패딩" + }, + "xl": { + "$type": "dimension", + "$value": "{spacing.64}", + "$description": "1. 페이지 콘텐츠 최대 좌우 여백(데스크탑) / 2. 히어로 섹션 상하 패딩" + } + } + } + }, + "semantic/typography": { + "typography": { + "fontFamily": { + "base": { + "$type": "fontFamily", + "$value": "{typography.fontFamily.base}", + "$description": "1. 모든 UI 텍스트 기본 폰트 / 2. 코드 블록 외 전체 텍스트" + } + }, + "lineHeight": { + "default": { + "$type": "number", + "$value": "{typography.lineHeight.regular}", + "$description": "1. 본문 단락 행간 / 2. 멀티라인 인풋 텍스트 행간" + }, + "tight": { + "$type": "number", + "$value": "{typography.lineHeight.compact}", + "$description": "1. 헤딩·제목 행간 / 2. 버튼·레이블 단행 텍스트 행간" + } + }, + "display": { + "fontSize": { + "$type": "dimension", + "$value": "{typography.fontSize.48}", + "$description": "1. 랜딩 히어로 헤딩 / 2. 최상위 마케팅 카피" + }, + "fontWeight": { + "$type": "fontWeight", + "$value": "{typography.fontWeight.bold}", + "$description": "1. 랜딩 히어로 텍스트 강조 / 2. 기능 소개 대형 카피" + } + }, + "heading": { + "lg": { + "fontSize": { + "$type": "dimension", + "$value": "{typography.fontSize.32}", + "$description": "1. 페이지 제목(h1) / 2. 다이얼로그 메인 제목" + }, + "fontWeight": { + "$type": "fontWeight", + "$value": "{typography.fontWeight.bold}", + "$description": "1. 페이지 대제목 강조 / 2. 섹션 최상위 타이틀" + } + }, + "md": { + "fontSize": { + "$type": "dimension", + "$value": "{typography.fontSize.24}", + "$description": "1. 섹션 제목(h2) / 2. 카드 헤딩" + }, + "fontWeight": { + "$type": "fontWeight", + "$value": "{typography.fontWeight.semiBold}", + "$description": "1. 섹션 소제목 / 2. 모달 타이틀" + } + }, + "sm": { + "fontSize": { + "$type": "dimension", + "$value": "{typography.fontSize.20}", + "$description": "1. 서브섹션 제목(h3) / 2. 리스트 그룹 레이블" + }, + "fontWeight": { + "$type": "fontWeight", + "$value": "{typography.fontWeight.semiBold}", + "$description": "1. 서브 헤딩 강조 / 2. 사이드바 섹션 타이틀" + } + } + }, + "body": { + "lg": { + "fontSize": { + "$type": "dimension", + "$value": "{typography.fontSize.18}", + "$description": "1. 긴 형식 본문 텍스트 / 2. 소개 단락" + }, + "fontWeight": { + "$type": "fontWeight", + "$value": "{typography.fontWeight.regular}", + "$description": "1. 기사·블로그 본문 / 2. 제품 상세 설명 텍스트" + } + }, + "md": { + "fontSize": { + "$type": "dimension", + "$value": "{typography.fontSize.16}", + "$description": "1. 일반 UI 본문 텍스트 / 2. 폼 인풋 입력값" + }, + "fontWeight": { + "$type": "fontWeight", + "$value": "{typography.fontWeight.regular}", + "$description": "1. 기본 단락 텍스트 / 2. 드롭다운 항목 텍스트" + } + }, + "sm": { + "fontSize": { + "$type": "dimension", + "$value": "{typography.fontSize.14}", + "$description": "1. 보조 설명 텍스트 / 2. 테이블 셀 텍스트" + }, + "fontWeight": { + "$type": "fontWeight", + "$value": "{typography.fontWeight.regular}", + "$description": "1. 인풋 헬프 텍스트 / 2. 리스트 아이템 설명" + } + } + }, + "label": { + "fontSize": { + "$type": "dimension", + "$value": "{typography.fontSize.14}", + "$description": "1. 폼 필드 레이블 / 2. 버튼 텍스트" + }, + "fontWeight": { + "$type": "fontWeight", + "$value": "{typography.fontWeight.medium}", + "$description": "1. 인풋 레이블 / 2. 네비게이션 링크" + } + }, + "caption": { + "fontSize": { + "$type": "dimension", + "$value": "{typography.fontSize.12}", + "$description": "1. 이미지 캡션 / 2. 에러·힌트 메시지" + }, + "fontWeight": { + "$type": "fontWeight", + "$value": "{typography.fontWeight.regular}", + "$description": "1. 타임스탬프·날짜 표시 / 2. 메타 정보 텍스트" + } + } + } + }, + "$themes": [], + "$metadata": { + "tokenSetOrder": [ + "primitive/color", + "primitive/radius", + "primitive/spacing", + "primitive/typography", + "semantic/dark/color", + "semantic/radius", + "semantic/spacing", + "semantic/typography" + ] + } +}