Skip to content

feat: 라이트 모드 도입과 디자인 토큰 테마 분리 - #148

Merged
lee-sihun merged 23 commits into
mainfrom
feat/light-theme
Oct 21, 2026
Merged

lee-sihun merged 23 commits into
mainfrom
feat/light-theme

Conversation

@eun-yeon

Copy link
Copy Markdown
Member

개요

앱 UI에 라이트 모드를 넣음. 색을 반전한 것이 아니라 다크 팔레트의 실측 단차를 밝은 쪽에서 재현했고, 그 과정에서 토큰 체계를 테마별로 나눠 라이트 값 누락이 조용히 다크로 새지 않게 구조로 막음. 설정 미리보기 클립도 라이트 한 벌을 렌더해 붙임

변경 내용

토큰 구조

  • tokens.css를 배럴로 바꾸고 tokens/{base,dark,light}.css 3분할
  • 다크를 bare :root 폴백으로 두지 않음. 라이트 토큰이 빠지면 미정의가 되어 즉시 드러나고, 세 창 html의 data-theme 정적 속성이 미정의를 막음
  • 선택자를 :root:where([data-theme='...'])로 잡아 뒤에 주입되는 사용자 CSS의 :root 재정의와 특이도 동률 유지
  • 파리티 계약 테스트로 두 테마의 키 집합과 선언 순서 일치, base에 색 없음, tailwind와 소스가 참조하는 모든 --ui-*가 양쪽에 존재함을 고정

라이트 팔레트

면 관계를 다크 실측 ΔL*로 맞춤

면 관계 다크 라이트
상하단 크롬 -> 캔버스 +3.9 +5.7
패널 유리 -> 카드 +4.0 +3.4
캔버스 -> 격자선 +6.9 -6.0
유리 -> 둘레 링 +8.2 -7.7
유리 -> 상단 립 +3.3 +2.9
  • 크롬과 캔버스만 폭을 넓힘. 다크는 두 면의 휘도비가 1.67배라 작은 ΔL*로도 갈리는데 밝은 쪽은 1.1배도 안 나옴
  • 카드가 뜨는 방향이 유일한 구조적 반전. --ui-fill-faint만 흰 알파를 쓰고, 조작면인 --ui-fill 계열은 라이트에서도 잉크가 늘어나는 방향을 유지
  • 유리의 밝기 바닥은 틴트 알파가 소유. brightness(>1)은 대응물이 아님. sRGB 곱연산이라 검정은 곱해도 검정이고 밝은 쪽만 먼저 포화하므로, 범위를 좁히는 contrast(<1) 항을 필터 체인에 추가
  • 립은 하이브리드. 둘레 링은 어두운 잉크로 뒤집고 상단 하이라이트는 흰색 유지. 테마가 바뀐다고 광원 방향이 뒤집히지는 않음
  • 읽어야 하는 --ui-fg-caption과 장식용 --ui-fg-faint 분리. 밝은 바탕에서는 대비비가 빠르게 압축돼 한 값으로 묶으면 앱 바닥의 작은 글자를 살릴 때 muted와 뭉침

테마 전환

  • system, light, dark 3단이고 기본값은 system
  • 부트 스크립트가 첫 페인트 전에 테마를 확정하고, store 초기값도 같은 캐시를 읽어 첫 렌더에서 어긋나지 않음
  • 분리 패널 자식 문서에 테마 전파. 스타일 미러링은 head 노드만 옮기고 html 속성은 따라가지 않음
  • 네이티브 패널 크롬 재동기화. head 옵저버는 html 속성 변경을 보지 못함
  • 파형처럼 토큰을 구워 그리는 캔버스는 전환 시 재드로우

백엔드

  • ui_theme 스칼라 설정. 프리셋 화이트리스트와 히스토리 스냅샷에서 제외해 프리셋 로드와 Undo가 테마를 건드리지 않음
  • 창별 set_theme. 메인과 분리 패널만 적용하고 투명 창인 오버레이는 제외
  • 첫 페인트 배경색은 숨긴 창을 만든 뒤 테마를 해석해 지정하고 표시. OS 테마 변경도 추종
  • Windows 첫 프레임 씨앗 색 테마 분기

