-
Notifications
You must be signed in to change notification settings - Fork 949
@radix-ui/react-presence doesn't handle the animationend
event correctly when keyframe has escapable character
#2763
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
Comments
Do you know what sort of escaping it's currently doing? ie. is there a built-in function we could call to get the same result? |
Not entirely sure, from what I could get from logging what the function sees seems to come from |
Fixes radix-ui#2763. Using [CSS.escape](https://developer.mozilla.org/en-US/docs/Web/API/CSS/escape_static_method). As I checked, this API is supported in all browsers even in the [2022 browserslist targets](radix-ui#1019 (comment)) of this project. Further explanation of the bug: `getComputedStyle()` returns a `CSSStyleDeclaration``, which is serialized according to the spec. Meanwhile, the values from `AnimationEvent` are not required to be serialized (which makes sense, as it's intended for JavaScript usage, where escaping for CSS syntax is unnecessary). Therefore the `animationName` is returned as-is in the event handler, causing the mismatch.
Fixes radix-ui#2763. Using [CSS.escape](https://developer.mozilla.org/en-US/docs/Web/API/CSS/escape_static_method). As I checked, this API is supported in all browsers even in the [2022 browserslist targets](radix-ui#1019 (comment)) of this project. Further explanation of the bug: `getComputedStyle()` returns a `CSSStyleDeclaration`, which is serialized according to the spec. Meanwhile, the values from `AnimationEvent` are not required to be serialized (which makes sense, as it's intended for JavaScript usage, where escaping for CSS syntax is unnecessary). Therefore the `animationName` is returned as-is in the event handler, causing the mismatch.
I opened a PR to fix this issue using Here's the fixed example with patches applied: https://stackblitz.com/edit/vitejs-vite-dm8pji1o (I couldn't figure out how to apply patches in CodeSandbox, so I recreated a StackBlitz example) |
Fixes radix-ui#2763. Using [CSS.escape](https://developer.mozilla.org/en-US/docs/Web/API/CSS/escape_static). As I checked, this API is supported in all browsers even in the [2022 browserslist targets](radix-ui#1019 (comment)) of this project. Further explanation of the bug: `getComputedStyle()` returns a `CSSStyleDeclaration`, which is serialized according to the spec. Meanwhile, the values from `AnimationEvent` are not required to be serialized (which makes sense, as it's intended for JavaScript usage, where escaping for CSS syntax is unnecessary). Therefore the `animationName` is returned as-is in the event handler, causing the mismatch.
Bug report
Current Behavior
When using an exit animation on @radix-ui/react-dialog for the overlay, we noticed that if the keyframe has a special character (in our case
\+
generated from webpack hashing classes using base64) in its name, Presence does not correctly unmount the element, but is rather left hanging for the animation to finish. This is due to the Presence component usinggetComputedStyles
which seems to escape those character and fails to correctly resolveisCurrentAnimation
due to the mismatch between the two strings (check screenshot for the example we have seen), being left inunmountSuspended
state.Expected behavior
When dialog is closed, all Presence elements should be unmounted correctly.
Reproducible example
Very crude example with dialog. To reproduce, open the modal, click "Save changes" and you will see the exit animation playing correctly, but the overlay element (
.DialogOverlay
) not unmounting. The correct behaviour can be replicated by changing the keyframeoverlayFadeOut\+R8
(and the consuming animation in.DialogOverlay[data-animate="true"]
) to not have the\+
(i.e.overlayFadeOutR8
)Suggested solution
A potential solution could be not to use
event.animationName
in theanimationend
handler but rather to usegetAnimationName(getComputedStyles(event.target))
, or simply to escape theevent.animationName
similarly to whatgetComputedStyles
returns.Additional context
Your environment
Same as sandbox
The text was updated successfully, but these errors were encountered: