Motion
피드백, 공간 관계와 진행을 설명할 때만 움직임을 사용합니다.
목적
Dot의 motion은 상태 변화, 공간 관계, 진행 상황을 이해하게 한다. 움직임 자체로 즐거움을 만들기보다 무엇이 바뀌었고 어디에서 왔으며 다음에 무엇을 할 수 있는지 설명한다.
- Flexible: 입력 방식, 성능, motion 선호에 맞게 강도를 조절하되 상태 의미는 유지한다.
- Link: trigger와 결과, 이전과 다음 위치, 처리와 완료를 공간적으로 연결한다.
- Glow: 불확실한 순간의 방향 안내에만 사용하고 상시 움직임으로 업무를 지배하지 않는다.
Motion을 사용하는 조건
다음 중 하나를 설명할 때만 사용한다.
- 상태가 바뀌었다.
- content가 어디에서 열리고 어디로 돌아가는지 보여준다.
- selection과 detail 사이의 관계를 유지한다.
- 실제 작업이 진행 중임을 알린다.
- 사용자의 행동 결과가 특정 영역에 반영됐다.
motion이 없어도 정보와 interaction을 이해할 수 있어야 한다.
Duration
| 범위 | duration | 사용 |
|---|---|---|
| interaction | 120–180ms | hover, focus, selected, 작은 상태 변화 |
| overlay | 180–240ms | Dialog, Sheet, Popover 열림·닫힘 |
현재 제공되는 기본 animation은 다음 범위에 있다.
-
fade-in: 180ms ease-out -
slide-in-from-top: 180ms ease-out, 6px 이동 -
accordion open/close: 200ms ease-out
-
짧은 상태는 즉각적으로 느껴지되 변화가 식별될 정도만 움직인다.
-
큰 surface는 작은 control보다 약간 긴 duration을 사용할 수 있다.
-
화면마다 새로운 duration을 만들지 않는다.
-
같은 component의 open과 close는 관계를 이해할 수 있는 일관된 timing을 사용한다.
-
motion을 느리게 만들어 중요도를 표현하지 않는다.
Easing과 이동 거리
- 등장과 overlay는 최종 위치에서 자연스럽게 멈추는 ease-out을 기본으로 한다.
- 사라짐은 사용자의 다음 행동을 지연하지 않는다.
- 작은 component 이동은 4–8px 범위의 짧은 거리로 충분하다.
- 멀리 날아오거나 크게 확대되는 transition을 일반 제품 UI에 사용하지 않는다.
- layout 전체를 움직이기보다 opacity와 transform으로 의미 있는 element만 전환한다.
- spring, bounce, overshoot는 업무 결과와 오류를 가볍게 만들 수 있으므로 사용하지 않는 것을 기본으로 한다.
상태 변화
Hover와 focus
- hover는 pointer 사용자를 위한 보조 피드백이며 필수 action을 새로 공개하지 않는다.
- focus-visible은 animation보다 명확한 ring이 우선이다.
- hover와 focus의 transition이 control 반응을 늦추지 않는다.
- selected와 active는 transition 후에도 지속되는 상태로 구분한다.
Loading과 progress
- 일반 content 최초 loading은 최종 구조와 닮은
Skeleton을 사용할 수 있다. - button loading은 label을
저장 중…처럼 유지하고 중복 실행을 막는다. - 정확한 progress를 알 수 있을 때만 determinate 표현을 사용한다.
- background refresh는 기존 content를 지우지 않고 작은 상태로 알린다.
- 무한 spinner를 화면의 유일한 설명으로 사용하지 않는다.
Success와 error
- 성공 animation은 결과 확인을 보조할 수 있지만 다음 action을 지연하지 않는다.
- error를 shake, flash, 반복 진동으로 표현하지 않는다.
- field error는 문장, 관계, focus로 설명하고 animation은 필요하지 않다.
- 일부 성공은 단일 축하 animation보다 성공·실패 범위를 구조화한다.
Overlay motion
- Dialog와 Sheet의 움직임은 trigger와 layer 관계를 이해하게 한다.
- Popover는 짧은 fade 또는 작은 위치 이동으로 충분하다.
- Tooltip은 content를 읽기 전에 과도한 delay나 animation을 만들지 않는다.
- overlay가 닫히면 focus가 trigger로 돌아가므로 motion 종료와 focus timing이 충돌하지 않게 한다.
- nested overlay animation을 연속으로 쌓지 않는다.
- screen edge에서 들어오는 Sheet는 실제 edge 관계와 방향이 일치해야 한다.
DotMotion
DotMotion은 별도 motion entrypoint에서 가져오며 실제 AI 맥락에만 사용한다.
processing
- AI 생성, 채점, 분석이 실제로 진행 중일 때 사용한다.
- 일반 API 요청, page loading, 자동 refresh에는 사용하지 않는다.
- 무엇을 처리하는지 설명하는
ariaLabel과 시각 text를 제공한다. - 작업이 끝나면 motion도 끝내고 결과 상태로 전환한다.
avatar
- AI DOT의 실제 발화나 안내가 진행되는 동안 사용한다.
- 대기 화면의 장식적 무한 반복이나 일반 profile image로 사용하지 않는다.
- 발화·안내가 끝나면 정적 상태로 돌아간다.
Fallback
- viewport 근처에서만 renderer를 불러오는 lazy behavior를 유지한다.
- reduced motion, loading, renderer failure에서는 정적 fallback을 제공한다.
- motion이 실패해도 text 상태와 주요 action은 유지한다.
- 제품에서 JSON expression이나 asset path를 직접 수정해 우회하지 않는다.
Character와 Glow
- 2D motion 표현은 제품 안의 처리·답변·안내처럼 기능에 가까운 맥락에 적합하다.
- 3D character는 넓고 드문 브랜드 맥락이며 일반 transition 요소가 아니다.
- 캐릭터의 형태, 색, 요소 관계, clear space를 animation을 위해 변형하지 않는다.
- Glow를 움직이는 background나 항상 pulsating하는 focus로 사용하지 않는다.
- 다음 방향을 안내해야 하는 짧고 의미 있는 순간에만 brand motion을 검토한다.
Scroll과 layout motion
- 자동 scroll은 사용자의 위치를 잃게 할 수 있으므로 오류, 새 선택, 직접 요청처럼 이유가 명확할 때만 한다.
- streaming AI 결과가 새 내용마다 viewport를 밀어내지 않게 한다.
- list 갱신 시 row가 갑자기 재정렬되면 변경 원인과 현재 selection을 보존한다.
- drag-and-drop에는 keyboard 대안을 제공하고 drop 결과를 알린다.
- height animation이 긴 content를 가리거나 focus target을 잘라내지 않게 한다.
- page route transition이 제목 focus와 읽기 시작을 지연하지 않게 한다.
Reduced motion
.dot-theme는 prefers-reduced-motion: reduce에서 다음을 적용한다.
- scroll behavior를 즉시 전환한다.
- animation duration을 사실상 제거한다.
- 반복 횟수를 1회로 제한한다.
- transition duration을 사실상 제거한다.
제품 component도 이 경계를 우회하지 않는다.
- motion 제거 후에도 상태가 즉시 최종 모습으로 나타나야 한다.
- 처리 상태는 text,
aria-busy, static indicator로 유지한다. - 공간 관계가 중요한 disclosure는 expanded state와 heading 구조로 보완한다.
- 자동 재생 video나 별도 canvas motion이 있다면 독립적인 pause/stop 정책을 검토한다.
상태와 접근성
- motion만으로 성공, 오류, 선택, 진행을 전달하지 않는다.
- 진행 상태에는 text와 필요한 live region을 제공한다.
- flash, rapid blink, 반복 진동을 사용하지 않는다.
- focus 이동과 animation이 동시에 사용자를 다른 위치로 끌지 않는다.
- screen reader announcement는 visual animation frame이 아니라 의미 있는 상태 변경에 맞춘다.
- pause, cancel, stop이 필요한 장시간 작업은 keyboard로도 조작할 수 있어야 한다.
- motion asset의 대체 text는 animation 형태보다 실제 작업 상태를 설명한다.
예외와 피해야 할 사용
- 모든 hover와 mount에 animation을 넣지 않는다.
- 단순 중요도를 pulse, bounce, shake로 표현하지 않는다.
- error에 반복적인 움직임을 사용하지 않는다.
- 알 수 없는 진행률을 animation 속도나 percent로 꾸미지 않는다.
- 일반 loading에
DotMotion processing을 사용하지 않는다. - 캐릭터와 Glow를 장식적으로 무한 반복하지 않는다.
- reduced-motion CSS를 component override로 무효화하지 않는다.
- animation이 끝날 때까지 action과 focus를 막지 않는다.
검토 질문
- motion이 상태, 공간 관계, 진행 중 무엇을 설명하는가?
- motion을 제거해도 같은 정보와 action을 이해할 수 있는가?
- duration이 interaction 120–180ms, overlay 180–240ms 체계 안에 있는가?
- 이동 거리와 easing이 component 크기와 관계에 비례하는가?
- loading, success, error를 text와 구조로도 전달하는가?
- DotMotion이 실제 AI 생성·채점·분석 또는 발화에만 쓰이는가?
- 처리 완료와 함께 반복 motion이 끝나는가?
- focus, scroll, selection이 animation 때문에 이동하거나 사라지지 않는가?
- reduced motion에서 static fallback과 상태 문장이 유지되는가?
- Glow와 character motion이 다음 방향을 밝히는 드문 순간에만 쓰였는가?