본문으로 건너뛰기

토큰

zs-ui 컴포넌트가 함께 쓰는 모서리·모션·상태·터치 영역·그림자 기준입니다. 커스텀 UI에도 같은 값을 쓰면 zs-ui 컴포넌트와 모양이 맞습니다.

모서리 — RADIUS · radiusStyle​

모서리 반경(pt·dp)입니다.

토큰값M3 shape scale
none0none
xs4extraSmall
sm8small
md12medium
lg16large
xl20largeIncreased
2xl28extraLarge
3xl32extraLargeIncreased
4xl48extraExtraLarge
full9999full

숫자로 시작하는 키는 RADIUS['2xl']처럼 대괄호로 읽습니다.

토큰zs-ui 쓰임
fullZSButton·ZSChip·ZSSegmentedControl·스낵바·Android 떠 있는 탭 바
md (12)ZSTooltip
lg (16)ZSTextField·Android ZSSelect 필드·ZSCard 기본·iOS 진행 표시 상자
xl (20)ZSBanner
3xl (32)Alert

radiusStyle(token)은 모서리 스타일을 반환합니다. iOS는 시스템 컨트롤과 같은 연속 곡률(borderCurve: 'continuous')을 함께 넣습니다(none·full 제외).

import { View } from 'react-native';
import { radiusStyle, useTheme } from '@0610studio/zs-ui';

const { colors } = useTheme();
<View style={[radiusStyle('lg'), { backgroundColor: colors.surface3, padding: 16 }]} />;

RadiusToken 타입(RADIUS의 키)을 내보냅니다.

모션 — spring · timing​

위치·크기가 바뀌는 움직임(move)은 spring, 색·투명도가 바뀌는 움직임(fade)은 오버슈트 없는 spring 또는 짧은 timing을 씁니다. 모든 설정은 시스템 '동작 줄이기'를 따릅니다(켜져 있으면 끝값으로 바로 갑니다).

springConfig​

function springConfig(kind: MotionKind, speed?: MotionSpeed): WithSpringConfig;
import { withSpring } from 'react-native-reanimated';
import { springConfig } from '@0610studio/zs-ui';

offset.value = withSpring(target, springConfig('move', 'fast'));
플랫폼값
iOSSwiftUI 기본 spring(spring(duration: 0.5, bounce: 0))을 normal로 — duration: IOS_SPRING_DURATION[speed], dampingRatio: 1. fade는 항상 fast(350ms)
AndroidANDROID_SPRING[kind][speed]의 dampingRatio·stiffness(Compose ExpressiveMotionTokens). mass: 1, damping = dampingRatio × 2√stiffness

IOS_SPRING_DURATION​

{ fast: 350, normal: 500, slow: 700 }(ms). normal은 SwiftUI 기본값이고 fast·slow는 zs-ui가 정한 값입니다(HIG에 숫자 토큰이 없습니다).

ANDROID_SPRING​

kindfastnormalslow
move (M3 spatial, 오버슈트 있음)0.6 / 8000.8 / 3800.8 / 200
fade (M3 effects, 오버슈트 없음)1 / 38001 / 16001 / 800

(dampingRatio / stiffness)

timingConfig · DURATION​

페이드처럼 시간 기반이 필요한 fade 움직임에 씁니다. DURATION은 { fast: 150, normal: 200, slow: 300 }(ms)입니다.

import { withTiming } from 'react-native-reanimated';
import { timingConfig } from '@0610studio/zs-ui';

opacity.value = withTiming(1, timingConfig('fast'));

MotionKind·MotionSpeed 타입을 내보냅니다.

상태 — OPACITY​

M3 상태 레이어·비활성 불투명도입니다. withOpacity와 함께 씁니다.

키값용도
disabled0.38비활성 글자·아이콘 (text 38%)
disabledBackground0.12비활성 배경·외곽선 (text 12%)
hover0.08
focus0.1
pressed0.1누름 표시 (ZSPressable)
dragged0.16
backdrop0.32모달 뒤를 덮는 backdrop 색
disabledView0.5안쪽 색을 모르는 영역 전체를 흐리게 합니다(zs-ui 값). 색을 아는 컴포넌트는 disabled·disabledBackground를 씁니다
const { colors } = useTheme();
const disabledText = withOpacity(colors.text, OPACITY.disabled);

최소 터치 영역 — MIN_TOUCH_TARGET​

{ ios: 44, android: 48 } — iOS 44pt, Android 48dp. ZSPressable은 보이는 크기가 이보다 작으면 hitSlop을 자동으로 넓혀 이 크기를 채웁니다.

그림자 — shadow​

그림자 단계입니다. 높이(dp)는 M3 elevation 05 단계 값 그대로입니다. 표면 높낮이는 surface1surface5로 먼저 나타내고, 그림자는 툴팁·떠 있는 카드처럼 실제로 떠 있는 요소에만 씁니다.

토큰nonexssmmdlgxl
SHADOW (dp)0136812
M3 elevation 단계012345
  • useTheme().shadows[token]은 { boxShadow } 스타일입니다(none은 빈 객체). ZSBox shadow가 이 값을 씁니다.
  • createShadows(colors)는 shadow 색으로 단계별 스타일(ShadowStyles)을 만듭니다. colors에 background가 있고 어두운 바탕이면 다크 불투명도(아래)를 씁니다.
  • shadowFor(dp, shadowColor)는 dp 높이를 key·ambient 두 겹 BoxShadowValue[]로 바꿉니다. 단계에 없는 높이가 필요할 때 씁니다.
import { View } from 'react-native';
import { shadowFor, useTheme } from '@0610studio/zs-ui';

const { colors, shadows } = useTheme();

<View style={[{ backgroundColor: colors.surface1, borderRadius: 16 }, shadows.sm]} />;
<View style={{ boxShadow: shadowFor(4, colors.shadow) }} />;

ShadowToken('none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl')·ShadowStyles 타입을 내보냅니다.

관련 문서​