모션
움직임은 상태가 바뀌었다는 것을 알리는 데만 쓴다. 나타날 때는 빠르게 시작해 부드럽게 멈추고(out), 사라질 때는 천천히 시작해 빠르게 사라진다(in). 시간은 대부분 130~240ms다.
곡선 2종#
out 나타날 때in 사라질 때| 이름 | 앱 코드 | CSS | 쓰는 때 |
|---|---|---|---|
out | Easing.out(Easing.cubic) | cubic-bezier(0.33, 1, 0.68, 1) | 나타날 때. 처음에 빠르고 끝에서 부드럽게 멈춘다. |
in | Easing.in(Easing.quad) | cubic-bezier(0.11, 0, 0.5, 0) | 사라질 때. 천천히 시작해 빠르게 사라진다. |
시간#
| 움직임 | 시간 | 곡선 | 쓰는 곳 |
|---|---|---|---|
| 시트 열림 | 240ms | out | Sheet. 어둠막은 투명해졌다 나타나고 시트는 아래에서 올라온다. |
| 시트 닫힘 | 180ms | in | Sheet |
| 메뉴 시트 열림 | 220ms | out | dialog.menu |
| 중앙 대화상자 열림 | 180ms | out | dialog.alert, dialog.confirm, dialog.choose. 0.96배에서 1배로 커지며 나타난다. |
| 대화상자·메뉴 닫힘 | 130ms | in | dialog 전체 |
| 끌어내리다 놓음 | 160ms | 기본 | Sheet와 메뉴 시트. 닫힐 만큼 끌지 않았을 때 제자리로 돌아온다. |
| 토스트 나타남 | 스프링(damping 18) | 스프링 | toast. 아래에서 위로 떠오른다. |
| 토스트 사라짐 | 160ms | 기본 | toast |
| 토스트 표시 시간 | 2400ms (되돌리기 버튼이 있으면 6000ms) | — | toast |
| 로딩 막대 깜빡임 | 700ms씩 반복 | 기본 | Skeleton. 투명도 0.5와 1 사이를 오간다. |
| 링 차트 채움 | 900ms (150ms 지연) | out | AnimatedRing |
| 숫자 올라감 | 900ms (150ms 지연) | out | useCountUp |
| 문제 진행 칸 채움 | 380ms | out | SegmentedProgress |
| 밀어서 삭제: 화면 밖으로 | 200ms | 기본 | SwipeRow. 110 이상 밀고 놓았을 때. |
| 밀어서 삭제: 제자리로 | 스프링(damping 18) | 스프링 | SwipeRow |
| 이미지 확대 되돌리기 | 180~220ms | 기본 | ZoomableImage. 더블탭 확대 220ms, 되돌리기 180~200ms. |
| 화면 모드 바뀜: 덮기 | 90ms | 기본 | ThemeFade. 새 배경색으로 화면을 덮는다. |
| 화면 모드 바뀜: 걷기 | 300ms (60ms 지연) | 기본 | ThemeFade. 새 모드가 그려진 뒤 덮개를 걷는다. |
- 새 움직임의 시간은 120~300ms 안에서 정한다. 나타나는 동작이 사라지는 동작보다 길다(예: 시트 240ms 대 180ms).
- 움직임은 크기(
scale), 투명도(opacity), 위치(translate)만 바꾼다. 레이아웃 크기를 애니메이션하지 않는다. - 목록 항목이 차례로 나타나는 효과와 계속 도는 장식 움직임은 쓰지 않는다. 앱에서 계속 반복되는 것은 로딩 막대(
Skeleton) 하나뿐이다.
웹에서 쓰기
.sheet { animation: slide-up 240ms var(--tds-ease-out) both; }
.sheet[data-closing] { animation: slide-down 180ms var(--tds-ease-in) both; }눌림 표현#
눌렀을 때의 반응은 컴포넌트마다 정해져 있다. Android에서는 물결(ripple)이 눌림 표시를 대신하고, 투명도와 배경색 변화는 지워진다(크기 변화는 유지). 자세한 내용은 Pressable 문서에 있다.
| 컴포넌트 | 눌렀을 때 |
|---|---|
PrimaryButton | 0.985배 |
CircleButton | 0.96배 |
탭 바 가운데 버튼 | 0.95배 |
SecondaryButton, SmallButton, WellRow, FilterPill | 투명도 0.8 |
AmberButton, Card | 투명도 0.85 |
OptionRow, ChoiceCard | 투명도 0.9 |
TextButton, IconButton | 투명도 0.6 |
SettingsRow, 메뉴 행 | 배경이 pressed 색으로 바뀜 |
진동#
진동은 선택, 눌림, 결과를 손으로 느끼게 하는 보조 수단이다. 진동만으로 정보를 전달하지 않는다. 진동이 꺼진 기기에서는 아무 일도 일어나지 않는다.
| 함수 | 느낌 | 쓰는 때 |
|---|---|---|
haptic.select | 가벼운 선택 진동 | 탭, 칩, 슬라이더 같은 선택이 바뀔 때 |
haptic.tap | 가벼운 눌림 | PrimaryButton, 대화상자 버튼을 누를 때 |
haptic.firm | 중간 세기 눌림 | 길게 눌러 열기·끌기를 시작할 때 |
haptic.success | 성공 알림 진동 | 정답을 맞혔을 때, 길게 눌러 확정했을 때 |
haptic.warning | 경고 알림 진동 | 문제를 틀렸을 때 |
haptic.error | 오류 알림 진동 | 확인 문제를 틀렸을 때, 신고 전송이 실패했을 때 |
동작 줄이기#
동작 줄이기 대응
@media (prefers-reduced-motion: reduce) {
.sheet { animation: none; }
}