Skip to main content

Crate motion

Crate motion 

Source
Expand description

Animation kit — a named motion catalog as reusable helpers over gpui Animation/AnimationExt.

Catalog (docs/research/feature-inventory.md §1.12):

  • fade-in 0.5s cubic-bezier(0.16,1,0.3,1), translateY 4→0 (entrances)
  • fade-quick 0.15s
  • menu-in 0.14s scale 0.96 + translateY −2 (popovers)
  • dialog-in 0.18s scale 0.96→1
  • splash-out 0.5s opacity + translateY −6, 0.15s delay
  • pulse 2.4s staggered cell opacity 0.08→1, scale 0.9→1 (loaders)
  • gradient-spin-pulse 750ms per-cell phase wave (working indicator)
  • 200ms ease-out width/height transitions (sidebar/panes)

Custom easing is a closure over gpui’s Fn(f32) -> f32 easing shape; CSS cubic-bezier() is evaluated exactly by CubicBezier.

Reduced motion: gpui’s App::reduce_motion flag is honored automatically by every with_animation element — oneshot animations snap to their end state, repeating ones to their start state, and no frames are scheduled. The set_reduced_motion/reduced_motion wrappers make it a single global switch; pure helpers take the flag explicitly where they run outside elements.

translateY is implemented as a relative-position top inset: taffy applies relative insets after layout, so — like a CSS transform — siblings never move. gpui has no scale transform for divs at the pinned rev (only svg transformations), so menu-in/dialog-in approximate their scale component with fade + translate; see the module report in ARCHITECTURE §4 follow-ups.

Re-exports§

pub use crate::phase::ORB_BLOOM_RINGS;
pub use crate::phase::ORB_RING_DOT;
pub use crate::phase::ORB_RING_DOTS;
pub use crate::phase::ORB_RING_RADIUS;
pub use crate::phase::ORB_SEATS;
pub use crate::phase::ORBS;
pub use crate::phase::PULSE_MIN_OPACITY;
pub use crate::phase::PULSE_MIN_SCALE;
pub use crate::phase::PULSE_STAGGER;
pub use crate::phase::gspin_opacity;
pub use crate::phase::orb_bloom_opacity;
pub use crate::phase::orb_bloom_radius;
pub use crate::phase::orb_converge_radius;
pub use crate::phase::orb_drift;
pub use crate::phase::orb_glow;
pub use crate::phase::orb_opacity;
pub use crate::phase::orb_ring_seat;
pub use crate::phase::orb_size;
pub use crate::phase::pulse_opacity;
pub use crate::phase::pulse_scale;
pub use crate::phase::pulse_wave;
pub use crate::phase::staggered_phase;

Modules§

phase
Loader math — the pure phase functions behind the loading indicators.

Structs§

CubicBezier
A CSS cubic-bezier(x1, y1, x2, y2) timing function (endpoints fixed at (0,0) and (1,1)). Evaluation solves x(t) = input by Newton iteration with a bisection fallback — the standard UnitBezier approach.
Fade
Which fade: the view that paints it, and which element inside that view.
FadeEntry
One element’s hover fade: progress runs origin → target over HOVER_FADE, re-anchored at origin whenever the pointer flips direction mid-flight so the blend is continuous.
HoverFades
Per-fade progress store. Pure core (explicit now) — unit-testable; the thread-local wrappers below feed it the clock.
MotionSpec
One catalog entry: duration + optional delay + curve. The delay is folded into the gpui animation timeline (gpui Animation has no native delay): the animation runs for delay + duration and progress holds 0 until the delay has elapsed.
Painter
A component’s line back to the view that paints it.

Constants§

