Yugen UI

Foundations

Motion

Chuyển động ngắn và có lý do: cho biết thứ gì vừa xuất hiện, từ đâu tới và đi đâu. Vào chậm dần, ra nhanh dần.

Control nhỏ dùng 100–150ms, bề mặt lớn 200–250ms. Chiều ra luôn ngắn hơn chiều vào.

Token

Bấm ▶ để chạy. Minh hoạ thời lượng chậm ×4 để dễ quan sát.

durationUltraFast

duration-ultra-fast · 50ms

Phản hồi tức thì (nhấn)

durationFaster

duration-faster · 100ms

Hover, đổi màu, icon

durationFast

duration-fast · 150ms

Bề mặt rời đi

durationNormal

duration-normal · 200ms

Mở / đóng nội dung tại chỗ

durationGentle

duration-gentle · 250ms

Bề mặt đi vào (Dialog, Drawer)

durationSlow

duration-slow · 300ms

Chuyển động lớn, hiếm

curveDecelerateMid

ease-decelerate-mid

Phần tử đi vào

curveAccelerateMid

ease-accelerate-mid

Phần tử rời đi

curveEasyEase

ease-easy-ease

Đổi trạng thái tại chỗ

curveDecelerateMax

ease-decelerate-max

Đi vào, quãng dài

curveAccelerateMax

ease-accelerate-max

Rời đi, quãng dài

curveEasyEaseMax

ease-easy-ease-max

Đổi chỗ trên màn hình

curveLinear

ease-linear

Progress, xoay vòng

Utility & keyframe

duration-* đặt transition-duration, ease-* đặt transition-timing-function. Các animate-* dưới đây có sẵn trong theme (theme.css, theme-core.css); keyframe nằm trong @theme nên Tailwind chỉ xuất keyframe mà một class hay khai báo animation dùng tới. Muốn thay một keyframe bằng @keyframes cùng tên của app, khai báo nó trong @theme.

UtilityChuyển độngThời lượng · đường cong
animate-fade-inopacity 0 → 1200ms · decelerate-mid
animate-fade-outopacity 1 → 0150ms · accelerate-mid
animate-surface-inopacity 0 → 1, scale 0.96 → 1250ms · decelerate-mid
animate-surface-outopacity 1 → 0150ms · accelerate-mid
animate-slide-in-start / -end / -bottomtrượt vào từ mép đầu / cuối / đáy (lật theo RTL)250ms · decelerate-mid
animate-slide-out-start / -end / -bottomtrượt ra về mép đó150ms · accelerate-mid
animate-sweepdải sáng chạy ngang, bằng transform (Skeleton)1.8s · linear · ∞
animate-indeterminate-slidethanh 1/3 chạy ngang, bằng transform (ProgressBar không xác định)3s · linear · ∞
animate-shimmer / animate-indeterminatebản cũ đổi background-position / left (vẽ lại mỗi frame)1.8s / 3s · linear · ∞

Theo component

Cặp vào / ra mà mỗi component dùng, kèm component thật. Bật xem trước để thấy chúng khi người dùng chọn giảm chuyển động.

Dialog

Vào
surface-in 250ms · fade-in (backdrop)
Ra
fade-out 150ms
Giảm
Giữ nguyên: chỉ mờ và thu nhỏ 4%.

Drawer / Sheet

Vào
slide-in-start | end | bottom 250ms
Ra
slide-out-* 150ms
Giảm
Không trượt: hiện và ẩn ngay; nền phủ vẫn mờ dần.

Menu / Popover

Vào
surface-in 250ms
Ra
fade-out 150ms
Giảm
Giữ nguyên.

Tooltip

Vào
fade-in 200ms
Ra
fade-out 150ms
Giảm
Giữ nguyên.

Toast

Vào
slide-in-end (góc cuối) · surface-in (giữa)
Ra
slide-out-end · vuốt để đóng
Giảm
Không trượt: hiện và ẩn ngay.

Accordion

