Skip to content

feat: Hero animations#6157

Open
ndonkoHenri wants to merge 9 commits intomainfrom
hero
Open

feat: Hero animations#6157
ndonkoHenri wants to merge 9 commits intomainfrom
hero

Conversation

@ndonkoHenri
Copy link
Contributor

@ndonkoHenri ndonkoHenri commented Feb 11, 2026

Fix #2438

Test code

import flet as ft


def main(page: ft.Page):
    hero_tag = "demo-hero-card"

    def build_card(size: int, label: str) -> ft.Container:
        icon_size = max(24, int(size * 0.28))
        return ft.Container(
            width=size,
            height=size,
            border_radius=ft.BorderRadius.all(20),
            gradient=ft.LinearGradient(
                begin=ft.Alignment.TOP_LEFT,
                end=ft.Alignment.BOTTOM_RIGHT,
                colors=[ft.Colors.BLUE_700, ft.Colors.CYAN_400],
            ),
            alignment=ft.Alignment.CENTER,
            content=ft.Stack(
                fit=ft.StackFit.EXPAND,
                controls=[
                    ft.Container(
                        alignment=ft.Alignment.CENTER,
                        content=ft.Icon(
                            ft.Icons.ROCKET_LAUNCH,
                            size=icon_size,
                            color=ft.Colors.WHITE,
                        ),
                    ),
                    ft.Container(
                        alignment=ft.Alignment.BOTTOM_CENTER,
                        padding=ft.Padding.only(left=8, right=8, bottom=10),
                        content=ft.Text(
                            label,
                            color=ft.Colors.WHITE,
                            weight=ft.FontWeight.BOLD,
                            size=12,
                            no_wrap=True,
                            max_lines=1,
                            overflow=ft.TextOverflow.ELLIPSIS,
                            text_align=ft.TextAlign.CENTER,
                        ),
                    ),
                ],
            ),
        )

    async def go_to_details(_):
        await page.push_route("/details")

    async def go_home(_):
        await page.push_route("/")

    def build_home_view() -> ft.View:
        return ft.View(
            route="/",
            appbar=ft.AppBar(title=ft.Text("Hero animation")),
            controls=[
                ft.Container(
                    expand=True,
                    alignment=ft.Alignment.CENTER,
                    content=ft.Column(
                        alignment=ft.MainAxisAlignment.CENTER,
                        horizontal_alignment=ft.CrossAxisAlignment.CENTER,
                        spacing=20,
                        controls=[
                            ft.Text("Tap the card to navigate"),
                            ft.GestureDetector(
                                mouse_cursor=ft.MouseCursor.CLICK,
                                on_tap=go_to_details,
                                content=ft.Hero(
                                    tag=hero_tag,
                                    content=build_card(130, "Open details"),
                                ),
                            ),
                        ],
                    ),
                )
            ],
        )

    def build_details_view() -> ft.View:
        return ft.View(
            route="/details",
            appbar=ft.AppBar(title=ft.Text("Details")),
            controls=[
                ft.Container(
                    expand=True,
                    alignment=ft.Alignment.CENTER,
                    content=ft.Column(
                        alignment=ft.MainAxisAlignment.CENTER,
                        horizontal_alignment=ft.CrossAxisAlignment.CENTER,
                        spacing=20,
                        controls=[
                            ft.Hero(
                                tag=hero_tag,
                                transition_on_user_gestures=True,
                                content=build_card(280, "Details"),
                            ),
                            ft.Button("Back", on_click=go_home),
                        ],
                    ),
                )
            ],
        )

    def route_change(e: ft.RouteChangeEvent = None):
        page.views.clear()
        page.views.append(build_home_view())
        if page.route == "/details":
            page.views.append(build_details_view())
        page.update()

    async def view_pop(e: ft.ViewPopEvent):
        if e.view is not None:
            page.views.remove(e.view)
            await page.push_route(page.views[-1].route)

    page.on_route_change = route_change
    page.on_view_pop = view_pop
    route_change()


if __name__ == "__main__":
    ft.run(main)

Summary by Sourcery

Add a new Hero control with shared-element route animations and support it end-to-end across Python and Flutter, including documentation, examples, and tests.

New Features:

  • Introduce a Hero layout control with typed HeroTag identifiers to enable shared-element animations between routes.
  • Expose the Hero and HeroTag symbols in the public Python API and wire the Hero control into the Flutter runtime.

Enhancements:

  • Document numerous existing type aliases and event-related types to clarify accepted value shapes and usage.
  • Improve integration test documentation formatting and expand CupertinoTimerPicker docs with a concrete example.
  • Refine Flet CLI archive extraction helper with clearer, multi-line docstring formatting.

Build:

  • Override the flet Flutter package dependency path in the flet_build_test example app for local development.

Documentation:

  • Add comprehensive Hero control documentation with embedded example code and reference images.
  • Register Hero and HeroTag in the type alias and controls navigation docs for discoverability.

Tests:

  • Add integration tests and golden-based screenshot/GIF generation for the basic Hero animation example.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've reviewed this pull request using the Sourcery rules engine

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Feb 11, 2026