CHEVRON
Diff-pane chevron rotate: 200ms (§1.11; approximated as a crossfade — gpui divs have no rotation transform at the pinned rev, same caveat as scale).
COLLAPSE
Diff-pane per-file collapse: 180ms height (§1.11).
DIALOG_IN
Dialog-in: 0.18s (scale 0.96→1 approximated).
EASE
CSS ease — quick fades, menu/dialog pops.
EASE_IN_OUT
CSS ease-in-out — the transcript scroll glide (browser smooth-scroll shape: gentle start, cruise, gentle landing).
EASE_OUT
CSS ease-out — width/height transitions.
EASE_OUT_EXPO
The signature entrance curve — CSS cubic-bezier(0.16, 1, 0.3, 1).
EASE_RESORT
Sidebar resort glide — CSS cubic-bezier(0.22, 1, 0.36, 1) (used from M3b).
EASE_TAILWIND
Tailwind’s default transition curve — CSS cubic-bezier(0.4, 0, 0.2, 1) (transition-colors et al. carry it unless overridden).
FADE_IN
Entrances: 0.5s expo-out fade + 4px rise.
FADE_QUICK
Quick fade: 0.15s.
GRADIENT_SPIN
Gradient matrix spinner wave period: 750ms.
HOVER_FADE
CSS transition-colors default: 150ms over EASE_TAILWIND — the temporal blend every interactive hover wash rides in the original.
MENU_IN
Popover-in: 0.14s (scale 0.96 approximated, translateY −2).
MENU_OUT
Popover-out: 0.1s — quicker than the entrance (exits should get out of the way; matches the Radix convention of a shorter close than open).
ORB
Orb cluster breath: 2s, and EASE_IN_OUT because a breath has no edges — the two spinners tick, this one swells.
PULSE
Pulse loader period: 2.4s.
RESIZE
Sidebar / pane width+height transitions: 200ms ease-out.
SCROLL_GLIDE
Rail-tick / scroll-to-row glide: 500ms ease-in-out over the whole distance (Electron parity — the original rail rode the browser’s native smooth scroll, a fixed-duration gentle ease, never percent-of-remaining).
SPLASH_OUT
Boot splash exit: 0.5s fade + 6px lift after a 0.15s hold.
TAB_SLIDE
Terminal tab drag-reorder sliding transforms: 150ms (§1.10).

Traits§

AnimationExt
What the catalog’s one-shot entrances are built on. Repeats belong on pulse_delta, which leases the view instead of pinning the window. An extension trait for adding the animation wrapper to both Elements and Components

Functions§

dialog_in
Dialog entrance over DIALOG_IN (scale approximated with fade + 2px rise).
fade_in
Standard entrance: opacity 0→1 + translateY 4→0 over FADE_IN.
fade_quick
Quick opacity-only fade over FADE_QUICK.
hover_blend
The standard hover blend: rest → hover color at this fade’s progress.
hover_listener
An .on_hover listener driving the fade — pair with hover_t or hover_blend reads of the same Fade in the same element.
hover_t
Hover progress (0..1) for fade this frame.
lerp
Linear interpolation (layout tweens).
matrix_wave
Gradient-matrix spinner wave: intensity (0..1) of cell wave_index out of wave_count diagonals, at raw delta raw_delta of the 750ms period. The wave front travels across diagonals once per period.
menu_in
Popover entrance: fade + translateY −2→0 over MENU_IN. (the original also scales 0.96→1; divs have no scale transform in gpui — approximated.)
menu_out
Popover exit: the reverse of menu_in — fade to 0 + translateY 0→−2 over MENU_OUT. Unlike the entrances, the eased progress t comes from the caller (computed off bezel::popover::Popup’s closing instant at render time): with_animation’s element-id-keyed clock replays from 0 on remount (the hover-blend comment’s warning), and a replay mid-exit is a full-opacity flash. The wall-clock progress is monotonic by construction; the animation wrapper here only pumps frames for the exit’s span, its own delta unused.
mix
Blend two colors by t the way the browser transitions them: component interpolation in sRGB with premultiplied alpha — a wash fading in from transparent brightens without passing through grey.
pulse_delta
Current phase [0,1) of a repeating spec, plus a [lease] that keeps the calling view re-rendering at [PULSE_FPS] while its spinner stays mounted. All cells across all views share one epoch, so multi-instance loaders stay phase-locked. Reduced motion returns a static 0 and schedules nothing.
reduced_motion
Read the global reduced-motion flag.
set_hover
Record a hover flip for fade (reduced motion snaps). Prefer hover_listener, which also asks the clock for the frames to paint it.
set_reduced_motion
Global reduced-motion flag. gpui snaps every with_animation element when set (end state for oneshots, rest state for loops) and schedules no frames.
set_speed
Stretch every catalog timeline by scale10.0 slows the 200ms pane tweens to 2s, so a screenshot burst can sample the geometry frame by frame.
speed_scale
How far every timeline in the catalog is stretched. 1.0 is the designed speed.
splash_out
Boot-splash exit: hold 150ms, then fade out + lift 6px over 500ms.