모션 계층 및 호버 레시피은(는) 무엇을 하나요?
17개의 프로토타입 앱에서 입증된 두 가지 아이디어:
- 지속 시간은 구성 요소별 숫자가 아니라 하나의 척도(scale)입니다. 눈은 공유된 템포를 하나의 제품으로 읽습니다. 작은 것은 더 빠르게 움직입니다.
- 호버는 기하학을 부드럽게 움직입니다. 행 안으로 자라는 하이라이트, 도착하는 화살표, 가는 방향으로 기울어지는 슬쩍 밀기, 다음 상태로 굴러가는 레이블. 색상만 바뀌는 호버는 스위치가 켜지듯 읽힙니다.
파일
references/recipes.css: Tailwind v4@theme토큰 및@utility레시피.references/timing.ts: Motion 및 WAAPI를 위한 동일한 계층.references/swap.tsx:IconSwap및LabelSwap(React).
계층
| 계층 | ms | 용도 |
|---|---|---|
tap | 100 | 아이콘 교체, 누름 |
pop | 150 | 메뉴, 팝오버 또는 툴팁 열기 |
hover | 200 | 포인터에 반응하는 행 또는 컨트롤 |
card | 300 | 카드 들림, 목록 안정화, 페이지 전환 |
layout | 500 | 패널 접힘, 페이지 재배치 |
- 진입은 ease-out(
cubic-bezier(0.22,1,0.36,1))입니다. 종료는 ease-in이며 한 계층 더 짧게 실행됩니다. - 두 요소가 자리를 교환할 때, 나가는 요소는 즉시 사라지고 들어오는 요소는
delay-handoff(50ms) 후에 시작됩니다. - 값 트윈(카운터, 막대 채우기, 차트 선 그리기)은 더 오래 실행될 수 있습니다. 눈이 데이터를 따라가기 때문입니다.
- 의도적인 스프링은 유지하세요.
마이그레이션: 모든 임시 지속 시간을 가장 가까운 계층에 매핑합니다.
| 임시 값 | 계층 |
|---|---|
| 0.12 | tap |
| 0.15–0.18 | pop |
| 0.2–0.24 | hover |
| 0.28–0.35 | card |
| 0.4–0.5 | layout |
거의 모든 곳에서 화면상 타이밍이 20ms 미만으로 변경될 것으로 예상됩니다.
레시피 (요소당 하나)
hover-grow(네비게이션 행, 링크 행):- 하이라이트는
::before로 시작하여 처음에는 안쪽으로 들어가고(3px x 6px) 투명하다가, 페이드 인되면서 전체 행으로 부풀어 오릅니다. :focus-visible,data-state=open및aria-current=page에도 표시됩니다.- 정사각형 또는 브루탈리스트 디자인(Carbon 스타일)은 대신 평평한 하이라이트를 유지해야 합니다.
- 하이라이트는
trail(링크 행, "요금제 보기"):- 후행 글리프가 절반 크기로 투명하게 시작하여 부모
.group이 호버되거나 포커스될 때 앞쪽 가장자리에서 커집니다. trail-out(왼쪽 아래에서 자람) +arrow-up-right는 앱을 떠나는 링크를 표시합니다.
- 후행 글리프가 절반 크기로 투명하게 시작하여 부모
nudge/nudge-back(슬쩍 밀기, "모두 보기", 뒤로 가기 링크): 목적지 쪽으로 2px 기울임.lift(클릭 가능한 카드):card계층 동안 한 단계 더 밝은 표면과 한 단계 더 깊은 그림자.- 절대 translate 사용 금지: 커서 아래에서 튀는 카드는 사용자가 조준하는 대상을 움직입니다.
scroll-fade(스크롤 창):- 마스크 기반 가장자리 페이드, 스크롤 가능한 쪽에만 적용됩니다. 컨테이너 자체의 스크롤 타임라인으로 구동되며 배경색이 필요 없습니다.
- 지원하지 않는 브라우저는 페이드 없이 표시됩니다.
IconSwap(메뉴에서 닫기로, 복사에서 체크로, 해에서 달로):- 나가는 글리프는 축소되고 -22° 기울이며 ease-in으로 페이드 아웃됩니다.
- 들어오는 글리프는 핸드오프 지연 후에 따라옵니다.
- 둘 다 마운트된 상태로 유지되므로 중간에 깔끔하게 역전됩니다.
LabelSwap("링크 복사"에서 "복사됨"으로, "접기"에서 "펼치기"로):- 두 레이블이 하나의 그리드 셀에 위치하므로 너비 점프가 없습니다.
- 숨겨진 레이블은
transition-discrete를 통해invisible이 되어, 보조 기술이 현재 레이블만 인식합니다.
함정
scroll-fade를 자기 자신을 애니메이션하는 요소에 사용 (Radix 메뉴, 팝오버 또는 선택 콘텐츠)은 해당 요소의 종료 애니메이션을 대체합니다. Radix는 끝나지 않는 종료를 기다리며 메뉴가 열린 상태로 유지됩니다. 페이드는 내부의 스크롤 가능한 자식에 적용하세요.scroll-fade는 테두리와 그림자도 마스킹합니다. 테두리가 있는 카드에 직접 적용하지 말고 내부 스크롤러에 적용하세요.- Tailwind v4의 사용자 정의
duration-*유틸리티는--tw-duration도 설정해야 합니다. 그렇지 않으면 같은 요소의transition-[…]유틸리티가 정렬 순서에 따라 우선합니다. - line-height를 전달하는 명명된 타입 스텝 (
--text-meta--line-height)은 부모의 leading을 상속하는 임의 크기를 대체할 때 변환된 모든 줄을 1px씩 이동시킵니다. 중간 스텝에는 자체 line-height를 지정하지 마세요. - 호버를
@media (hover: hover)뒤에 게이트하세요.:focus-visible에서 동일한 상태를 표시하고prefers-reduced-motion을 존중하세요(Motion:<MotionConfig reducedMotion="user">).