Vào
grid-template-rows 200ms · easy-ease
Ra
grid-template-rows 200ms · easy-ease
Giảm
Mở / đóng ngay, chevron không xoay.

Nội dung bên dưới được đẩy xuống cùng nhịp.

Tabs

Vào
màu vạch chỉ báo 100ms · easy-ease
Ra
không trượt giữa các tab
Giảm
Giữ nguyên (chỉ đổi màu).
Nội dung đổi ngay.

Playground

Chọn thuộc tính, rồi thời lượng và đường cong cho hai phương án; chạy để so sánh và chép class.

A

B

/* A */ transition-[translate] duration-gentle ease-decelerate-mid
/* B */ transition-[translate] duration-gentle ease-linear

Giảm chuyển động

Khi hệ điều hành bật prefers-reduced-motion, component bỏ trượt, xoay và vòng lặp; mờ dần ngắn vẫn giữ để thấy được thay đổi.

ComponentKhi giảm chuyển động
Drawer, Sheet, ToastKhông trượt; nền phủ vẫn mờ dần.
Accordion, Collapse, Fade, Slide, ScaleĐổi trạng thái ngay.
CarouselKhông tự chạy, chuyển slide không cuộn mượt.
Skeleton, ProgressBar, Spinner, ChartKhông chạy vòng lặp hay hiệu ứng vẽ.
Stagger, TourHiện cùng lúc, không lần lượt.
Dialog, Menu, Popover, TooltipGiữ nguyên: mờ dần 150–250ms, không di chuyển.

Công tắc ở phần Theo component áp đúng các class motion-reduce:* mà component khai báo. Hành vi viết bằng JavaScript (Carousel, Stagger, Tour) chỉ đổi khi bật thật trong hệ điều hành hoặc trong DevTools (Rendering › Emulate CSS media feature prefers-reduced-motion).

Khi tự viết chuyển động, thêm motion-reduce:transition-none hoặc motion-reduce:animate-none ngay cạnh class chuyển động.

Phối hợp

Nhiều thứ cùng đổi thì cho chúng đi theo một thứ tự, cùng một hướng. Chỉ animate khi chuyển động giúp người dùng theo kịp thay đổi.

Danh sách lần lượt

Stagger: cách nhau 100ms, ẩn theo thứ tự ngược lại.

  • Hộp thư
  • Bản nháp
  • Đã gửi
  • Lưu trữ

Khung xương → nội dung

Fade tại chỗ, không trượt.

Bố cục thay đổi

Collapse / Accordion đẩy nội dung bên dưới cùng nhịp.

  • Chuyển trang trong docs và trong app: không animate cả trang; thanh PageProgress là đủ.
  • Không animate khi dữ liệu cập nhật liên tục (bảng, log, chat đang stream).
  • Bề mặt mở ra từ nút bấm thì xuất hiện cạnh nút đó (Menu, Popover).

Hiệu năng

  • Animate transform / translate / scale và opacity: trình duyệt chạy chúng trên compositor, không tính lại bố cục.
  • Tránh animate width, height, top, left, margin. Accordion và Collapse là ngoại lệ có chủ ý: vùng nhỏ, 200ms, dùng grid-template-rows.
  • will-change chỉ đặt ngay trước chuyển động và bỏ sau đó; đặt lâu dài tốn bộ nhớ GPU.
  • Chuyển động chạy lâu (shimmer, indeterminate) dùng CSS animation thay vì requestAnimationFrame, để không chiếm luồng chính.

Nên & không nên

Nên
  • Ra nhanh hơn vào (ra 150ms, vào 250ms).
  • Trượt từ mép mà bề mặt gắn vào, và lật theo RTL.
  • Dùng token duration-* và ease-* để chuyển động đồng nhất.
Không nên
  • Nảy hay vượt đích trên khung giao diện.
  • Animate mỗi lần hover hay mỗi lần dữ liệu cập nhật.
  • Quá 300ms cho thứ người dùng phải chờ.