Foundations파운데이션Motion모션

Foundations / New

Motion

Dynamic doesn't mean a screen that never stops moving; it means an experience that responds clearly to what people do. Every motion has a reason and a direction.Dynamic은 항상 움직이는 화면이 아니라, 사용자의 행동에 명확하게 반응하는 경험입니다. 모든 움직임은 이유와 방향을 가집니다.

Three principles세 가지 원칙

01 / Respond

Respond to actions행동에 응답합니다

Motion starts from user input. We don't use decorative motion that loops on its own.움직임은 사용자의 입력에서 시작합니다. 스스로 반복되는 장식 모션은 사용하지 않습니다.

02 / Connect

Show relationships관계를 보여줍니다

Show where an element comes from and where it goes, so people understand how screens connect.요소가 어디서 와서 어디로 가는지 보여줘 화면 사이의 연결을 이해하게 합니다.

03 / Settle

Settle quickly빠르게 자리잡습니다

Start fast and ease out at the end. Never make people wait.시작은 빠르게, 끝은 부드럽게 감속합니다. 사용자가 기다리게 하지 않습니다.

Motion tokens

Motion is defined by three kinds of tokens: curve (easing), time (duration), and spring.움직임은 곡선(easing), 시간(duration), 스프링(spring) 세 가지 토큰으로 정의합니다.

Easing

Pick a token to compare its curve and real movement against linear.토큰을 선택하면 곡선과 실제 움직임을 linear와 비교해 보여줍니다.

expressive
linear (reference)linear (비교)
CSS
transition: transform var(--dy-duration-expressive) var(--dy-ease-expressive);
/* 700ms / cubic-bezier(0.2, 0.8, 0.2, 1) */

Duration

The smaller and more frequent the element, the shorter the motion. Only brand motion runs long.요소가 작을수록, 자주 일어날수록 짧게. 브랜드 모션만 길게 사용합니다.

instantToggles, checks, presses토글, 체크, 눌림100ms
fastHover, focus, small state changeshover, 포커스, 작은 상태 변화160ms
basePanels, tabs, content transitions패널, 탭, 콘텐츠 전환240ms
slowLarge layout changes / dialogs큰 레이아웃 변화 / 다이얼로그400ms
expressiveEntering brand areas / emphasis transitions브랜드 영역 진입 / 강조 전환700ms
brandSymbol join motion (on user request)심볼 결합 모션 (사용자 요청 시)1200ms

Spring & the mingle moment

Spring / mingle

Pull apart, come back together.떼어내도, 다시 만납니다.

Drag either shape of the symbol. When you let go, the mingle spring snaps it back into place. Brand motion isn't decoration that loops forever; it's a moment of coming together that responds to what you do.심볼의 두 형태를 드래그해 보세요. 손을 놓으면 mingle 스프링으로 제자리에 결합합니다. 브랜드 모션은 계속 반복되는 장식이 아니라, 사용자의 행동에 응답하는 결합의 경험입니다.

snappy
stiffness 520 / damping 34Small controls / instant response작은 컨트롤 / 즉각 반응
mingle
stiffness 180 / damping 16Symbol join / attraction심볼 결합 / 끌어당김
gentle
stiffness 110 / damping 20Large elements / parallax대형 요소 / 패럴랙스

Times joined결합 횟수 0

Choreography연출 기준

Do권장

Use enter (decelerate) for elements coming in and exit (accelerate) for elements leaving. Stagger lists 30-60ms apart, and reveal large headlines line by line.들어오는 요소는 enter(감속), 나가는 요소는 exit(가속)를 사용합니다. 목록은 30~60ms 간격으로 순차 등장시키고, 큰 헤드라인은 줄 단위로 드러냅니다.

Don't지양

Avoid hover transitions over 400ms, elements moving in several directions at once, and marquees that loop forever regardless of scrolling.hover마다 400ms 이상 걸리는 전환, 동시에 여러 방향으로 움직이는 요소, 스크롤과 무관하게 무한 반복되는 마퀴는 사용하지 않습니다.

Reduced motion

People who turn on reduced motion in their OS must be able to see the final state without movement or scaling. This site applies it globally with MotionConfig (reducedMotion: user).운영체제에서 동작 줄이기를 설정한 사용자는 이동, 크기 변화 없이 최종 상태를 확인할 수 있어야 합니다. 이 사이트는 전역 MotionConfig(reducedMotion: user)로 이를 적용합니다.

LifeWe found a new connection새로운 연결을 찾았어요Position, scale, and rotation move together.위치, 크기, 회전이 함께 움직입니다.
CSS
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}

Motion tokens in code

CSS / React (motion)
/* CSS */
.panel {
  transition: transform var(--dy-duration-base) var(--dy-ease-standard);
}

// React: values generated from tokens.json
import { spring, ease } from "@/lib/motion";
<motion.div animate={{ x: 0 }} transition={spring.mingle} />
<motion.div animate={{ opacity: 1 }} transition={{ duration: 0.24, ease: ease.enter }} />/* CSS */
.panel {
  transition: transform var(--dy-duration-base) var(--dy-ease-standard);
}

// React: tokens.json에서 생성된 값
import { spring, ease } from "@/lib/motion";
<motion.div animate={{ x: 0 }} transition={spring.mingle} />
<motion.div animate={{ opacity: 1 }} transition={{ duration: 0.24, ease: ease.enter }} />
Things come together.© 2026 DYNGLE / Design system v0.3