From 2aa88ddc60df77fac3250ca15b95bd0301d6647e Mon Sep 17 00:00:00 2001 From: LESANF Date: Tue, 22 Sep 2026 15:37:51 +0900 Subject: [PATCH] fix(styles): restore the @variant light block so Uniwind's theme check passes 0.0.10 kept light values only in @theme static, which Uniwind treats as the default table, not the light theme table. At boot it compared the light and dark tables and reported every token as missing from light. The parity test now compares the registered, light and dark blocks. Co-Authored-By: Claude Fable 5.1 --- CHANGELOG.md | 6 ++++++ docs/colors-in-js.md | 8 ++++---- src/lib/theme/use-colors.test.ts | 8 +++++--- src/styles/tokens/semantic.css | 24 ++++++++++++++++++++++-- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db5a9f8..ac39ffa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ ## [Unreleased] +### Fixed + +- **`semantic.css` 에 `@variant light` 블록을 되살렸다.** 0.0.10 은 light 값을 `@theme static` 에만 두어 + Uniwind 가 부팅 때 `Theme light is missing variable --color-…` 를 냈다. 의미 토큰은 등록·light·dark + 세 블록에 같이 넣는다 — `use-colors.test` 가 셋의 집합이 같은지 본다 + ## [0.0.10] — 2026-09-22 ### Added diff --git a/docs/colors-in-js.md b/docs/colors-in-js.md index 2321de5..6793376 100644 --- a/docs/colors-in-js.md +++ b/docs/colors-in-js.md @@ -25,8 +25,8 @@ const colors = useColors(); ``` src/styles/tokens/colors.css @theme static — 원시색 -src/styles/tokens/semantic.css @theme static — 의미 토큰 등록 + light 값 - @layer theme { :root { @variant dark { … } } } — dark 값 +src/styles/tokens/semantic.css @theme static — 의미 토큰 등록(값은 light 와 같음) + @layer theme { :root { @variant light { … } @variant dark { … } } } — 테마별 값 src/lib/theme/use-colors.ts useColors() — TOKENS 표 하나, useCSSVariable 배열 읽기 src/lib/theme/use-colors.test.ts 이름 검증 ``` @@ -61,7 +61,7 @@ export function useColors(): Colors { ## 색을 추가할 때 1. 원시색이면 `colors.css`에 `--color-<이름>: #hex`. -2. 의미 토큰이면 `semantic.css`의 `@theme static`(light)과 `@variant dark` **둘 다**에 원시색 참조로 적는다. +2. 의미 토큰이면 `semantic.css`의 `@theme static`(등록), `@variant light`, `@variant dark` **세 곳 모두**에 원시색 참조로 적는다. 하나라도 빠지면 Uniwind 가 부팅 때 `Theme light is missing variable` 을 낸다. 3. JS에서도 쓰면 `use-colors.ts`의 `TOKENS`에 한 줄 추가한다. ## 가드레일 @@ -134,5 +134,5 @@ ESLint 규칙이 살아 있는지 확인하는 테스트(`eslint.config.test.ts` ## 검증 - `pnpm run check-all`. -- 번들: `npx expo export --platform android --no-bytecode --output-dir <임시경로>` 뒤 번들에 `"__uniwind-theme-dark":{"--color-background":…}`(dark 표)와 기본 표의 `"--color-background":…`(light)가 둘 다 있는지 본다. +- 번들: `npx expo export --platform android --no-bytecode --output-dir <임시경로>` 뒤 번들에 `"__uniwind-theme-light"` 와 `"__uniwind-theme-dark"` 표가 둘 다 있고 각각에 토큰이 전부 있는지 본다. - jest에서는 Metro 변환이 안 돌아 `useCSSVariable` 값이 비어 있다. 색 값 자체를 검증하는 테스트는 쓸 수 없고 쓸 필요도 없다. diff --git a/src/lib/theme/use-colors.test.ts b/src/lib/theme/use-colors.test.ts index 9aa874b..5b41c5c 100644 --- a/src/lib/theme/use-colors.test.ts +++ b/src/lib/theme/use-colors.test.ts @@ -23,9 +23,11 @@ describe('useColors', () => { expect(primitives + semantic).not.toMatch(/@theme\s*\{/); }); - it('dark 는 light 와 같은 의미 토큰 집합이다 — 한쪽에만 추가하면 다른 테마에서 값이 빈다', () => { - const light = block(semantic, /@theme static \{/).sort(); + it('등록·light·dark 가 같은 의미 토큰 집합이다 — 어긋나면 Uniwind 가 부팅 때 "missing variable" 을 낸다', () => { + const registered = block(semantic, /@theme static \{/).sort(); + const light = block(semantic, /@variant light \{/).sort(); const dark = block(semantic, /@variant dark \{/).sort(); - expect(dark).toEqual(light); + expect(light).toEqual(registered); + expect(dark).toEqual(registered); }); }); diff --git a/src/styles/tokens/semantic.css b/src/styles/tokens/semantic.css index a0b8c19..85d47e4 100644 --- a/src/styles/tokens/semantic.css +++ b/src/styles/tokens/semantic.css @@ -1,5 +1,5 @@ -/* 의미 토큰. light 값은 @theme static, dark 는 아래에서 값만 바꾼다 — 화면 코드에 dark: 를 쓰지 않는다. - * 값은 원시색 참조만. 토큰은 두 블록에 같이 넣는다(use-colors.test 가 본다). */ +/* 의미 토큰. @theme static 은 등록(값은 light 와 같음), 테마별 값은 @variant light·dark — 화면 코드에 dark: 를 쓰지 않는다. + * Uniwind 는 부팅 때 light·dark 표의 변수 집합을 비교한다. 토큰은 세 블록에 같이 넣는다(use-colors.test 가 본다). */ @theme static { --color-background: var(--color-white); --color-foreground: var(--color-black); @@ -22,6 +22,26 @@ @layer theme { :root { + @variant light { + --color-background: var(--color-white); + --color-foreground: var(--color-black); + --color-card: var(--color-white); + --color-muted: var(--color-gray-100); + --color-muted-foreground: var(--color-gray-500); + + --color-primary: var(--color-gray-900); + --color-primary-foreground: var(--color-gray-50); + + --color-success: var(--color-green-500); + --color-warning: var(--color-amber-600); + --color-destructive: var(--color-red-600); + + --color-border: var(--color-gray-200); + + --color-tab-active: var(--color-gray-700); + --color-tab-inactive: var(--color-gray-300); + } + @variant dark { --color-background: var(--color-black); --color-foreground: var(--color-gray-50);