Foundations

Motion

사용 예시

시간과 곡선

움직임의 설정이에요. 모든 움직임은 상태, 나타남, 사라짐 3가지 짝 가운데 하나를 써요.

ease-state상태가 바뀔 때
--dur-state150ms
ease-enter나타날 때
--dur-enter200ms
ease-exit사라질 때
--dur-exit150ms
tsx
<span className="transition-transform duration-(--dur-state) ease-state motion-reduce:transition-none" /><span className="transition-transform duration-(--dur-enter) ease-enter motion-reduce:transition-none" /><span className="transition-transform duration-(--dur-exit) ease-exit motion-reduce:transition-none" />

시간과 곡선 바꾸기

전역 CSS에 적으면 그 짝을 쓰는 움직임이 모두 바뀌어요. 시간은 :root, 곡선은 @theme에 적어요.

css
:root { --dur-state: 120ms; }@theme { --ease-state: cubic-bezier(.4, 0, .6, 1); }

상태 전환

상태 짝을 써요. 마우스를 올려 보세요. transition-state 하나가 글자색, 배경색, 그림자, scale을 전환해요.

주문 상세
tsx
<div className="card rounded-r12 text-label px-4 py-3            transition-state hover:ring-2 hover:ring-line-strong">  주문 상세</div>

눌림

상태 짝을 써요. 누르면 press는 overlay를 겹치고 press-shrink는 --scale-press만큼 줄여요. 가로로 긴 요소에는 press만 써요.

tsx
<button type="button"        className="card rounded-r12 text-label px-4 py-3               transition-state press press-shrink">  주문 상세</button>

눌림 바꾸기

줄어드는 정도는 :root에, overlay 색은 라이트와 다크에 따로 적어요. 한 요소만 바꾸려면 그 요소에 시간을 적어요.

css
:root { --scale-press: 0.94; }:root, .light { --pds-pressed-dim: rgba(0, 23, 51, 0.16); }.dark         { --pds-pressed-dim: rgba(209, 209, 253, 0.2); }
tsx
<Button color="neutral" emphasis="outline" className="[--dur-state:80ms]">저장</Button>

자리 옮기기

상태 짝을 써요. 탭을 눌러 보세요. translate는 transition-state에 없어서 옮기는 요소에 직접 적어요.

css
.underline {  transition: translate var(--dur-state) var(--ease-state);}@media (prefers-reduced-motion: reduce) {  .underline { transition: none; }}

나타나고 사라지기

나타남과 사라짐 짝을 써요. 플로팅 요소는 --enter-scale 크기에서 커지며 나타나고, overlay는 투명도만 바뀌어요. data-open과 data-closed가 붙는 요소에는 open:animate-enter closed:animate-exit처럼 붙여요.

tsx
<div className={`bg-bg-overlay z-overlay fixed inset-0 ${open ? 'animate-fade-in' : 'animate-fade-out'}`} /><div  className={`float rounded-r16 text-label z-overlay fixed              left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 px-4 py-3              ${open ? 'animate-enter' : 'animate-exit'}`}>  주문을 접수했어요</div>

획 그리기

나타남 짝을 써요. 복사를 눌러 보세요. 복사 완료처럼 짧은 확인 표시에서 선 하나로 된 svg path에 붙여요.

tsx
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">  <path className="animate-draw motion-reduce:animate-none" d="M4 12l5 5L20 6" /></svg>

동작 줄이기

확대와 축소는 저절로 꺼지고, 이동과 획에는 직접 붙여요. 색과 그림자의 전환은 그대로 둬요.

tsx
<span className="transition-transform ease-state motion-reduce:transition-none" /><path className="animate-draw motion-reduce:animate-none" d="M4 12l5 5L20 6" />

추가 가이드

기존 짝으로 만들기

기존 짝을 쓰면 시간과 곡선을 바꿀 때 함께 바뀌어요.

css
@utility transition-move {  transition: translate var(--dur-state) var(--ease-state);}

새 짝으로 만들기

시간과 곡선을 새로 만들면 그 움직임만 따로 바꿀 수 있어요.

css
:root { --dur-pop: 300ms; }@theme { --ease-pop: cubic-bezier(.34, 1.56, .64, 1); }@utility animate-pop {  animation: enter var(--dur-pop) var(--ease-pop);}

명세

토큰과 유틸리티

토큰과 유틸리티
이름값설명
곡선
ease-statecubic-bezier(.35, 0, .65, 1)상태 전환, 자리 옮기기
ease-entercubic-bezier(0, 0, .15, 1)나타나기, 획 그리기
ease-exitcubic-bezier(.35, 0, 1, 1)사라지기
시간과 크기
--dur-state150ms
--dur-enter200ms
--dur-exit150ms
--enter-scale0.95나타날 때 시작하는 크기. 동작 줄이기에서 1
--scale-press0.97눌린 동안의 크기. 동작 줄이기에서 1
--draw-len24그리는 획의 길이
--pds-pressed-dimrgba(0,23,51,.12), rgba(209,209,253,.14)눌린 동안 겹치는 overlay. 라이트, 다크 순
유틸리티
transition-state글자색, 배경색, 그림자, scale의 전환
press눌린 동안 overlay를 겹쳐요. 손을 뗄 때만 시간이 들어요
press-shrink눌린 동안 --scale-press 크기
animate-enter--enter-scale 크기에서 커지며 나타나요. Popover, Tooltip, Select 목록
animate-exit작아지며 사라져요
animate-fade-in투명도만 바뀌며 나타나요. Dialog와 그 overlay
animate-fade-out투명도만 바뀌며 사라져요
animate-drawsvg path의 획을 그려요
상태 변형
open[data-open]open:animate-enter
closed[data-closed]closed:animate-exit
motion-reduceprefers-reduced-motion: reducemotion-reduce:transition-none