Enter, exit and screen transitions Pro

An enter/exit transition animates an element as it appears and disappears. The tricky part in UI Toolkit is display: an element must be display: flex before it can animate in, and should become display: none only after it has animated out, or it keeps taking space and catching clicks.

Cascade Pro's Show and Hide handle that order for you.

using Cascade;

panel.Show(Transition.SlideFade(Edge.Bottom, 0.35f));   // display: flex, then animate in
panel.Hide(Transition.ScaleFade(0.25f));                // animate out, then display: none

Built-in transitions

TransitionLooks like
Transition.Fade(d)opacity only
Transition.Slide(edge, d)moves in from an edge
Transition.SlideFade(edge, d)moves and fades; the usual choice for panels and toasts
Transition.Scale(d)grows from 85%
Transition.ScaleFade(d)grows and fades; the usual choice for dialogs
Transition.Crossfade(d)a fade, used for swapping screens

Add .WithEase(...) to any of them, for example Transition.ScaleFade(0.28f).WithEase(Ease.OutBack).

Toast: slide in, dismiss itself

void ShowToast()
{
    toast.StopAnimations();   // a second click restarts it cleanly
    toast.Show(Transition.SlideFade(Edge.Top, 0.3f).WithEase(Ease.OutCubic));
    toast.schedule.Execute(HideToast).ExecuteLater(1900);
}

void HideToast()
{
    if (toast.resolvedStyle.display == DisplayStyle.None) return;
    toast.Hide(Transition.SlideFade(Edge.Top, 0.25f).WithEase(Ease.InCubic));
}

Ease out on the way in and ease in on the way out. Accelerating away reads as "dismissed".

void OpenModal()
{
    modalOpen = true;
    modalRoot.style.display = DisplayStyle.Flex;
    backdrop.Show(Transition.Fade(0.2f));
    dialog.Show(Transition.ScaleFade(0.28f).WithEase(Ease.OutBack));
}

void CloseModal()
{
    modalOpen = false;
    backdrop.Hide(Transition.Fade(0.18f));
    dialog.Hide(Transition.ScaleFade(0.2f));
    // hide the container after the children finish, unless the modal was re-opened meanwhile
    modalRoot.schedule.Execute(() => { if (!modalOpen) modalRoot.style.display = DisplayStyle.None; })
             .ExecuteLater(240);
}

Keep the backdrop on a plain fade and give the overshoot to the dialog, so only one thing draws the eye.

Swap screens

screens.SwapTo(settingsScreen, Transition.Crossfade(0.3f));

SwapTo animates the current child of screens out (ending at display: none) and the new one in. Both screens must already be children of screens.

Tabs with a sliding underline

void SwitchTab(int i)
{
    if (i == current) return;                        // clicking the open tab does nothing
    pages[current].Hide(Transition.Fade(0.16f));     // out a little faster than in
    pages[i].Show(Transition.Fade(0.22f));

    indicator.Animate().MoveX(tabs[i].layout.x, 0.28f).Ease(Ease.OutCubic);
    indicator.Animate().Width(tabs[i].layout.width, 0.28f).Ease(Ease.OutCubic);
    current = i;
}

Read layout only after the first layout pass, for example in a GeometryChangedEvent callback. Before that it returns zeros.

Show/Hide or AnimateIn/AnimateOut?

AnimateIn and AnimateOut play the same transitions but don't touch display. Use them when you manage visibility yourself. Anything that opens and closes repeatedly should use Show and Hide: an element left at display: none by a previous Hide stays invisible under AnimateIn.

With Cascade Lite

Lite has no Show/Hide, but the same effect takes a few lines:

// in
panel.style.display = DisplayStyle.Flex;
panel.Animate().SlideIn(Edge.Bottom, 0.35f).Ease(Ease.OutCubic).Fade(1f, 0.35f).From(0f);

// out
panel.Animate().Fade(0f, 0.25f).Ease(Ease.InCubic)
     .OnSettled(done => { if (done) panel.style.display = DisplayStyle.None; });
// "done" is false when a new animation replaced this one, e.g. the panel was opened again

Get Cascade Pro Get Cascade Lite (free)