Documentation

Transitions

Animate screens and components as they enter and exit with built-in transition directives.

Overview

Whitehall provides four transition directives for complete control over enter/exit animations:

  • in: - Controls how this element enters
  • out: - Controls how this element exits
  • transition: - Shorthand for symmetric enter and exit
  • cover: - Controls backdrop animation when this element enters
  • uncover: - Controls backdrop animation when this element exits

Basic Usage

Add transitions to any component:

<Column in:fade={{ duration: 250 }} out:fade={{ duration: 250 }}>
  <Text>Content</Text>
</Column>

Symmetric Transitions

Use transition: when enter and exit animations are the same:

<Column transition:fade={{ duration: 250 }}>
  <Text>Content</Text>
</Column>

Built-in Transitions

TransitionEffectExample
fadeOpacity onlyin:fade
slidePosition changein:slide={{ from: "bottom" }}
flyPosition + fadein:fly={{ from: "right" }}
scaleScale + fadein:scale={{ from: 0.95 }}

Transition Options

Duration

in:fade={{ duration: 300 }}  // milliseconds

Direction

Available for slide and fly transitions:

in:slide={{ from: "bottom" }}
in:slide={{ from: "top" }}
in:slide={{ from: "left" }}
in:slide={{ from: "right" }}

Scale Factor

For scale transitions:

in:scale={{ from: 0.95 }}  // Start at 95% size
out:scale={{ to: 0.9 }}    // End at 90% size

Delay

in:fade={{ duration: 300, delay: 100 }}

Easing

Control animation timing:

in:fade={{ duration: 300, easing: "ease-in-out" }}

Available easing functions:

  • "linear"
  • "ease"
  • "ease-in"
  • "ease-out"
  • "ease-in-out"
  • "spring"
  • "spring(0.5, 400)" - custom spring with damping and stiffness
  • "cubic-bezier(0.32, 0.72, 0, 1)" - custom bezier curve

Screen Transitions

Apply transitions to screen root elements for page navigation animations:

// +screen.wh
<Column
  in:slide={{ from: "right", duration: 300 }}
  out:slide={{ to: "left", duration: 300 }}
>
  <Text>Screen Content</Text>
</Column>

Backdrop Transitions

Control how the previous screen animates when a new screen enters:

<Column
  in:slide={{ from: "bottom" }}
  cover:scale={{ to: 0.9 }}  // Previous screen scales down
>
  <Text>Modal Content</Text>
</Column>

Use cover:none to keep the backdrop still:

<Column in:fade cover:none>
  <Text>Overlay</Text>
</Column>

Conditional Animations

Animate components in @if blocks:

@if (visible) {
  <Card in:fade out:fade>
    <Text>Content</Text>
  </Card>
}

Stagger multiple elements:

@if (showPanel) {
  <Card in:fade={{ duration: 300 }}>Header</Card>
  <Text in:slide={{ from: "bottom", delay: 100 }}>Details</Text>
}

Transitions automatically use AnimatedVisibility for @if blocks and predictive back gestures for screen navigation.

Examples

Modal Sheet

<Column
  in:slide={{ from: "bottom", duration: 400 }}
  out:slide={{ to: "bottom", duration: 300 }}
  cover:scale={{ to: 0.95 }}
  uncover:scale={{ from: 0.95 }}
>
  <Text>Modal Content</Text>
</Column>

Fade Through

<Column
  in:fade={{ duration: 150, delay: 75 }}
  out:fade={{ duration: 75 }}
>
  <Text>Content</Text>
</Column>

Shared Axis

<Column
  in:fly={{ from: "right", duration: 300 }}
  out:fly={{ to: "left", duration: 300 }}
>
  <Text>Next Screen</Text>
</Column>

See Also