설정 미리보기 클립

  • 라이트 9종 렌더. 구성과 모션과 길이는 다크와 완전히 같고 색만 다름
  • 무대 바닥만 중간 회색. 흰 무대에서는 눌림 피드백 대비가 ΔL* 80.7에서 8.8로 무너져 키를 눌러도 아무 일도 안 일어난 것처럼 보임
  • 무대 위에 그리는 윤곽선은 주변 콘텐츠와 반대 방향으로 감. 대비비만 맞추면 어두운 키 무리에 섞여 배경 무늬로 읽힘
  • 렌더 워크스페이스는 .gitignore 규약대로 로컬 전용이라 결과 mp4만 포함

접근성

  • 아이콘 버튼에 접근성 이름 추가. ariaLabel을 필수 prop으로 만들어 누락을 컴파일 단계에서 막음
  • 최신 버전 모달의 화면 제목과 dialog 이름 불일치 수정

검증

  • Vitest 3,145 통과, 18 스킵, 실패 0
  • Rust lib 935 통과, main 933 통과, 실패 0
  • 타입, 포맷, 린트, cargo check, clippy, cargo fmt --check 통과
  • 팔레트 값은 계산으로 끝내지 않고 실제 토큰 파일을 불러오는 화면을 렌더해 눈으로 확인하며 세 차례 재보정

남은 것

  • macOS 트래픽 라이트 외관과 OS 테마 실시간 전환 실기 확인
  • Windows 첫 프레임 씨앗 색 실기 확인. 해당 테스트는 Windows 전용이라 macOS에서는 실행되지 않음
  • 라이트 클립 재생 확인

@eun-yeon

Copy link
Copy Markdown
Member Author

리베이스 필수

eun-yeon and others added 12 commits October 7, 2026 20:14
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
main의 모듈 경계 분리·소스 구조 재편에 맞춰 PR 변경을 새 위치로 옮김

- 백엔드: UiTheme을 models/settings.rs로, window_theme.rs를 state/window/로 이동.
  패널 창 테마·씨앗 색은 app_state/panel_runtime.rs, 설정 반영은 overlay_runtime.rs,
  메인 창 ThemeChanged 처리는 lifecycle_runtime.rs, 메인 창 초기 반영은 app.rs에 적용.
  apply_patch_to_store 오류 전파는 history_restore.rs와 분리된 tests로 이관
- 토큰: main이 추가한 --z-chrome-drag, 토글 누름 배율, 탭 드래그 모션 토큰은 base.css,
  --ui-guide-activity, --ui-tab-socket-*는 dark.css/light.css에 라이트 값과 함께 추가
- main이 투명도 축소 글래스 폴백을 제거해 *-reduced 토큰과 해당 계약 테스트를 정리하고,
  glass·테마 파리티 계약 테스트를 __tests__/rendering으로 이동
- caption/handle 토큰 이관을 분리된 PluginSettingsForm, BatchPanelHeader,
  SingleMappingSection, CounterAnimation 하위 컴포넌트, GooeyThumb(color/),
  pluginSettingsDialogContent, GridSelectionOverlays에 다시 적용
- UpdateModal 접근성 이름은 main의 동일 수정과 테스트를 채택하고 중복 테스트 제거
- 2.0.0 릴리스 노트 크레딧은 main의 CHANGELOG 통합본과 수정본을 유지

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
분기 이후 main에 추가된 스프라이트 UI가 다크 전용 값을 써 라이트 캔버스에서 묻히던 부분

- 이미지 없는 스프라이트 자리표시자 기본색을 --ui-canvas-placeholder 토큰으로 교체
  (다크 값은 기존과 동일, 라이트는 잉크 계열)
- 자세 편집 팝업의 "키 요소 없음" 안내를 읽기용 caption 위계로 변경

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
테마 구독 effect가 redrawWaveformStatic을 의존성에서 빠뜨려 react-hooks 경고가 나던 부분.
함수가 바뀌면 구독을 다시 걸도록 의존성에 포함

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
dmn.settings.get/update가 다루는 SettingsState에 앱 UI 테마(system/light/dark)가
추가된 것을 en/ko 문서에 반영

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
#204가 #148보다 먼저 병합될 예정이라 최종 동기화를 한 번으로 끝내기 위해 함께 합침

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@lee-sihun
lee-sihun merged commit 193a3cb into main Oct 21, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants