GPUI Box GitHub

Components / effects

CinematicEffect builder

A semantic one-shot effect with an optional prepared dotLottie clip.

A builder is RenderOnce. Construct and mount it in one expression.

use gpui_kit::effects::CinematicEffect;

Reviewed in cinematic-effects.

Construct
new(ident: impl Into<Ident>, plan: EffectPlan) -> Self
Options

Chain onto the value.

clip(clip: Rc<dyn DotLottieClip>) -> Self
resolved(clip: Result<Rc<dyn DotLottieClip>, DotLottieError>) -> Self
unavailable(error: DotLottieError) -> Self
sample_at(elapsed: Duration) -> Self
Example · cinematic-effects
fn cinematic_effects(_window: &mut Window, cx: &mut App) -> AnyElement {
    let theme = cx.theme().clone();
    let clip: Rc<dyn DotLottieClip> = Rc::new(SceneCinematicClip);
    let mut planner = EffectPlanner::new(EffectPolicy::new(EffectQuality::Cinematic));
    let success = planner.plan(
        EffectEvent::new(
            "scene-cinematic-success",
            "cinematic-effects",
            "success",
            VisualCue::Success,
        ),
        1,
        false,
    );
    let handoff = planner.plan(
        EffectEvent::new(
            "scene-cinematic-handoff",
            "cinematic-effects",
            "handoff",
            VisualCue::Handoff,
        ),
        1,
        false,
    );
    let reward = planner.plan(
        EffectEvent::new(
            "scene-cinematic-reward",
            "cinematic-effects",
            "reward",
            VisualCue::Reward,
        ),
        1,
        false,
    );
    let mut static_planner = EffectPlanner::new(EffectPolicy::new(EffectQuality::Cinematic));
    let static_reward = static_planner.plan(
        EffectEvent::new(
            "scene-cinematic-static",
            "cinematic-effects-static",
            "reward",
            VisualCue::Reward,
        ),
        1,
        true,
    );

    let card = |title: &'static str, detail: &'static str, effect: AnyElement| {
        div()
            .column()
            .w(px(372.0))
            .h(px(228.0))
            .radius(&theme, Radius::Card)
            .overflow_hidden()
            .bg(theme.colors.sunken)
            .child(div().relative().w_full().h(px(154.0)).child(effect))
            .child(
                div()
                    .column()
                    .gap_token(&theme, Space::Xs)
                    .px_token(&theme, Space::Md)
                    .py_token(&theme, Space::Sm)
                    .child(crate::foundation::text(&theme, TypeScale::Label, title))
                    .child(
                        crate::foundation::text(&theme, TypeScale::Caption, detail)
                            .text_color(theme.colors.text_muted),
                    ),
            )
    };

    stack(&theme)
        .w(px(808.0))
        .child(crate::foundation::text(
            &theme,
            TypeScale::Subtitle,
            "Semantic cinematic effects",
        ))
        .child(caption(
            &theme,
            "events choose recipes; hosts resolve bytes and own playback requests",
        ))
        .child(
            row(&theme)
                .gap_token(&theme, Space::Md)
                .child(card(
                    "Handoff · deterministic sample",
                    "A resolved clip sampled at 575 ms; RTL mirrors its directional trail.",
                    CinematicEffect::new("scene.cinematic.handoff", handoff)
                        .clip(clip.clone())
                        .sample_at(Duration::from_millis(575))
                        .into_any_element(),
                ))
                .child(card(
                    "Success · runtime unavailable",
                    "The semantic recipe falls back to the policy-owned particle burst.",
                    CinematicEffect::new("scene.cinematic.success", success)
                        .unavailable(DotLottieError::new(
                            DotLottieErrorKind::RuntimeUnavailable,
                            "dotLottie backend is not installed",
                        ))
                        .sample_at(Duration::from_millis(520))
                        .into_any_element(),
                )),
        )
        .child(
            row(&theme)
                .gap_token(&theme, Space::Md)
                .child(card(
                    "Reward · invalid asset fallback",
                    "A refused archive stays explicit while a bounded particle recipe renders.",
                    CinematicEffect::new("scene.cinematic.invalid", reward)
                        .unavailable(DotLottieError::new(
                            DotLottieErrorKind::ArchiveInvalid,
                            "animation archive did not pass validation",
                        ))
                        .sample_at(Duration::from_millis(620))
                        .into_any_element(),
                ))
                .child(card(
                    "Reward · reduced-motion poster",
                    "The same recipe becomes a deterministic poster with no frame timeline.",
                    CinematicEffect::new("scene.cinematic.poster", static_reward)
                        .clip(clip)
                        .into_any_element(),
                )),
        )
        .into_any_element()
}

Source: crates/gpui-kit/src/effects/dotlottie.rs