본문으로 건너뛰기

색 역할

zs-ui는 브랜드 시드 색으로 Material 3 색 역할을 계산하고, 용도가 드러나는 이름(background·text·border·surface1~surface5·primary …)으로 내보냅니다. 앱 코드는 숫자 톤이 아니라 색 역할로 색을 고르고, 라이트·다크·고대비에서는 같은 역할이 다른 값을 갖습니다.

const { colors } = useTheme();

<View style={{ backgroundColor: colors.surface3 }}>
<Text style={{ color: colors.text }}>본문</Text>
</View>

만드는 방법​

ThemeProvider는 시드 색, 모드, 대비 수준으로 createThemeColors를 호출합니다.

  • primary는 채움 강조, onPrimary는 그 위의 글자·아이콘입니다.
  • 밝은 시드의 primary는 채움에 쓰고, 작은 선택 표시에는 대비를 보정한 primaryMark를 씁니다.
  • 배경·글자·선은 기본 무채색입니다. neutral 시드로 색조를 지정할 수 있습니다.
  • secondary·tertiary는 생략하면 primary에서 파생합니다. 상태 색은 기본 시드를 사용합니다.
  • 다크 모드와 고대비에서는 같은 색 역할의 값이 자동으로 바뀝니다.

DEFAULT_COLORS​

colors를 넘기지 않거나 일부만 넘기면 빈 자리를 기본 시드로 채웁니다. secondary·tertiary·neutral은 기본 시드가 없습니다(secondary·tertiary는 primary에서 만들고, neutral은 무채색입니다).

시드기본값
primary#ffa20d
error#ff4d6f
success#4fd165
warning#ffd700
info#4981ff

색 규칙 — 채움과 얇은 표시​

primary는 채움 색입니다. 글자나 얇은 선에는 쓰지 않습니다. 밝은 시드의 primary는 흰 바탕 위 글자·선으로 2:1 남짓이라(기본 호박 2.0:1) 읽히지 않습니다.

쓰임색zs-ui 컴포넌트
넓은 채움 강조primary 면 + onPrimary 글자·아이콘ZSButton filled, 선택된 ZSChip, ZSSwitch 켬, 스낵바 동작 버튼. ZSCheckbox 켬·고른 ZSRadioGroup 라디오도 primary 면이지만 체크·점은 흰색(플랫폼 기본 컨트롤처럼)
얇은 선택 표시(3:1 필요)textZSTextField 포커스 테두리·라벨·커서, Android ZSMenu 체크
글자 버튼·링크textZSButton text·outlined(color="primary"), 헤더 버튼·뒤로가기
주색 표시(아이콘·선택 라벨, 3:1)primaryMarkZSTabNavigator 선택 아이콘·라벨, ZSCalendar 선택 카드 위 숫자
브랜드 색조 글자(4.5:1)onPrimaryContaineruseStackTheme({ tint: 'primary' })(밝은 시드일 때)

선택 상태는 면 색 하나에 기대지 않습니다. 고른 칩·세그먼트·라디오 줄·달력 숫자는 굵기·체크로도 상태를 알립니다. 예외로 ZSTabNavigator는 선택 아이콘·라벨을 주색 표시색 primaryMark로 칠합니다(Android 떠 있는 바은 회색 선택 캡슐이 함께 알립니다).

색 역할 목록 — ColorName​

ThemeColors의 키(ColorName)이고, 모든 값은 #rrggbb 문자열입니다.

강조·상태 (팔레트 색마다 4개)​

팔레트 색 (PaletteColor)mainoncontaineronContainer
primaryprimaryonPrimaryprimaryContaineronPrimaryContainer
secondarysecondaryonSecondarysecondaryContaineronSecondaryContainer
tertiarytertiaryonTertiarytertiaryContaineronTertiaryContainer
errorerroronErrorerrorContaineronErrorContainer
successsuccessonSuccesssuccessContaineronSuccessContainer
warningwarningonWarningwarningContaineronWarningContainer
infoinfoonInfoinfoContaineronInfoContainer
neutral(회색)neutralonNeutralneutralContaineronNeutralContainer
  • main은 강한 강조(채운 버튼·선택 면·위험 동작), container는 덜 강한 강조(배너 배경)입니다.
  • on*은 그 색 위의 글자·아이콘입니다. 같은 행끼리만 짝지어 씁니다.

배경·글자·선​

역할용도
background화면 배경(페이지)·입력 칸 면 — 라이트 흰색, 다크 #131313
surface1페이지 면 — 두 모드 모두 background와 같습니다. 라이트 Alert·elevated 카드
surface2묶음 목록·칩·세그먼트 트랙·filled 카드, Android 시트 배경
surface3눌림 면, 다크에서 떠 있는 면(Alert·elevated 카드·흐림 막), Android 내비게이션 바·메뉴
surface4스켈레톤 자리 표시, 다크 세그먼트 선택 칸, Android 진행 표시 상자·스위치 꺼짐 트랙·탭 선택 캡슐
surface5비활성 채움
text본문 글자·아이콘, 얇은 선택 표시(색 규칙)
textSecondary라벨·보조 글자·비선택 아이콘·일정 점
border구분선·칩·세그먼트 테두리처럼 장식적인 선
borderStrong입력 칸 테두리처럼 경계가 중요한 선
backgroundInverse반전 배경(툴팁)
textInverse반전 배경 위 글자·아이콘
primaryInverse반전 배경 위 강조
shadow그림자 색
backdrop모달 뒤를 덮는 색(불투명도는 OPACITY.backdrop)

