Skip to content

feat(fab-button): add animated prop to disable state transitions - #31743

Open
ShaneK wants to merge 2 commits into
feature-9.1from
FW-7511
Open

ShaneK wants to merge 2 commits into
feature-9.1from
FW-7511

Conversation

@ShaneK

@ShaneK ShaneK commented Nov 12, 2026 •

Copy link
Copy Markdown
Member

Issue number: resolves #20177


What is the current behavior?

Currently, the fab button always rotates and scales between its content and the close icon when a fab list opens. That transition lives in the shadow DOM, so there's no way to turn it off, and it ignores both the global animated: false config and prefers-reduced-motion.

What is the new behavior?

  • Added an animated prop to ion-fab-button. When it's false, or the global animated config is false, the button doesn't transition at all.
  • With prefers-reduced-motion: reduce, the content and close icon crossfade instead of rotating and scaling, and the iOS press no longer scales the button. This follows the reduced motion rule in the animations and gestures design doc, which is to remove movement and scaling but keep short opacity changes.

Does this introduce a breaking change?

  • Yes
  • No

But it is a new feature, which is why it's pointed at feature-9.1

Other information

The prop only affects the button it's set on, so buttons inside an ion-fab-list need it too. The md ripple still plays with animated="false" because it comes from ion-ripple-effect rather than the button's transitions, but the global animated: false config already turns it off.

To check reduced motion, turn on "Emulate CSS media feature prefers-reduced-motion" in the DevTools Rendering panel.

Current dev build:

9.0.11-dev.11794501674.16819717

Animation test page (MD)
Animation test page (iOS)
Animation test page with animated: false config

Docs

Related docs PR

@ShaneK
ShaneK requested a review from a team as a code owner November 12, 2026 14:53
@ShaneK
ShaneK requested a review from brandyscarney November 12, 2026 14:53
@vercel

vercel Bot commented Nov 12, 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 Nov 12, 2026 3:55pm UTC

Request Review

@github-actions github-actions Bot added package: core @ionic/core package package: angular @ionic/angular package package: vue @ionic/vue package labels Nov 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please add an inner part to .button-inner. It's the only element in the fab button that transitions without a part, so apps can't restyle that transition from outside.

<span class="button-inner" part="inner">
 * @part inner - The wrapper around the button's content, which transitions to the close icon when a fab list opens.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  • The transition is gated on .fab-button-animated but the ios press --transform: scale(1.1) is not, so with animated="false" the button jumps to 1.1x on press instead of staying still
  • The reduced motion transform: none has the same gate, so a non-animated button still jumps in size when the user prefers reduced motion

Please move --transform in fab-button.ios.scss to its own rule gated on the animated class:

:host(.ion-activated) {
  --box-shadow: #{$fab-ios-box-shadow-activated};
  --transition: #{$fab-ios-transition-activated};
}

/**
 * Only scale on press when the button animates,
 * otherwise it would jump in size.
 */
:host(.fab-button-animated.ion-activated) {
  --transform: #{$fab-ios-transform};
}

And a test for it in the ios describe at the bottom of test/animation/fab-button.e2e.ts:

    test('should not scale the pressed button when animated is false', async ({ page }) => {
      await page.setContent(
        `
        <ion-fab-button animated="false">
          <ion-icon name="add"></ion-icon>
        </ion-fab-button>
      `,
        config
      );

      const fabButton = page.locator('ion-fab-button');
      await fabButton.evaluate((el) => el.classList.add('ion-activated'));

      expect(await getStyles(fabButton, 'transform')).toMatchObject({ native: 'none' });
    });

This branch was successfully deployed

1 active deployment
Preview — 6819717a Deployed Nov 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: angular @ionic/angular package package: core @ionic/core package package: vue @ionic/vue package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants