Want to set up GraphQL subscriptions on GitHub with your custom GitHub app?
Here's a video showing how to set that up:
This is also a test of embedding mov files directly in GitHub issues to be displayed in OneBlog.
I have a project, source code shots, that turns your source code into a png as you type. It takes a little bit of time to generate the image, so I wanted to indicate to the user that some work was being done to give them a visual cue that the image on the page was going to update.
I made a simple loading spinner component, using a css animation, and rendered it while the image was being fetched.
The code looked something like
/* styles.css */
@keyframes throb {
0% {
transform: scale(0.1, 0.1);
opacity: 0;
}
50% {
opacity: 0.8;
}
100% {
transform: scale(1.2, 1.2);
opacity: 0;
}
}
.loading {
animation: throb 1s ease-out;
animation-iteration-count: infinite;
opacity: 0;
border: 3px solid #999;
border-radius: 30px;
height: 16px;
width: 16px;
}
export default function App() {
const [isLoading, setIsLoading] = React.useState(false);
const [code, setCode] = React.useState("");
React.useEffect(() => {
let canceled = false;
setIsLoading(true);
// Simulate getting the image for the code
new Promise((resolve) =>
setTimeout(resolve, Math.random() * 300 + 100)
).then(() => {
if (!canceled) {
setIsLoading(false);
}
});
return () => {
canceled = true;
};
}, [code, setIsLoading]);
return (
<div>
<textarea value={code} onChange={(e) => setCode(e.target.value)} />
<div
className="loading"
style={{ display: isLoading ? "block" : "none" }}
/>
</div>
);
}
I thought I was done, but the spinner was so annoying I almost threw it out. As I typed, the animation would start and stop, creating an annoying jittery effect.
Type a few characters at a time into the textarea below to see what I mean:
What I would like is for the animation to continue to completion, even if we’re finished loading. That way the animation will never flash in and out.
A little google searching reveals a family of animation hooks that look like they could be useful. There is an onanimationiteration
event, accessible with the onAnimationIteration
React prop on our loading div
, that will fire on every round of the animation. In our case, it will fire every second.
Instead of hiding our loading spinner when isLoading
switches to false, we can wait for the onAnimationIteration
hook to fire and hide the loading spinner in the callback.
The relevant change looks like
<div
className="loading"
onAnimationIteration={() => {
if (!isLoading) {
setPlayAnimation(false);
}
}}
style={{ display: playAnimation ? "block" : "none" }}
/>
Try it below:
You can also try it out at Source Code Shots1.
Do you have a better way to build an elegant loading spinner? Let me know in the comments below.