Skip to content

fix(transition): make large title animations work in every theme - #31559

Open
thetaPC wants to merge 5 commits into
FW-6863from
FW-6863-animations
Open

thetaPC wants to merge 5 commits into
FW-6863from
FW-6863-animations

Conversation

@thetaPC

@thetaPC thetaPC commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Issue number: resolves internal


What is the current behavior?

The iOS large title animations rely on the iOS theme's title stylesheet, so they only look right in the iOS theme. With iOS mode and the md or ionic theme, the page transition squashes the title (width scale 0.20 instead of about 0.5), a centered title jumps to the screen edge, and the overscroll stretch slides the title 17px past its padding.

What is the new behavior?

  • The iOS page transition sets up what it needs itself: it measures the title's text, copies the title's color, font and padding to its copy, starts both copies where the text is rendered so a centered title morphs in place, and hides the back button with visibility so a title placed next to it doesn't shift.
  • The header stretch sets its own transform origin from the title's text alignment.
  • Removes the title's animation-only tokens and the cloned title rule, which nothing reads anymore.
  • Fixes the ionic toolbar briefly showing a centered title off-center while the back button renders.
  • Adds a title transition test page.

This is the first proof of concept for FW-7295: animations set up what they need instead of relying on a theme's stylesheet.

Does this introduce a breaking change?

  • Yes
  • No

Other information

Open each before and after link side by side. For the pull down rows, use Safari on a Mac with a trackpad in Responsive Design Mode for a phone-sized view, or the iOS Simulator. With the page at the top, do a two-finger swipe down over the page content so it bounces past the top. Chrome and Firefox, including their device modes, can't scroll past the top, so the title won't grow there.

Check Before After What to do and look for
Page transition, ionic theme before after Tap "Go (matching back text)", then the back button. Before, the centered big title jumps to the left edge and gets squeezed narrow on its way to the back button. After, it shrinks and slides from where it sits, and grows back the same way
Page transition, md theme before after Tap "Go (matching back text)", then the back button. Before, the big title doesn't move to the back button. After, it shrinks and slides into it, and grows back the same way
Page transition, ios theme before after Tap "Go (matching back text)", then the back button. Looks the same on both
Toolbar centering before after Tap "Go (matching back text)". Before, the "Message" title appears right of center for a moment, then jumps to the center. After, it's centered from the start
Pull down, md theme before after Pull down at the top of the page. Before, the growing title's left edge moves past the page margin. After, the left edge stays in place
Pull down, md theme, RTL before after Same as above, on the right edge
Pull down, ios theme before after Pull down at the top of the page. Looks the same on both
Pull down, ionic theme before after Pull down at the top of the page. Looks the same on both

@thetaPC
thetaPC added this pull request to stack #31538 October 9, 2026 21:46
@vercel

vercel Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
ionic-framework Ready Ready Preview Oct 12, 2026 3:42pm UTC

Request Review

@github-actions github-actions Bot added the package: core @ionic/core package label Oct 9, 2026
@thetaPC thetaPC changed the title Fw 6863 animations fix(transition): make large title animations work in every theme Oct 9, 2026
@thetaPC
thetaPC force-pushed the FW-6863-animations branch from 5974626 to 04dc471 Compare October 10, 2026 02:29
@thetaPC
thetaPC force-pushed the FW-6863-animations branch from 04dc471 to fe6013d Compare October 12, 2026 15:15
@thetaPC
thetaPC marked this pull request as ready for review October 12, 2026 18:14
@thetaPC
thetaPC requested a review from a team as a code owner October 12, 2026 18:14
@thetaPC
thetaPC requested a review from brandyscarney October 12, 2026 18:14

@brandyscarney brandyscarney left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Added a few minor requests but this is looking good!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why did the tests lose padding on this branch? It doesn't look like the test itself changed, are we not respecting the ion-padding class?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Are the font differences between the two branches expected?

next PR branch
next branch

}

// The slotted content, not the slots, so setting the slot widths doesn't re-trigger it
this.el.querySelectorAll(':scope > [slot]').forEach((el) => this.slotContentObserver!.observe(el));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This only observes slot content that exists when it runs (at load, or when titlePlacement changes), so buttons added later with *ngIf or conditional rendering aren't watched. The has-*-content classes already had this limitation, so it isn't a regression. But the comment above this function says it handles "a back button that renders after the toolbar", which is only true if the element is already in the DOM. Could you either reword the comment or watch for slot changes too?


disconnectedCallback() {
this.slotContentObserver?.disconnect();
this.slotContentObserver = undefined;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This sets the observer to undefined on disconnect, but it's only created again in updateSlotClasses(), which runs from componentWillLoad and componentDidLoad. Stencil runs those once, so if the toolbar is removed and re-inserted (framework portals, Vue , a cached page moved in the DOM), the centering fix stops working. Could you recreate it in connectedCallback, for example by calling this.observeSlotContent() there when getTitlePlacement() === 'center'?

background: toolbar.shadowRoot!.querySelector('.toolbar-background'),
ionTitleEl,
innerTitleEl: ionTitleEl ? ionTitleEl.shadowRoot!.querySelector('.toolbar-title') : null,
innerTitleOrigin: ionTitleEl ? getTitleOrigin(ionTitleEl) : undefined,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: this runs getComputedStyle on every toolbar title in the header, but only large titles use the origin (scaleLargeTitles returns early otherwise). Could it be:

Suggested change
innerTitleOrigin: ionTitleEl ? getTitleOrigin(ionTitleEl) : undefined,
innerTitleOrigin: ionTitleEl && isLargeTitle(ionTitleEl) ? getTitleOrigin(ionTitleEl) : undefined,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you add two cases here? Both cover behavior this PR moved out of CSS and into JavaScript, and nothing else tests them:

  1. Backward transition: going back to the large-title page, which is the most common case. largeTitleStartShift changed the start and end math in both directions, but only forward is tested, and backward uses a different measurement (the entering title instead of the leaving one).
  2. Color and font on the copy: the removed :host(.title-size-large.ion-cloned-element) rule is now replaced by copying getComputedStyle values. Could you check that the copy's computed color and font-family match the title's, with color="primary" and both hues ("Cycle title color" does this), including the ionic theme since it sets its own font? Screenshots won't catch this because they never capture a transition in progress.

This branch was successfully deployed

1 active deployment
Preview — fe6013db Deployed Oct 12, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: core @ionic/core package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants