# Screen transitions

> Animate the window switch (fade/slide/scale) by declaring WindowStyle.transition.

Source: https://crossfly.dev/docs/ui/animations/screen-transitions — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Screen transitions

On a window's `show()`/`hide()`, CrossFly can animate the switch by capturing the screen **before** and
**after** and interpolating between them. You **declare** the effect in the `WindowStyle`; the framework triggers
the transition on its own.

## Complete example (copy, paste and run)
```java
package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      // Declare the transition BEFORE mounting the UI (the "before" is captured on the first paint).
      // getStyle() infers WindowStyle here, where transition(...) is defined.
      getStyle().transition(UIConstants.Transition.SLIDE_LEFT, 0.4f);   // effect + duration (s)

      setLayout(new VerticalLayout());
      Label titulo = new Label("Nova tela");
      add(LAY_AUTO, titulo);

      Button avancar = new Button("Avançar");
      add(LAY_AUTO, avancar);
      // When stacking another window with a SLIDE_LEFT transition, the framework animates the swap on its own:
      avancar.onAction(c -> new MainWindow().show());
   }
}
```
> The snippets below show **only the core** (what goes inside `onShow()`). To run them, place them in the `MainWindow` skeleton above.

## The declarative way (recommended)
Define the effect in the window's style — in `onShow()`, before anything appears:
```java
@Override public void onShow() throws Exception {
   super.onShow();
   getStyle().transition(UIConstants.Transition.SLIDE_LEFT, 0.4f);  // effect + duration (s)
   // … mounts the UI …
}
```
Or through the `WindowStyle` fields/fluent methods:
```java
getStyle().transition = UIConstants.Transition.FADE;   // public field
getStyle().transitionDuration = 0.3f;
// fluent equivalent:
getStyle().transition(UIConstants.Transition.FADE).transitionDuration(0.3f);
```

## Available effects (`UIConstants.Transition`)
| Value | Effect |
|---|---|
| `NONE` | instant switch (default) |
| `FADE` | fades one screen over the other |
| `SLIDE_LEFT` / `SLIDE_RIGHT` | slides on the horizontal axis |
| `SLIDE_UP` / `SLIDE_DOWN` | slides on the vertical axis |
| `SCALE` | the new screen grows from the center |
| `SCALE_DOWN` | the current screen shrinks toward the center |

> Defaults: `WindowStyle.transition` starts at `NONE` and `transitionDuration` at `0.5s`. **Pickers** already
> use `FADE` by default.

## How it works under the hood
`ScreenTransition.begin(Transition, duration)` captures the current screen as "before", the new one as
"after" on the next frame, and interpolates (using an internal `AlphaAnimation`). You usually **don't**
call this — `Window.show()`/`hide()` calls it when there is `transition != NONE`.

## Best practices
- Choose the effect by the **navigation intent**: `SLIDE_LEFT` to go forward, `SLIDE_RIGHT`/`SCALE_DOWN`
  to go back.
- Keep durations short (0.25–0.4s) — long transitions get in the way.
- Set the transition in `onShow()` (before the window is painted).

## Common mistakes
- Setting the transition too late (after the first paint) — the "before" has already changed.
- Long durations that make navigation feel slow.

## See also
- [Value animations](/docs/ui/animations/value-animations) · [The window stack](/docs/ui/navigation/the-window-stack)
