-
Notifications
You must be signed in to change notification settings - Fork 9
Guide Animation
A unified animation system providing preset animations, easing functions, constants, and orchestration capabilities for UI components.
The animation module provides a comprehensive set of tools for creating smooth, performant UI animations. It builds on top of gpui's Animation and Transition APIs, offering:
- Easing functions: Mathematical easing functions for natural motion
- Preset animations: Ready-to-use common animation patterns
- Animation configuration: Configurable animation settings with duration, easing, delay, and repeat options
- Animation state: State tracking for complex animations
- Orchestration: Sequence, parallel, and staggered animation playback
- Helper utilities: Interpolation functions and extension traits
use yororen_ui::animation::{
fade_slide_in,
constants::duration::MENU_OPEN,
};
// Apply preset animation to a gpui element
div.with_animation(
"menu-open",
Animation::new(MENU_OPEN),
fade_slide_in(MENU_OPEN),
)- Menu/dropdown open/close animations
- Modal dialog transitions
- Loading states (pulse, spin)
- Hover/focus state transitions
- Page/component entrance animations
Not a good fit:
- Complex physics-based animations (use custom implementation)
- Frame-by-frame procedural animations
Provides mathematical easing functions for controlling animation timing. All functions take a normalized time value (0.0 to 1.0) and return the eased progress value.
| Function | Description |
|---|---|
ease_linear |
No easing, linear progression |
| Function | Description |
|---|---|
ease_in_quad |
Starts slow, accelerates |
ease_out_quad |
Starts fast, decelerates |
ease_in_out_quad |
Slow start and end, fast middle |
| Function | Description |
|---|---|
ease_in_cubic |
Starts slow, accelerates |
ease_out_cubic |
Starts fast, decelerates |
ease_in_out_cubic |
Slow start and end, fast middle |
| Function | Description |
|---|---|
ease_in_quart |
Starts slow, accelerates |
ease_out_quart |
Starts fast, decelerates |
ease_in_out_quart |
Slow start and end, fast middle |
| Function | Description |
|---|---|
ease_in_quint |
Starts slow, accelerates |
ease_out_quint |
Starts fast, decelerates |
ease_in_out_quint |
Slow start and end, fast middle |
| Function | Description |
|---|---|
ease_in_sine |
Starts slow, accelerates |
ease_out_sine |
Starts fast, decelerates |
ease_in_out_sine |
Slow start and end, fast middle |
| Function | Description |
|---|---|
ease_in_expo |
Very slow start, accelerates sharply |
ease_out_expo |
Fast start, decelerates sharply |
ease_in_out_expo |
Very slow start and end, fast middle |
| Function | Description |
|---|---|
ease_in_circ |
Starts slow, accelerates |
ease_out_circ |
Starts fast, decelerates |
ease_in_out_circ |
Slow start and end, fast middle |
Creates a slight overshoot effect before settling.
| Function | Description |
|---|---|
ease_out_back |
Overshoots target, then settles |
ease_in_out_back |
Overshoots at both ends |
Creates a spring-like bouncing effect.
| Function | Description |
|---|---|
ease_in_elastic |
Bounces at the start |
ease_out_elastic |
Bounces at the end |
ease_in_out_elastic |
Bounces at both ends |
Creates a bouncing effect like a ball hitting the ground.
| Function | Description |
|---|---|
ease_in_bounce |
Bounces at the start |
ease_out_bounce |
Bounces at the end |
ease_in_out_bounce |
Bounces at both ends |
Simple quadratic easing functions that match gpui's built-in easing.
| Function | Description |
|---|---|
ease_in |
Quadratic ease in |
ease_out |
Quadratic ease out |
ease_in_out |
Quadratic ease in-out |
pub type EasingFn = fn(f32) -> f32;Provides ready-to-use animation functions that can be applied directly to gpui elements.
pub enum AnimationType {
FadeIn,
FadeOut,
SlideIn(SlideDirection),
SlideOut(SlideDirection),
ScaleIn,
ScaleOut,
BounceIn,
BounceOut,
ElasticIn,
ElasticOut,
FadeSlideIn(SlideDirection),
FadeScaleIn,
}
pub enum SlideDirection {
Left,
Right,
Up,
Down,
}| Function | Description |
|---|---|
fade_slide_in(duration) |
Fade + slide up for menus (opacity 0→1, translate 10px→0) |
fade_slide_out(duration) |
Reverse of fade_slide_in (opacity 1→0, translate 0→10px) |
pulse(duration) |
Loading pulse animation (opacity 0.55→0.95) |
fade_slide_in_left(distance) |
Slide from left with fade |
fade_slide_in_right(distance) |
Slide from right with fade |
fade_slide_in_up(distance) |
Slide from top with fade |
fade_slide_in_down(distance) |
Slide from bottom with fade |
| Struct | Description |
|---|---|
FadeIn |
Fade in animation builder with custom easing support |
FadeOut |
Fade out animation (opacity 1→0) |
use yororen_ui::animation::preset::duration;
duration::VERY_FAST // 100ms
duration::FAST // 150ms
duration::NORMAL // 200ms
duration::SLOW // 300ms
duration::VERY_SLOW // 400ms
duration::INSTANT // 0msProvides configuration and state tracking for animations.
Configurable animation settings:
pub struct AnimationConfig {
pub duration: Duration,
pub easing: EasingFn,
pub delay: Duration,
pub repeat: bool,
pub reverse: bool,
}Example:
use yororen_ui::animation::AnimationConfig;
use std::time::Duration;
let config = AnimationConfig::new()
.with_duration(Duration::from_millis(300))
.with_easing(ease_out_cubic)
.with_delay(Duration::from_millis(100))
.with_repeat()
.with_reverse(); // yoyo effectTrack animation progress and status:
pub struct AnimationState {
pub progress: f32, // 0.0 to 1.0
pub is_running: bool,
pub is_paused: bool,
}Example:
use yororen_ui::animation::AnimationState;
let mut state = AnimationState::new();
state.update(0.5); // Set progress to 50%
state.reset(); // Reset to initial stateProvides timing constants for consistent animation timing across the library.
| Constant | Duration |
|---|---|
CURSOR_BLINK_INTERVAL |
500ms |
| Constant | Duration |
|---|---|
duration::MENU_OPEN |
160ms |
duration::MENU_OPEN_FAST |
100ms |
duration::MENU_OPEN_SLOW |
250ms |
| Constant | Duration |
|---|---|
duration::NAVIGATOR_SLIDER |
200ms |
duration::TAB_SWITCH |
150ms |
| Constant | Duration |
|---|---|
duration::SKELETON_PULSE_1 |
1100ms |
duration::SKELETON_PULSE_2 |
1200ms |
| Constant | Duration |
|---|---|
duration::PROGRESS_SPINNER |
850ms |
duration::PROGRESS_CIRCLE |
900ms |
duration::PROGRESS_BAR |
1500ms |
| Constant | Duration |
|---|---|
duration::MODAL_FADE_IN |
200ms |
duration::MODAL_SLIDE_UP |
250ms |
| Constant | Duration |
|---|---|
duration::TOOLTIP_SHOW |
150ms |
duration::TOOLTIP_HIDE |
100ms |
| Constant | Duration |
|---|---|
duration::VERY_FAST |
100ms |
duration::FAST |
150ms |
duration::NORMAL |
200ms |
duration::SLOW |
300ms |
duration::VERY_SLOW |
400ms |
Provides capabilities for sequencing and parallelizing multiple animations.
Run animations one after another:
use yororen_ui::animation::{AnimationSequence, sequence};
use yororen_ui::animation::constants::duration::*;
// Builder pattern
let seq = AnimationSequence::new()
.then(MODAL_FADE_IN)
.then(MODAL_SLIDE_UP);
// Or use convenience function
let seq = sequence(&[MODAL_FADE_IN, MODAL_SLIDE_UP]);
// Query sequence info
let total = seq.total_duration(); // Total duration of all animations
let count = seq.len(); // Number of animations in sequence
// Calculate progress for specific animation
let (anim_index, anim_progress) = seq.calculate_progress(0.5); // At 50% overall progressRun animations simultaneously:
use yororen_ui::animation::{AnimationParallel, parallel};
use yororen_ui::animation::constants::duration::*;
// Builder pattern
let par = AnimationParallel::new()
.with(FAST)
.with(FAST);
// Or use convenience function
let par = parallel(&[FAST, FAST]);
// Query parallel info
let max_duration = par.max_duration(); // Longest animation duration
let count = par.len(); // Number of parallel animations
// Calculate progress for specific animation
let progress = par.calculate_progress(0.5, 0); // At 50% overall progressCreate staggered delays for list animations:
use yororen_ui::animation::Staggered;
use std::time::Duration;
let base_duration = Duration::from_millis(200);
let delay = Duration::from_millis(50);
// Create staggered delays for 5 items
let delays: Vec<Duration> = base_duration.stagger(5, delay);
// Result: [200ms, 250ms, 300ms, 350ms, 400ms]Extension trait for animating gpui elements directly:
use yororen_ui::animation::AnimateExt;
// Fade animation
div.animate_fade("fade-id", Duration::from_millis(200), 0.5);
// Slide animation
div.animate_slide(
"slide-id",
SlideDirection::Up,
px(10.0),
Duration::from_millis(200),
0.5,
);
// Scale animation
div.animate_scale("scale-id", Duration::from_millis(200), 0.5);pub enum SlideDirection {
Left,
Right,
Up,
Down,
}Linear interpolation between two values:
use yororen_ui::animation::lerp;
let start = 0.0;
let end = 100.0;
let value = lerp(start, end, 0.5); // 50.0Linear interpolation between two colors:
use yororen_ui::animation::lerp_color;
use gpui::Hsla;
let start = Hsla { h: 0.0, s: 1.0, l: 0.5, a: 1.0 };
let end = Hsla { h: 0.33, s: 1.0, l: 0.5, a: 1.0 };
let color = lerp_color(start, end, 0.5);Create animation IDs for stateful animations:
use yororen_ui::animation::animation_id;
let id = animation_id("menu", OpenState::Open);
// Result: "menu:Open"Stick to the defined constants for consistency across the UI:
// Good
use yororen_ui::animation::constants::duration::MENU_OPEN;
// Avoid
let duration = Duration::from_millis(160);| Animation Type | Recommended Easing |
|---|---|
| Entrance animations |
ease_out_* (fast start, smooth end) |
| Exit animations |
ease_in_* (smooth start, fast end) |
| Equal emphasis | ease_in_out_* |
| Loading/continuous |
ease_in_out or ease_linear
|
| Attention-grabbing |
ease_out_back or ease_out_elastic
|
Most UI animations should be 100-300ms:
- Very fast (100ms): Hover states, tooltips
- Fast (150ms): Simple toggles, tab switches
- Normal (200ms): Most transitions, fades
- Slow (300ms): Complex animations, modals
Some users prefer reduced motion. Check for user preferences before applying animations.
Before (old):
use crate::constants::animation::MENU_OPEN;After:
use yororen_ui::animation::constants::duration::MENU_OPEN;use yororen_ui::animation::{
Animation, AnimationExt,
fade_slide_in,
constants::duration::MENU_OPEN,
};
menu.with_animation(
"popover-menu",
Animation::new(MENU_OPEN),
fade_slide_in(MENU_OPEN),
)use yororen_ui::animation::{
Animation, AnimationExt,
fade_slide_in, fade_slide_out,
AnimationSequence, AnimationConfig,
AnimateExt, SlideDirection,
constants::duration::*,
easing::{ease_out_quint, ease_in_out},
lerp,
};
fn animate_menu_open(menu: gpui::Div) -> gpui::Div {
menu.with_animation(
"menu-open",
Animation::new(MENU_OPEN).with_easing(ease_out_quint()),
fade_slide_in(MENU_OPEN),
)
}
fn animate_list_items(items: &[gpui::Div]) {
use yororen_ui::animation::Staggered;
let delays = FAST.stagger(items.len(), Duration::from_millis(30));
for (item, delay) in items.iter().zip(delays) {
// Apply staggered animation to each item
item.with_animation(
"list-item",
Animation::new(delay).with_easing(ease_out_quint()),
fade_slide_in(delay),
);
}
}Yororen UI v0.3.0 · repository · Apache-2.0 · This wiki documents Yororen UI v0.3.0.
This wiki documents Yororen UI v0.3.0 — the headless-core, swappable-renderer build.