From 432d04120305da91b2faead4885bca430e515dd2 Mon Sep 17 00:00:00 2001 From: Ady Beraud <102751374+ady-beraud@users.noreply.github.com> Date: Fri, 12 Apr 2024 10:27:32 +0200 Subject: [PATCH] Added loader and counter animations (#4931) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added loader animation: https://github.com/twentyhq/twenty/assets/102751374/c569762a-f512-4995-ac4d-47570bacdcaa Added counter animation: https://github.com/twentyhq/twenty/assets/102751374/7d96c625-b56a-4ef6-8042-8e71455caf67 Co-authored-by: Ady Beraud Co-authored-by: Félix Malfait --- .../contributors/AnimatedFigures.tsx | 50 +++++++++++++++++++ .../_components/contributors/AvatarGrid.tsx | 24 +++++---- .../contributors/ContentContainer.tsx | 8 ++- .../_components/contributors/ProfileInfo.tsx | 9 ++-- .../src/app/_components/releases/Release.tsx | 25 ++++++---- .../_components/ui/layout/LoaderAnimation.tsx | 19 +++++++ 6 files changed, 110 insertions(+), 25 deletions(-) create mode 100644 packages/twenty-website/src/app/_components/contributors/AnimatedFigures.tsx create mode 100644 packages/twenty-website/src/app/_components/ui/layout/LoaderAnimation.tsx diff --git a/packages/twenty-website/src/app/_components/contributors/AnimatedFigures.tsx b/packages/twenty-website/src/app/_components/contributors/AnimatedFigures.tsx new file mode 100644 index 000000000..91e962b22 --- /dev/null +++ b/packages/twenty-website/src/app/_components/contributors/AnimatedFigures.tsx @@ -0,0 +1,50 @@ +import { useEffect, useRef } from 'react'; +import styled from '@emotion/styled'; +import { + animate, + motion, + useInView, + useMotionValue, + useTransform, +} from 'framer-motion'; + +import { Theme } from '@/app/_components/ui/theme/theme'; + +const Container = styled.div` + display: flex; + flex-direction: row; + font-size: 56px; + font-weight: 700; + color: ${Theme.text.color.secondary}; + + @media (max-width: 810px) { + font-size: 32px; + } +`; + +interface AnimatedFiguresProps { + value: number; + children?: React.ReactNode; +} + +export const AnimatedFigures = ({ value, children }: AnimatedFiguresProps) => { + const count = useMotionValue(0); + const rounded = useTransform(count, (latest) => { + return Math.round(latest); + }); + const ref = useRef(null); + const inView = useInView(ref); + + useEffect(() => { + if (inView) { + animate(count, value, { duration: 2 }); + } + }, [count, inView, value]); + + return ( + + {rounded} + {children} + + ); +}; diff --git a/packages/twenty-website/src/app/_components/contributors/AvatarGrid.tsx b/packages/twenty-website/src/app/_components/contributors/AvatarGrid.tsx index 4f98abf43..48dbe4120 100644 --- a/packages/twenty-website/src/app/_components/contributors/AvatarGrid.tsx +++ b/packages/twenty-website/src/app/_components/contributors/AvatarGrid.tsx @@ -3,6 +3,8 @@ import styled from '@emotion/styled'; import Link from 'next/link'; +import MotionContainer from '@/app/_components/ui/layout/LoaderAnimation'; + export interface User { id: string; avatarUrl: string; @@ -67,16 +69,18 @@ import React from 'react'; const AvatarGrid = ({ users }: { users: User[] }) => { return ( - - {users.map((user) => ( - - - {user.id} - {user.id} - - - ))} - + + + {users.map((user) => ( + + + {user.id} + {user.id} + + + ))} + + ); }; diff --git a/packages/twenty-website/src/app/_components/contributors/ContentContainer.tsx b/packages/twenty-website/src/app/_components/contributors/ContentContainer.tsx index a53f0e681..27b27f33c 100644 --- a/packages/twenty-website/src/app/_components/contributors/ContentContainer.tsx +++ b/packages/twenty-website/src/app/_components/contributors/ContentContainer.tsx @@ -2,6 +2,8 @@ import styled from '@emotion/styled'; +import MotionContainer from '@/app/_components/ui/layout/LoaderAnimation'; + const Container = styled.div` display: flex; flex-direction: column; @@ -22,5 +24,9 @@ export const ContentContainer = ({ }: { children?: React.ReactNode; }) => { - return {children}; + return ( + + {children} + + ); }; diff --git a/packages/twenty-website/src/app/_components/contributors/ProfileInfo.tsx b/packages/twenty-website/src/app/_components/contributors/ProfileInfo.tsx index 2b6003100..731959cdf 100644 --- a/packages/twenty-website/src/app/_components/contributors/ProfileInfo.tsx +++ b/packages/twenty-website/src/app/_components/contributors/ProfileInfo.tsx @@ -1,7 +1,9 @@ 'use client'; +import React from 'react'; import styled from '@emotion/styled'; +import { AnimatedFigures } from '@/app/_components/contributors/AnimatedFigures'; import { CardContainer } from '@/app/_components/contributors/CardContainer'; import { Theme } from '@/app/_components/ui/theme/theme'; @@ -64,22 +66,23 @@ export const ProfileInfo = ({ rank, activeDays, }: ProfileInfoProps) => { + const parsedValue = parseFloat(rank.replace('%', '')); return ( <>

Merged PR

- {mergedPRsCount} +

Ranking

- {rank}% + %

Active Days

- {activeDays} +
diff --git a/packages/twenty-website/src/app/_components/releases/Release.tsx b/packages/twenty-website/src/app/_components/releases/Release.tsx index f64d54dad..d0a10a746 100644 --- a/packages/twenty-website/src/app/_components/releases/Release.tsx +++ b/packages/twenty-website/src/app/_components/releases/Release.tsx @@ -4,6 +4,7 @@ import { JSXElementConstructor, ReactElement } from 'react'; import styled from '@emotion/styled'; import { Gabarito } from 'next/font/google'; +import MotionContainer from '@/app/_components/ui/layout/LoaderAnimation'; import { Theme } from '@/app/_components/ui/theme/theme'; import { ReleaseNote } from '@/app/releases/api/route'; @@ -97,16 +98,18 @@ export const Release = ({ mdxReleaseContent: ReactElement>; }) => { return ( - - - {release.release} - - {release.date.endsWith(new Date().getFullYear().toString()) - ? release.date.slice(0, -5) - : release.date} - - - {mdxReleaseContent} - + + + + {release.release} + + {release.date.endsWith(new Date().getFullYear().toString()) + ? release.date.slice(0, -5) + : release.date} + + + {mdxReleaseContent} + + ); }; diff --git a/packages/twenty-website/src/app/_components/ui/layout/LoaderAnimation.tsx b/packages/twenty-website/src/app/_components/ui/layout/LoaderAnimation.tsx new file mode 100644 index 000000000..1b8849098 --- /dev/null +++ b/packages/twenty-website/src/app/_components/ui/layout/LoaderAnimation.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { motion } from 'framer-motion'; + +const containerVariants = { + hidden: { opacity: 0, y: 20 }, + visible: { + opacity: 1, + y: 0, + transition: { duration: 0.2, ease: 'easeOut' }, + }, +}; + +const MotionContainer = ({ children }: { children?: React.ReactNode }) => ( + + {children} + +); + +export default MotionContainer;