From 2196cf4200777a14183403b9f7368178937b755f Mon Sep 17 00:00:00 2001 From: clkim Date: Wed, 17 Sep 2025 15:45:02 +0900 Subject: [PATCH] =?UTF-8?q?feat.=20=EA=B2=8C=EC=9E=84=20=EC=BB=AC=EB=9F=AC?= =?UTF-8?q?=20=EB=A3=A8=ED=8A=B8=EC=97=90=20=EB=8F=99=EC=A0=81=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/app.vue | 10 ++ layers/assets/css/base/_theme.css | 14 --- layers/components/atoms/Button.vue | 4 +- layers/composables/useGameColors.ts | 154 ++------------------------- layers/plugins/game-colors.client.ts | 17 --- tailwind.config.ts | 7 -- 6 files changed, 22 insertions(+), 184 deletions(-) delete mode 100644 layers/plugins/game-colors.client.ts diff --git a/app/app.vue b/app/app.vue index 4f6092e..9bd036a 100644 --- a/app/app.vue +++ b/app/app.vue @@ -13,12 +13,14 @@ import { useNuxtApp } from 'nuxt/app' import LoadingFull from '#layers/components/blocks/loading/Full.vue' import LoadingLocal from '#layers/components/blocks/loading/Local.vue' import { useGameDataStore } from '#layers/stores/useGameDataStore' +import { useGameColors } from '#layers/composables/useGameColors' import type { GameDataMetaTag, GameDataValue } from '#layers/types/api/gameData' const nuxtApp = useNuxtApp() const getGameData = ref(null) const metaData = ref(null) const { setGameData } = useGameDataStore() +const { applyGameColors } = useGameColors() // SSR에서만 접근 가능 const gameDataFromServer = import.meta.server @@ -30,6 +32,14 @@ if (gameDataFromServer) { setGameData(gameDataFromServer) } +if (import.meta.client) { + const gameDataStore = useGameDataStore() + + if (gameDataStore.gameData?.key_color_codes) { + applyGameColors(gameDataStore.gameData.key_color_codes) + } +} + const meta = gameDataFromServer?.meta_tag ?? null const theme = gameDataFromServer?.design_theme === 1 ? 'dark' : 'light' diff --git a/layers/assets/css/base/_theme.css b/layers/assets/css/base/_theme.css index c697ed1..20a7080 100644 --- a/layers/assets/css/base/_theme.css +++ b/layers/assets/css/base/_theme.css @@ -8,13 +8,6 @@ --foreground-reversal-30: #ebebeb; /* gray-80 */ --foreground-reversal-40: rgba(0, 0, 0, 0.4); --foreground-reversal-70: #666666; /* gray-700 */ - - /* 게임별 동적 색상 기본값 */ - --game-primary: transparent; - --game-alternative-01: transparent; - --game-alternative-02: transparent; - --game-text-primary: transparent; - --game-text-secondary: transparent; } /* 다크 테마 색상 */ @@ -27,13 +20,6 @@ --foreground-reversal-30: #404040; /* gray-750 */ --foreground-reversal-40: rgba(255, 255, 255, 0.4); --foreground-reversal-70: #b2b2b2; /* gray-300 */ - - /* 게임별 동적 색상 기본값 */ - --game-primary: transparent; - --game-alternative-01: transparent; - --game-alternative-02: transparent; - --game-text-primary: transparent; - --game-text-secondary: transparent; } /* 커스텀 컴포넌트 스타일 */ diff --git a/layers/components/atoms/Button.vue b/layers/components/atoms/Button.vue index a110145..5526ed1 100644 --- a/layers/components/atoms/Button.vue +++ b/layers/components/atoms/Button.vue @@ -8,8 +8,8 @@ import type { // Props 정의 const props = withDefaults(defineProps(), { size: 'medium', - backgroundColor: 'var(--game-primary)', - textColor: 'var(--game-text-primary)', + backgroundColor: 'var(--primary)', + textColor: 'var(--text-primary)', icon: '', disabled: false, }) diff --git a/layers/composables/useGameColors.ts b/layers/composables/useGameColors.ts index 42390d3..e120883 100644 --- a/layers/composables/useGameColors.ts +++ b/layers/composables/useGameColors.ts @@ -1,160 +1,26 @@ -import { useGameDataStore } from '#layers/stores/useGameDataStore' import type { ParsedKeyColorCodes } from '#layers/types/api/gameData' /** - * 게임별 색상 코드를 CSS 변수로 설정하는 컴포저블 + * 게임 데이터의 key_color_codes를 CSS 커스텀 프로퍼티로 적용하는 기능을 제공합니다. */ export const useGameColors = () => { - const gameDataStore = useGameDataStore() - /** - * CSS에 정의된 기본 색상으로 리셋 + * @param keyColorCodes */ - const resetToDefaultColors = () => { - if (typeof document !== 'undefined') { - const root = document.documentElement - - // CSS에 정의된 기본값으로 리셋 (브라우저가 자동으로 CSS 값을 사용하도록 함) - root.style.removeProperty('--game-primary') - root.style.removeProperty('--game-alternative-01') - root.style.removeProperty('--game-alternative-02') - root.style.removeProperty('--game-text-primary') - root.style.removeProperty('--game-text-secondary') - - console.log('게임 색상을 CSS 기본값으로 리셋했습니다.') - } - } - - /** - * 게임 색상 코드를 파싱하여 CSS 변수로 설정 - */ - const setGameColors = () => { - if (!gameDataStore.gameData?.key_color_codes) { - console.warn( - '게임 색상 데이터가 없습니다. CSS에 정의된 기본 색상을 사용합니다.' - ) - // CSS에 정의된 기본값을 명시적으로 설정 (혹시 모를 경우를 대비) - resetToDefaultColors() + const applyGameColors = (keyColorCodes: ParsedKeyColorCodes | null) => { + if (!keyColorCodes || import.meta.server) { return } - try { - // key_color_codes가 문자열인 경우 파싱 - const colorCodes = - typeof gameDataStore.gameData.key_color_codes === 'string' - ? JSON.parse(gameDataStore.gameData.key_color_codes) - : gameDataStore.gameData.key_color_codes + const root = document.documentElement - const colors = colorCodes as ParsedKeyColorCodes - - // CSS 변수 설정 - if (typeof document !== 'undefined') { - const root = document.documentElement - - // 색상 유효성 검사 함수 - const isValidColor = (color: string): boolean => { - return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color) - } - - // 기본 색상 설정 (유효성 검사 포함) - if (colors.primary && isValidColor(colors.primary)) { - root.style.setProperty('--game-primary', colors.primary) - console.log('게임 Primary 색상 설정:', colors.primary) - } - - if (colors.secondary && isValidColor(colors.secondary)) { - root.style.setProperty('--game-secondary', colors.secondary) - console.log('게임 Secondary 색상 설정:', colors.secondary) - } - - if (colors['text-primary'] && isValidColor(colors['text-primary'])) { - root.style.setProperty('--game-text-primary', colors['text-primary']) - console.log('게임 텍스트 Primary 색상 설정:', colors['text-primary']) - } - - if ( - colors['text-secondary'] && - isValidColor(colors['text-secondary']) - ) { - root.style.setProperty( - '--game-text-secondary', - colors['text-secondary'] - ) - console.log( - '게임 텍스트 Secondary 색상 설정:', - colors['text-secondary'] - ) - } - - // alternative 색상들 설정 - if ( - colors['alternative-01'] && - isValidColor(colors['alternative-01']) - ) { - root.style.setProperty( - '--game-alternative-01', - colors['alternative-01'] - ) - console.log( - '게임 Alternative-01 색상 설정:', - colors['alternative-01'] - ) - } - - if ( - colors['alternative-02'] && - isValidColor(colors['alternative-02']) - ) { - root.style.setProperty( - '--game-alternative-02', - colors['alternative-02'] - ) - console.log( - '게임 Alternative-02 색상 설정:', - colors['alternative-02'] - ) - } - } - } catch (error) { - console.error('게임 색상 코드 파싱 오류:', error) - console.warn('CSS에 정의된 기본 색상을 사용합니다.') - resetToDefaultColors() - } - } - - /** - * 게임 색상 코드를 반환 - */ - const getGameColors = (): ParsedKeyColorCodes | null => { - if (!gameDataStore.gameData?.key_color_codes) { - return null - } - - try { - const colorCodes = - typeof gameDataStore.gameData.key_color_codes === 'string' - ? JSON.parse(gameDataStore.gameData.key_color_codes) - : gameDataStore.gameData.key_color_codes - - return colorCodes as ParsedKeyColorCodes - } catch (error) { - console.error('게임 색상 코드 파싱 오류:', error) - return null - } - } - - /** - * 특정 색상 코드를 반환 - */ - const getColor = (colorKey: keyof ParsedKeyColorCodes): string | null => { - const colors = getGameColors() - return colors?.[colorKey] || null + Object.entries(keyColorCodes).forEach(([key, value]) => { + const cssVarName = `--${key}` + root.style.setProperty(cssVarName, String(value)) + }) } return { - setGameColors, - getGameColors, - getColor, - resetToDefaultColors, + applyGameColors, } } diff --git a/layers/plugins/game-colors.client.ts b/layers/plugins/game-colors.client.ts deleted file mode 100644 index c806f71..0000000 --- a/layers/plugins/game-colors.client.ts +++ /dev/null @@ -1,17 +0,0 @@ -export default defineNuxtPlugin(() => { - const { setGameColors } = useGameColors() - - // 게임 데이터가 로드된 후 색상 설정 - const gameDataStore = useGameDataStore() - - // 게임 데이터가 변경될 때마다 색상 업데이트 - watch( - () => gameDataStore.gameData, - newGameData => { - if (newGameData) { - setGameColors() - } - }, - { immediate: true } - ) -}) diff --git a/tailwind.config.ts b/tailwind.config.ts index 89fefcf..cb44fdc 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -20,13 +20,6 @@ export default { 'theme-foreground-reversal-30': 'var(--foreground-reversal-30)', 'theme-foreground-reversal-40': 'var(--foreground-reversal-40)', 'theme-foreground-reversal-70': 'var(--foreground-reversal-70)', - - // 게임별 동적 색상 (CSS 변수로 설정) - 'game-primary': 'var(--game-primary)', - 'game-alternative-01': 'var(--game-alternative-01)', - 'game-alternative-02': 'var(--game-alternative-02)', - 'game-text-primary': 'var(--game-text-primary)', - 'game-text-secondary': 'var(--game-text-secondary)', }, }, },