-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
fix: handle cases when Animation.persist() does not exist #33282
base: master
Are you sure you want to change the base?
Conversation
The Animation.persist() API is in our full suport matrix but was added after browsers in our partial support matrix. As no polyfill exists for this feature and it cannot be compiled away this commit explicitly handles the case when the API does not exist. When .persist() is not available we short-circuit the animation, using the existing "is reduced motion" code path to make the animation effectively instant while still firing all animation events, etc.
@@ -2,6 +2,9 @@ import * as React from 'react'; | |||
import type { AnimationHandle, AtomMotion } from '../types'; | |||
|
|||
function useAnimateAtomsInSupportedEnvironment() { | |||
// eslint-disable-next-line @nx/workspace-no-restricted-globals | |||
const SUPPORTS_PERSIST = typeof window !== 'undefined' && typeof window.Animation?.prototype.persist === 'function'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not in love with having this here. Ideally it would live in global scope because SUPPORTS_PERSIST
will be constant for any given environment.
I moved it here because I could not find a good way to test it with Jest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could move this to a function check in another module and mock that moduile in the tests, but I don't mind keeping it like this ELEMENT_SUPPORTS_WEB_ANIMATIONS
is done similarly
📊 Bundle size reportUnchanged fixtures
|
Pull request demo site: URL |
@@ -0,0 +1,7 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🕵🏾♀️ visual regressions to review in the fluentuiv9 Visual Regression Report
Avatar Converged 2 screenshots
Image Name | Diff(in Pixels) | Image Type |
---|---|---|
Avatar Converged.badgeMask.chromium.png | 6 | Changed |
Avatar Converged.Badge Mask RTL.chromium.png | 2 | Changed |
Drawer 2 screenshots
Image Name | Diff(in Pixels) | Image Type |
---|---|---|
Drawer.Full Overlay Dark Mode.chromium.png | 2561 | Changed |
Drawer.overlay drawer full.chromium.png | 3320 | Changed |
}); | ||
|
||
animation.persist(); | ||
SUPPORTS_PERSIST && animation.persist(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about we just create a polyfill for https://developer.mozilla.org/en-US/docs/Web/API/Animation/commitStyles?
if (SUPPORTS_PERSIST) {
animation.persist();
} else {
const resultKeyframe = keyframes[keyframes.length - 1];
Object.assign(element.style, resultKeyframe);
}
This would ensure that we don't have weirdness when multiple animations are composed https://stackblitz.com/edit/typescript-hqxwu6?file=index.ts
@@ -19,10 +22,10 @@ function useAnimateAtomsInSupportedEnvironment() { | |||
fill: 'forwards', | |||
|
|||
...params, | |||
...(isReducedMotion && { duration: 1 }), | |||
...((isReducedMotion || !SUPPORTS_PERSIST) && { duration: 1 }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need to go through the reduced motion path? the animation will still work without persist
- the main consequence is that with for multiple animations that target the same property, the latest animation will replace older ones
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't strictly need to. My thinking is twofold:
- It reduces the likelihood of multiple animations targeting the same property. I don't know if this is really true in practice but if you had multiple, delayed animations it seems like it would be.
- If your browser doesn't support
.persist()
you don't really fully support this feature so we just opt you out of it. Using reduced motion ensures the functionality is observably the same (barring the multiple animation situation) as all animation events will fire, etc. This only affects browsers in our partial support matrix so a graceful degradation approach feels fine to me.
Open to changing this but as-is seems best to me.
Previous Behavior
The Animation.persist() API is in our full support matrix but was added after browsers in our partial support matrix. As no polyfill exists for this feature and it cannot be compiled away this commit explicitly handles the case when the API does not exist.
New Behavior
When .persist() is not available we short-circuit the animation, using the existing "is reduced motion" code path to make the animation effectively instant while still firing all animation events, etc.