Skip to content

Animations & transitions (1.22)

Copy-ready motion for list → detail, page enter, and content swap. All helpers honor Theme.reducedMotion (and Theme.duration() collapses to ~1 ms when reduced motion is on).

Status: experimental — APIs are usable; keep them behind reduced-motion checks in production. Explicitly deferred in 1.37stable-api.md.

Gallery: Animations (hub) · ConnectedAnimation · EntranceThemeTransition · Theme transitions.


Choosing

Need Prefer
Shared-element morph (thumb → hero) ConnectedAnimation + ConnectedAnimationService
Master–detail pane handoff ListDetailsView connectedAnimationEnabled
First show of a section / card EntranceThemeTransition
Swap content identity (tab/panel) ContentThemeTransition
Flow/Grid children reflow RepositionThemeTransition
Icon hover/press micro-motion FontIcon / IconButton — icons.md (1.49)
Icon state swap (play/pause…) AnimatedIconicons.md (1.53, experimental, not Lottie)
Page carousel / hero strip FlipView + PipsPagercarousel-recipes.md (2.37)
Theme.dark / accent color change Behavior + Theme.duration (below) — not a dedicated type

Do not wrap the entire ShellWindow / title bar in entrance motion — animate client content only to avoid chrome jank.


Reduced motion

// Prefer system SPI (Gallery / apps):
WindowHelper.refreshAccessibility()
Theme.reducedMotion = WindowHelper.systemReducedMotion

// Or let the user toggle Theme.reducedMotion in Settings.
Helper When Theme.reducedMotion
ConnectedAnimation / Service Skips morph; still invokes finished / onFinished
Entrance / Content transitions Snaps to final opacity/transform
RepositionThemeTransition Behavior disabled
Theme.duration(ms) Returns 1

Always drive custom NumberAnimation / ColorAnimation durations through Theme.duration(...).


ConnectedAnimation — list → detail

Register from then to under the same key, then play. Same-window only (ghost parents to Overlay.overlay).

import QWinUI3.Extras

// After layout is ready (e.g. onClicked):
ConnectedAnimationService.register("mail.hero", listThumb)
ConnectedAnimationService.register("mail.hero", detailHero)
ConnectedAnimationService.play("mail.hero", function () {
    stack.push(detailPage)
})

// Or one-shot without the registry:
ConnectedAnimation {
    id: morph
    from: listThumb
    to: detailHero
    onFinished: stack.push(detailPage)
}
morph.play()
Tip Detail
Key lifetime Unregister or clear() when leaving the page
Timing Register after the destination item has a real size
ListDetailsView Set connectedAnimationEnabled: true for built-in handoff
Ghost look ghostColor / source tint via ConnectedAnimation

EntranceThemeTransition — shell page enter

EntranceThemeTransition {
    anchors.fill: parent
    autoPlay: true          // also replays when becoming visible
    // offsetY / fromScale — optional tuning
    YourPageBody { anchors.fill: parent }
}

Call play() / reset() for demos. Prefer wrapping one content host, not every nested card.


ContentThemeTransition — panel swap

Bump contentKey (or call play()) after replacing children:

ContentThemeTransition {
    anchors.fill: parent
    contentKey: currentPanelId
    // children = current panel UI
}

RepositionThemeTransition — layout reflow

Wrap Flow/Grid delegates so x/y changes animate:

Flow {
    spacing: Theme.spacing
    Repeater {
        model: count
        RepositionThemeTransition {
            width: 72; height: 40
            Rectangle { anchors.fill: parent; /* … */ }
        }
    }
}

Theme.dark / accent (no dedicated transition type)

Rectangle {
    color: Theme.bgLayer
    Behavior on color {
        ColorAnimation {
            duration: Theme.duration(Theme.motionNormal)
            easing.type: Theme.easingStandard
        }
    }
}

Use the same pattern for Theme.accent fills. Avoid animating dozens of deep tree nodes on every theme flip — prefer a few large surfaces (window layer, cards).


Motion tokens

Token Typical use
Theme.motionFast / motionNormal / motionSlow Pass to Theme.duration(...)
Theme.easingEnter / easingStandard / easingEmphasized Match Fluent enter vs morph

Doc / type Role
ConnectedAnimation Ghost morph
ConnectedAnimationService Key registry
EntranceThemeTransition Page enter
ContentThemeTransition Content swap
RepositionThemeTransition Reflow
ListDetailsView Built-in connected animation
accessibility.md reducedMotion / SPI
icons.md Glyph hover/press (1.49) · AnimatedIcon state swap (1.53)
data-collections.md List → detail notes