Deploying flet-examples with  Cloudflare Pages  Cloudflare Pages

Latest commit: 974fcfd
Status: ✅  Deploy successful!
Preview URL: https://ad8089f5.flet-examples.pages.dev
Branch Preview URL: https://hero.flet-examples.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Feb 11, 2026

Deploying flet-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 974fcfd
Status: ✅  Deploy successful!
Preview URL: https://f0a0a7a0.flet-docs.pages.dev
Branch Preview URL: https://hero.flet-docs.pages.dev

View logs

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds Hero animation support to Flet, enabling smooth shared-element transitions between routes. Hero animations are a common UI pattern where a control morphs and moves between screens during navigation, creating a visually appealing continuity effect.

Changes:

  • Implements a new Hero control with tag, content, and transition_on_user_gestures properties
  • Adds comprehensive documentation with basic and gallery examples demonstrating Hero animations
  • Includes type alias documentation for various helper types across the codebase

Reviewed changes

Copilot reviewed 30 out of 34 changed files in this pull request and generated no comments.

Show a summary per file
File Description
sdk/python/packages/flet/src/flet/controls/core/hero.py Core Hero control implementation with tag validation and content visibility checks
packages/flet/lib/src/controls/hero.dart Flutter/Dart Hero widget implementation with proper error handling
packages/flet/lib/src/flet_core_extension.dart Registers Hero control in the Flet extension system
sdk/python/packages/flet/src/flet/init.py Exports Hero and HeroTag for public API
sdk/python/examples/controls/hero/basic.py Basic example demonstrating Hero animation between two views
sdk/python/examples/controls/hero/gallery.py Advanced gallery example with multiple Hero-animated items
sdk/python/packages/flet/integration_tests/examples/core/test_hero.py Integration tests with screenshot assertions and GIF generation
sdk/python/packages/flet/docs/controls/hero.md Documentation page with examples and API reference
sdk/python/packages/flet/mkdocs.yml Adds Hero to documentation navigation
sdk/python/packages/flet/docs/types/aliases.md Adds HeroTag type alias documentation
sdk/python/packages/flet/src/flet/controls/types.py Adds docstrings for Number, ResponsiveNumber, and IconDataOrControl type aliases
sdk/python/packages/flet/src/flet/controls/transform.py Adds docstrings for RotateValue, ScaleValue, and OffsetValue type aliases
sdk/python/packages/flet/src/flet/controls/padding.py Adds PaddingValue type alias documentation
sdk/python/packages/flet/src/flet/controls/margin.py Adds MarginValue type alias documentation
sdk/python/packages/flet/src/flet/controls/keys.py Adds KeyValue type alias documentation
sdk/python/packages/flet/src/flet/controls/duration.py Adds DurationValue and DateTimeValue type alias documentation
sdk/python/packages/flet/src/flet/controls/control_state.py Adds ControlStateValue type alias documentation
sdk/python/packages/flet/src/flet/controls/control_event.py Adds documentation for EventControlType, ControlEventHandler, EventHandler, and ControlEvent
sdk/python/packages/flet/src/flet/controls/context.py Adds documentation for the global context object
sdk/python/packages/flet/src/flet/controls/box.py Adds BoxShadowValue type alias documentation
sdk/python/packages/flet/src/flet/controls/border_radius.py Adds BorderRadiusValue type alias documentation
sdk/python/packages/flet/src/flet/controls/border.py Adds BorderSideStrokeAlignValue type alias documentation
sdk/python/packages/flet/src/flet/controls/blur.py Adds BlurValue type alias documentation
sdk/python/packages/flet/src/flet/controls/animation.py Adds AnimationValue type alias documentation
sdk/python/packages/flet/src/flet/controls/material/tooltip.py Adds TooltipValue type alias documentation
sdk/python/packages/flet/src/flet/controls/material/badge.py Adds BadgeValue type alias documentation
sdk/python/packages/flet/src/flet/controls/cupertino/cupertino_timer_picker.py Adds "Example:" label to code example for consistency
sdk/python/packages/flet/integration_tests/README.md Adds bash language identifier to code blocks
sdk/python/packages/flet-cli/src/flet_cli/utils/distros.py Reformats function signature and docstring for better readability
sdk/python/examples/apps/flet_build_test/pyproject.toml Adds Flutter dependency override for local flet package development
sdk/python/packages/flet/integration_tests/examples/core/golden/macos/hero/basic_1.png Golden image for initial home view
sdk/python/packages/flet/integration_tests/examples/core/golden/macos/hero/basic_2.png Golden image for details view
sdk/python/packages/flet/integration_tests/examples/core/golden/macos/hero/basic.gif Animated GIF demonstrating Hero transition

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@FeodorFitsner
Copy link
Contributor

I noticed there is a (double) yellow line under text during transition. Can we do anything about that?

Screen.Recording.2026-02-12.at.1.51.24.PM.mov

@ndonkoHenri
Copy link
Contributor Author

Looks like a known issue: https://forum.itsallwidgets.com/t/why-does-a-yellow-horizontal-line-appear-under-the-text-component-during-the-hero-animation-transition/3059/3

Will push a fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hero Animations

2 participants