Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: multi-stage motion with createMotionComponent not returning onMotionStart/onMotionFinish for multiple stages #33410

Open
2 tasks done
kellygorr opened this issue Dec 4, 2024 · 1 comment

Comments

@kellygorr
Copy link
Contributor

kellygorr commented Dec 4, 2024

Component

Motion

Package version

9.51.1

React version

18.3.1

Environment

System:
    OS: macOS 15.1.1
    CPU: (11) arm64 Apple M3 Pro
    Memory: 132.47 MB / 18.00 GB
    Shell: 5.9 - /bin/zsh
  Browsers:
    Chrome: 131.0.6778.87
    Edge: 131.0.2903.70
    Safari: 18.1.1
  npmPackages:
    @fluentui/react-components: ^9.51.1 => 9.54.17

Current Behavior

Hi! I am using createMotionComponent to create a multi-stage animation (using AtomMotion[]). I need to know when each part of the multi-stage animation starts/ends, but onMotionStart/onMotionFinish callbacks are only returning null at the beginning/end of the full animation.

This means that, even though the motion is playing correctly, all the AtomMotion objects must all be starting and ending at the same time instead of based on their delay. Unless there is some other prop I should be using to make it run sequentially? There are no examples of a multi-stage animations in the documentation.

const sendButtonMotion: AtomMotionFn = ({ element }) => {
  return [
  	{
  		keyframes: [{ transform: `scale(1)` }, { transform: `scale(2)` }],
  		duration: 1000,
  		easing: motionTokens.curveLinear,
  		delay: 0,
  	},
  	{
  		keyframes: [{ transform: 'scale(2)' }, { transform: 'scale(0)' }],
  		duration: 2000,
  		easing: motionTokens.curveEasyEase,
  		delay: 1000,
  	},
  	{
  		keyframes: [{ transform: 'scale(0)' }, { transform: 'scale(1)' }],
  		duration: 4000,
  		easing: motionTokens.curveEasyEase,
  		delay: 3000,
  	},
  ]
}

const SendButtonMotion = createMotionComponent(sendButtonMotion)
export const SendMotionComponent = () => {
  const [isSending, setIsSending] = React.useState(false)
  const motionRef = React.useRef<MotionImperativeRef>()
  
  React.useEffect(() => {
    // stop animation from running on first render
    motionRef.current?.setPlayState('paused')
  }, [])
  
  React.useEffect(() => {
    if (isSending) {
      motionRef.current?.setPlayState('running')
    }
  }, [isSending])
  
  return (
  
    <SendButtonMotion
      imperativeRef={motionRef}
      onMotionStart={(ev) => console.log('motion start', ev)}
      onMotionFinish={(ev) => console.log('motion end', ev)}
    >
      <Button
        icon={<SendFilled />}
        content="Send"
        appearance="transparent"
        onClick={() => setIsSending(!isSending)}
      />
    </SendButtonMotion>
  
  )
}

Video:
https://github.com/user-attachments/assets/a460c8c0-be49-4eb5-b125-f83b0daffcda

Expected Behavior

The animation is running correctly but, the onMotionStart/onMotionFinish callbacks aren't working as expected

When using delay as a prop for AtomMotion, I would expect this to delay the start of the animation (or at least preserve when the animation starts running). (Unless there is another prop I should be using to make the motion run sequentially?)

For onMotionFinish it says: Callback that is called when the whole motion finishes. A motion definition can contain multiple animations and therefore multiple "finish" events. The callback is triggered once all animations have finished with "null" instead of an event object to avoid ambiguity.

Based on this comment, when you have a multi-stage animation, I would expect there to be multiple finish events returned with the final event being null. (Same idea for onMotionStart)

Reproduction

https://stackblitz.com/edit/wh9k5r?file=src%2Fexample.tsx

Steps to reproduce

  1. The animation plays automatically (the animation is playing correctly. Each stage of the animation is running when it should).
  2. onMotionFinish/onMotionStart is logged. Only receiving null at beginning and at end of the full animation, even though there is more than one stage to the motion.

Are you reporting an Accessibility issue?

None

Suggested severity

High - No workaround

Products/sites affected

No response

Are you willing to submit a PR to fix?

no

Validations

  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • The provided reproduction is a minimal reproducible example of the bug.
@miroslavstastny
Copy link
Member

@layershifter and @ling1726 to discuss the use case.

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

No branches or pull requests

5 participants