surface1~surface5는 숫자가 클수록 페이지와 멀어지는 면입니다. 라이트는 흰 페이지 위에서 5로 갈수록 짙어지고, 다크는 #131313 페이지 위에서 5로 갈수록 밝아집니다. 높낮이는 이 다섯 단계로 먼저 나타내고, 그림자는 떠 있는 요소에만 씁니다(토큰).

Android Compose 스킴과의 대응​

Android Compose 컨트롤은 zs-ui 색 역할로 덮은 M3 스킴을 받습니다(아래 네이티브 컨트롤). M3 문서나 Material Theme Builder 결과와 맞춰 볼 때 씁니다. 강조·상태 색은 M3 이름 그대로입니다.

zs-uiM3 역할
backgroundbackground·surface
surface1~surface5surfaceContainerLowest·Low·(기본)·High·Highest
surface5surfaceVariant
textonSurface·onBackground
textSecondaryonSurfaceVariant
borderoutlineVariant
borderStrongoutline
backgroundInverseinverseSurface
textInverseinverseOnSurface
primaryInverseinversePrimary
backdropscrim

surfaceBright·surfaceDim은 모드마다 가장 밝은·어두운 면(라이트 background·surface5, 다크 surface5·background)이고, surfaceTint는 투명입니다 — 면에 primary를 섞지 않습니다.

네이티브 컨트롤에 넘기는 테마​

zs-ui가 감싼 시스템 컨트롤과 오버레이는 앱 테마의 색 모드를 받습니다. 버튼 색·모서리 같은 브랜드 모양은 넘기지 않습니다.

iOSAndroid
대상SwiftUI 컨트롤(ZSSwitch·ZSSelect)Compose 컨트롤(ZSSwitch·ZSSelect·ZSMenu), 시트·진행 표시 — ZSCheckbox·ZSRadioGroup은 두 플랫폼 공통 SVG라 테마 색을 바로 씁니다
강조 색SwiftUI 기본 tint는 text입니다(tint가 글자·체크·커서 같은 얇은 표시에 쓰이기 때문). 켬 트랙을 채우는 ZSSwitch는 컨트롤에 primary tint를 직접 겁니다. ZSSelect 버튼 글자는 고른 값 text, 선택 전 textSecondaryprimary 시드(seedColor)로 만든 Compose 스킴 위에 zs-ui 색 역할을 덮습니다(대응표). 컨트롤마다도 색을 넘깁니다 — 켠 스위치 트랙 primary, 포커스 테두리·라벨·커서 text, 꺼진 스위치 썸·테두리 textSecondary·트랙 surface4, 진행 표시 textSecondary·상자 surface4, 다크 시트 뒤 막 backdrop 52%(라이트 32%)

iOS 메뉴는 색 모드만 받고 시스템 색으로 그립니다(메뉴의 destructive 항목 아이콘만 error). iOS 시트는 테마 색을 받지 않고, 색 모드는 syncNativeAppearance로 앱 테마를 따릅니다.

createThemeColors​

function createThemeColors(
seeds: ThemeColorOptions,
options: { mode: 'light' | 'dark'; contrastLevel: number },
): ThemeColors;

ThemeProvider 밖에서 같은 규칙으로 색을 미리 계산할 때 씁니다(예: 스플래시·위젯 색 맞추기, 디자인 토큰 내보내기, 테스트). contrastLevel은 0 표준 · 0.5 중간 · 1 높음입니다.

import { createThemeColors, DEFAULT_COLORS } from '@0610studio/zs-ui';

const dark = createThemeColors({ ...DEFAULT_COLORS, primary: '#2f6bff' }, { mode: 'dark', contrastLevel: 0 });
dark.background;

유틸​

getPaletteColors​

팔레트 색 하나의 4개 색을 묶어 반환합니다. ZSButton·ZSChip·ZSBanner가 쓰는 규칙과 같습니다.

import { getPaletteColors, useTheme, type PaletteColor } from '@0610studio/zs-ui';

const { colors } = useTheme();
const { main, onMain, container, onContainer } = getPaletteColors(colors, 'success');

PaletteColor는 'primary' | 'secondary' | 'tertiary' | 'error' | 'success' | 'warning' | 'info' | 'neutral'입니다.

resolveColor​

색 역할이면 그 값을, 아니면 문자열을 그대로 반환합니다. 색 역할을 받는 prop(ZSText의 color, 여러 컴포넌트의 backgroundColor 등)이 이 규칙을 씁니다. 그 prop의 타입은 ColorName | (string & {})라 역할 이름이 자동 완성되고 '#111827'·'rgba(0, 0, 0, 0.5)'도 그대로 받습니다.

resolveColor(colors, 'textSecondary');
resolveColor(colors, '#111827');
resolveColor(colors, undefined);

withOpacity​

#rrggbb에 불투명도(0~1)를 붙여 #rrggbbaa로 만듭니다. 6자리 hex가 아니면 그대로 반환합니다.

import { OPACITY, withOpacity } from '@0610studio/zs-ui';

withOpacity(colors.text, OPACITY.disabled);
withOpacity(colors.backdrop, OPACITY.backdrop);

ColorMode·ThemeColors·ColorName·PaletteColor·ThemeColorOptions 타입을 내보냅니다.

관련 문서​