Skip to content

Commit

Permalink
add animations to our counter (#824)
Browse files Browse the repository at this point in the history
  • Loading branch information
stopachka authored Feb 7, 2025
1 parent 0005e4a commit dd2d679
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 23 deletions.
70 changes: 65 additions & 5 deletions client/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 75 additions & 0 deletions client/www/components/AnimatedCounter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { MotionValue, motion, useSpring, useTransform } from 'motion/react';
import { useEffect } from 'react';

export default function AnimatedCounter({
number,
height,
}: {
number: number;
height: number;
}) {
const digits = `${number}`.split('');

return (
<div className="flex space-x-2 overflow-hidden">
{digits.map((digit, index) => {
return <Digit key={index} value={+digit} height={height} />;
})}
</div>
);
}

function Digit({ value, height }: { value: number; height: number }) {
const animatedValue = useSpring(value);
useEffect(() => {
animatedValue.set(value);
}, [animatedValue, value]);
const padding = 10;
const fontSize = height - padding;
return (
<div
className="font-mono border border-black leading-none flex items-center justify-center"
style={{ width: 28, height: height, fontSize, padding }}
>
<div style={{ height }} className="relative w-[1ch] tabular-nums">
{Array.from({ length: 10 }, (_, i) => i).map((digit) => (
<Number
key={digit}
mv={animatedValue}
number={digit}
height={height}
/>
))}
</div>
</div>
);
}

function Number({
mv,
number,
height,
}: {
mv: MotionValue;
number: number;
height: number;
}) {
const y = useTransform(mv, (latest) => {
const placeValue = latest % 10;
const offset = (10 + number - placeValue) % 10;
let memo = offset * height;
if (offset > 5) {
memo -= 10 * height;
}
return memo;
});

return (
<motion.span
style={{ y }}
className="absolute inset-0 flex items-center justify-center"
>
{number}
</motion.span>
);
}
1 change: 1 addition & 0 deletions client/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"json5": "^2.2.3",
"lodash": "^4.17.21",
"marked": "^4.0.12",
"motion": "^12.4.0",
"next": "^15.0.3",
"prism-react-renderer": "^1.3.5",
"prismjs": "^1.27.0",
Expand Down
25 changes: 7 additions & 18 deletions client/www/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import config from '@/lib/config';
import MuxPlayer from '@mux/mux-player-react';
import * as muxVideos from '@/lib/muxVideos';
import useTotalSessionsCount from '@/lib/hooks/useTotalSessionsCount';
import AnimatedCounter from '@/components/AnimatedCounter';

type EmojiName = keyof typeof emoji;

Expand Down Expand Up @@ -116,31 +117,19 @@ const ActiveSessionsCallout = () => {
const { isLoading, error, data } = useTotalSessionsCount({
refreshSeconds: 3,
});
const height = 38;

if (isLoading || error || data <= 0) {
return <div className="h-8"></div>;
return <div style={{ height }}></div>;
}

const digits = data.toString().split('');

return (
<div className="inline-flex items-center space-x-2 h-8">
<div className="inline-flex gap-1">
{digits.map((d, i) => {
return (
<div
key={i}
className="text-2xl font-mono w-7 h-8 border border-black leading-none flex items-center justify-center"
>
<span>{d}</span>
</div>
);
})}
</div>
<div>sessions are connected on Instant right now</div>
<div className="inline-flex items-center space-x-2" style={{ height }}>
<AnimatedCounter number={data} height={38} />
<div className="flex-1">sessions are connected on Instant right now</div>
</div>
);
};

function LandingHero() {
return (
<div className="pb-16 pt-8">
Expand Down

0 comments on commit dd2d679

Please sign in to comment.