Skip to content

feat(superdeck): animate images between slides - #136

Merged
leoafarias merged 4 commits into
mainfrom
feat/automatic-image-hero-transitions
Sep 28, 2026
Merged

leoafarias merged 4 commits into
mainfrom
feat/automatic-image-hero-transitions

Conversation

@leoafarias

Copy link
Copy Markdown
Collaborator

Summary

  • Automatically pair standalone Markdown images and built-in @image blocks by image order across slides, so they animate through Hero transitions without author-supplied tags. Explicit Markdown Hero tags still take precedence.
  • Share an image flight that blends different sources within Flutter's measured Hero bounds, including cache-resolved images. Static slide capture stays free of Heroes.
  • Document the behavior and cover forward/reverse navigation, tag precedence, static rendering, and flight geometry.

Validation

  • fvm flutter test --exclude-tags ci-excluded --no-pub in packages/superdeck — passed (803 tests, 1 skipped).
  • fvm dart run melos run analyze:dart — passed across all 7 packages.
  • fvm dart run melos run fix — Dart fix found nothing; DCM could not run because its license is not activated in this environment.

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Visit the preview URL for this PR (updated for commit 871e215):

https://superdeck-dev--pr136-feat-automatic-image-n0xwfadv.web.app

(expires Sun, 25 Oct 2026 19:01:08 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: bd68fc230762285849207e7e120aaf87cd4ca2f9

ImageHeroPositions counted only top-level standalone images, while
ImageBlockSyntax stamped every standalone image, including ones nested
in blockquotes, alerts, and list items. A quoted image next to a
top-level image therefore produced two `superdeck:image:0` Heroes and
Flutter threw "multiple heroes that share the same tag" on the next
slide transition. Alerts were off by one because their nested body
reused the same image builder counter.

Stamp the automatic position only when the image is parsed at the top
level, give alert bodies a nested syntax list that never stamps it, and
count positions with the same shared syntax list the renderer uses.
Nested images still render and still honor explicit `{.tag}` markers.
Automatic image Hero transitions stay on by default. Setting
`DeckOptions(animateImages: false)` stops untagged standalone Markdown
images and `@image` blocks from taking automatic Hero tags, while
explicit Markdown Hero tags keep animating. The option reaches the
renderers through SlideConfiguration, like `debug`.
@leoafarias

Copy link
Copy Markdown
Collaborator Author

Pushed three commits addressing the review of this PR.

Fix: nested standalone images no longer share automatic Hero tags

ImageHeroPositions counted only top-level standalone images, but ImageBlockSyntax stamped data-superdeck-block-image on every standalone image line, including lines nested in blockquotes, alerts, and list items. A slide with > ![q](a.png) and a top-level ![b](b.png) rendered two superdeck:image:0 Heroes. The next transition then threw "There are multiple heroes that share the same tag within a subtree". Alert images were off by one because the alert's nested MarkdownBody reused the same builder counter.

  • ImageBlockSyntax stamps the automatic position only at the top level (parser.parentSyntax == null), and only when assignsHeroPosition is true.
  • markdownBlockSyntaxes() in markdown_element_builders_registry.dart is now the single syntax list shared by rendering and ImageHeroPositions. SpecMarkdownBuilders.nestedBlockSyntaxes never stamps positions, and alert bodies use it.
  • ImageHeroPositions counts exactly the top-level elements that carry the attribute.
  • Nested images still render (blockquote and alert) and still honor explicit {.tag} markers. List-item images were already dropped by the li text builder before this PR, and that is unchanged.

New option: DeckOptions.animateImages (default true)

DeckOptions(animateImages: false) turns off automatic image Heroes for the whole deck. It covers standalone Markdown images and @image blocks. Explicit Markdown Hero tags keep working. The option is passed through SlideConfiguration the same way as debug.

Tests added

  • Nested blockquote, alert, and list images take no automatic position (exactly one Hero, superdeck:image:0), and navigating to the next slide raises no exception. Against 0bdcd530 this test fails with the duplicate-tag FlutterError.
  • An explicit {.chosen} tag inside a blockquote still produces a Hero.
  • With animateImages: false, a Markdown image and an @image block produce no Heroes, and an explicit {.chosen} image still does.
  • DeckOptions default, copyWith, and equality; SlideConfigurationBuilder passes the value to every slide.

Commands run

cd packages/superdeck
fvm flutter test test/src/markdown/hero_transition_test.dart test/src/deck/deck_options_test.dart \
  test/src/deck/slide_configuration_builder_test.dart --no-pub --reporter expanded   # 42 passed, 1 skipped
fvm flutter test --exclude-tags ci-excluded --no-pub                                # 809 passed, 1 skipped
cd ../.. && fvm dart run melos run analyze:dart                                     # No issues found in all 7 packages
fvm dart run melos run fix                                                          # dart fix: no changes; DCM fix not run (no licence locally)

Docs updated in docs/reference/deck-options.mdx, docs/reference/markdown-syntax.mdx, and the superdeck-presentations authoring reference.

@leoafarias
leoafarias added this pull request to stack #139 September 25, 2026 19:39
@leoafarias
leoafarias merged commit d87d3b0 into main Sep 28, 2026
8 checks passed
@leoafarias
leoafarias deleted the feat/automatic-image-hero-transitions branch September 28, 2026 01:36
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.

1 participant