Skip to content

Commit

Permalink
chore: fix safari spinner bug (#3834)
Browse files Browse the repository at this point in the history
* chore: fix safari spinner bug

* chore: refactor safari check

* fix: spinner animation bug

---------

Co-authored-by: TheSisb <[email protected]>
  • Loading branch information
nkrantz and TheSisb authored Apr 3, 2024
1 parent 33800d2 commit c020ede
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 14 deletions.
6 changes: 6 additions & 0 deletions .changeset/stupid-hats-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@twilio-paste/spinner": patch
"@twilio-paste/core": patch
---

[Spinner] Fix a bug that previously occured when a Safari user zoomed in on a page with a Spinner. The animated track moving around the Spinner circle would lose its center and appear off of the circle. This was due to the fact that Safari does not accept "center" as a value for the `transformOrigin` property. The fix was to remove the extra animations for Safari windows only.
19 changes: 17 additions & 2 deletions packages/paste-core/components/spinner/src/Spinner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ const Spinner = React.forwardRef<HTMLDivElement, SpinnerProps>(
const showTimer = setTimeout(() => setShow(true), delay);
return () => clearTimeout(showTimer);
}, [delay]);

// TODO: update animations so we dont need to check browser and render different animations
const [isSafari, setIsSafari] = React.useState<boolean | null>(null);
React.useEffect(() => {
setIsSafari(navigator.userAgent.includes("Safari") && !navigator.userAgent.includes("Chrome"));
}, []);
if (isSafari == null) {
return null;
}

return (
<IconWrapper
as={as}
Expand All @@ -68,11 +78,16 @@ const Spinner = React.forwardRef<HTMLDivElement, SpinnerProps>(
aria-hidden={decorative}
ref={ref}
>
<StyledSvg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" aria-labelledby={titleId}>
<StyledSvg
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
aria-labelledby={titleId}
isSafari={isSafari}
>
{title ? <title id={titleId}>{title}</title> : null}
<g strokeWidth={borderWidth40} stroke="currentColor" strokeLinecap="round" fill="transparent">
<StyledCircleTrack {...circleGeometry} />
<AnimatedStyledCircle show={show} {...circleGeometry} />
<AnimatedStyledCircle show={show} {...circleGeometry} isSafari={isSafari} />
</g>
</StyledSvg>
</IconWrapper>
Expand Down
12 changes: 12 additions & 0 deletions packages/paste-core/components/spinner/src/keyframes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,15 @@ export const CircleKeyframes = keyframes`
transform: rotateZ(360deg);
}
`;

export const SafariSvgKeyframes = keyframes`
0%,
75% {
stroke-dashoffset: 90%;
}
100% {
stroke-dashoffset: 90%;
transform: rotate(360deg);
}
`;
33 changes: 21 additions & 12 deletions packages/paste-core/components/spinner/src/styled.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
import { styled } from "@twilio-paste/styling-library";

import { circleCircumference } from "./constants";
import { CircleKeyframes, SvgKeyframes } from "./keyframes";
import { CircleKeyframes, SafariSvgKeyframes, SvgKeyframes } from "./keyframes";

export const StyledCircleTrack = styled.circle({
transformOrigin: "center",
opacity: 0.25,
});

export const AnimatedStyledCircle = styled.circle<{ show: boolean }>(({ show }) => ({
transformOrigin: "center",
animation: `1.5s ease-in-out infinite both ${CircleKeyframes}`,
strokeDasharray: circleCircumference,
opacity: show ? 1 : 0,
}));
/*
* AnimatedStyledCircle and StyledSvg use different animations for Safari because
* Safari does not respect the `transformOrigin: "center"` and causes bugs
*/

export const AnimatedStyledCircle = styled.circle<{ show: boolean; isSafari: boolean }>(({ show, isSafari }) => {
return {
transformOrigin: "center",
animation: isSafari ? "none" : `1.5s ease-in-out infinite both ${CircleKeyframes}`,
strokeDasharray: circleCircumference,
opacity: show ? 1 : 0,
};
});

export const StyledSvg = styled.svg({
height: "100%",
width: "100%",
display: "block",
animation: `4.25s linear infinite both ${SvgKeyframes}`,
export const StyledSvg = styled.svg<{ isSafari: boolean }>(({ isSafari }) => {
return {
height: "100%",
width: "100%",
display: "block",
animation: isSafari ? `1s infinite linear ${SafariSvgKeyframes}` : `4.25s linear infinite both ${SvgKeyframes}`,
};
});

0 comments on commit c020ede

Please sign in to comment.