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 entersout:- Controls how this element exitstransition:- Shorthand for symmetric enter and exitcover:- Controls backdrop animation when this element entersuncover:- 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
| Transition | Effect | Example |
|---|---|---|
fade | Opacity only | in:fade |
slide | Position change | in:slide={{ from: "bottom" }} |
fly | Position + fade | in:fly={{ from: "right" }} |
scale | Scale + fade | in: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
- animate:flip - List reordering animations
- transition:crossfade - Shared element transitions
- Progress-Driven Morphing - Gesture-driven animations