From 0c52be970b7a570d4b9e4d1709a40aaf45c1f50a Mon Sep 17 00:00:00 2001 From: Onur Date: Thu, 9 May 2024 13:59:12 +0200 Subject: [PATCH] chore(website): improve animation section - closes #17 (#19) --- apps/website/package.json | 2 + apps/website/src/components/code-block.tsx | 6 +- .../components/hero/sections/animation.tsx | 65 +++++++++++++++---- .../components/hero/sections/introduction.tsx | 2 + .../components/hero/sections/playground.tsx | 4 +- apps/website/src/components/snippet.tsx | 4 +- apps/website/src/components/ui/select.tsx | 10 +-- pnpm-lock.yaml | 30 +++++++++ 8 files changed, 97 insertions(+), 26 deletions(-) diff --git a/apps/website/package.json b/apps/website/package.json index b018ffe..6602db1 100644 --- a/apps/website/package.json +++ b/apps/website/package.json @@ -38,6 +38,8 @@ "next": "14.2.3", "react": "18.2.0", "react-dom": "18.2.0", + "react-icons": "^5.2.1", + "react-intersection-observer": "^9.10.2", "sonner": "^1.4.41", "sugar-high": "^0.6.1", "tailwind-merge": "^2.3.0", diff --git a/apps/website/src/components/code-block.tsx b/apps/website/src/components/code-block.tsx index 38e96f3..4477669 100644 --- a/apps/website/src/components/code-block.tsx +++ b/apps/website/src/components/code-block.tsx @@ -3,7 +3,7 @@ import { useState } from 'react' import { toast } from 'sonner' import { highlight } from 'sugar-high' -import { CopyIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon } from 'lucide-react' +import { LuCopy, LuCheck, LuChevronDown, LuChevronRight } from 'react-icons/lu' import { Button } from '@/components/ui/button' import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area' @@ -70,7 +70,7 @@ export const CodeBlock: React.FC = ({ 'invisible absolute right-4 top-4 z-10 size-8 p-0 opacity-0 transition-opacity group-hover/code-block:visible group-hover/code-block:opacity-100' )} > - {copied ? : } + {copied ? : } ) @@ -91,7 +91,7 @@ export const CodeBlock: React.FC = ({ className="flex cursor-pointer select-none items-center gap-2 bg-gray-50 px-4 py-3 text-sm text-gray-600" onClick={() => setIsOpened(!isOpened)} > - {isOpened ? : } + {isOpened ? : } {isOpened ? 'Hide code' : 'Show code'} {isOpened && } diff --git a/apps/website/src/components/hero/sections/animation.tsx b/apps/website/src/components/hero/sections/animation.tsx index a8207f9..648ef45 100644 --- a/apps/website/src/components/hero/sections/animation.tsx +++ b/apps/website/src/components/hero/sections/animation.tsx @@ -1,27 +1,65 @@ 'use client' +import { useEffect, useState } from 'react' import { Gauge } from '@suyalcinkaya/gauge' +import { useInView } from 'react-intersection-observer' import { CodeBlock } from '@/components/code-block' + import { Button } from '@/components/ui/button' +const initialGauges = [ + { value: 18, showAnimation: true, showValue: true }, + { value: 18, showAnimation: true, showValue: true, variant: 'descending' as const }, + { value: 81, showAnimation: true, showValue: true }, + { value: 81, showAnimation: true, showValue: true, variant: 'descending' as const } +] + export const Animation = () => { + const [gauges, setGauges] = useState(initialGauges) + const [isAnimationPlaying, setIsAnimationPlaying] = useState(false) + const { ref, inView } = useInView({ threshold: 0, triggerOnce: true }) + + const playAnimation = () => { + if (isAnimationPlaying) return + + setIsAnimationPlaying(true) + setGauges( + gauges.map((gauge) => ({ + ...gauge, + value: gauge.variant === 'descending' ? 100 : 0, + showAnimation: false + })) + ) + + setTimeout(() => { + setGauges(initialGauges) + + setTimeout(() => { + // Animation transition duration is 1s + setIsAnimationPlaying(false) + }, 1000) + }, 500) + } + + // Play animation when the component is in view + useEffect(() => { + if (inView) { + playAnimation() + } + }, [inView]) + return ( <>

Animation

On initial render, the showAnimation prop animates the Gauge from 0 to the value for the ascending variant, and from 100 to the value for the{' '} - descending variant.{' '} - {' '} - to see the animation. + descending variant.

+ - - - - +
+ {gauges.map((gauge, gaugeIndex) => ( + + ))}
} /> diff --git a/apps/website/src/components/hero/sections/introduction.tsx b/apps/website/src/components/hero/sections/introduction.tsx index 3b0b0c5..05f9d23 100644 --- a/apps/website/src/components/hero/sections/introduction.tsx +++ b/apps/website/src/components/hero/sections/introduction.tsx @@ -1,4 +1,5 @@ import Link from 'next/link' +import { FaGithub } from 'react-icons/fa' import { Button } from '@/components/ui/button' import { playgroundSectionId } from '@/lib/constants' @@ -18,6 +19,7 @@ export const Introduction = () => { diff --git a/apps/website/src/components/hero/sections/playground.tsx b/apps/website/src/components/hero/sections/playground.tsx index 04186d6..59fdaed 100644 --- a/apps/website/src/components/hero/sections/playground.tsx +++ b/apps/website/src/components/hero/sections/playground.tsx @@ -3,7 +3,7 @@ import { useState } from 'react' import { Gauge } from '@suyalcinkaya/gauge' import { toast } from 'sonner' -import { CopyIcon, CheckIcon } from 'lucide-react' +import { LuCopy, LuCheck } from 'react-icons/lu' import { CodeBlock } from '@/components/code-block' import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card' @@ -200,7 +200,7 @@ export const Playground = () => { diff --git a/apps/website/src/components/snippet.tsx b/apps/website/src/components/snippet.tsx index b1343dd..05f2853 100644 --- a/apps/website/src/components/snippet.tsx +++ b/apps/website/src/components/snippet.tsx @@ -2,7 +2,7 @@ import { useState } from 'react' import { toast } from 'sonner' -import { CopyIcon, CheckIcon } from 'lucide-react' +import { LuCopy, LuCheck } from 'react-icons/lu' import { Button } from '@/components/ui/button' import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area' @@ -40,7 +40,7 @@ export const Snippet: React.FC = ({ code, wrapperClassName }) => { diff --git a/apps/website/src/components/ui/select.tsx b/apps/website/src/components/ui/select.tsx index 9c20a88..6a309a3 100644 --- a/apps/website/src/components/ui/select.tsx +++ b/apps/website/src/components/ui/select.tsx @@ -1,7 +1,7 @@ 'use client' import * as React from 'react' -import { ChevronsUpDownIcon, CheckIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-react' +import { LuChevronsUpDown, LuCheck, LuChevronDown, LuChevronUp } from 'react-icons/lu' import * as SelectPrimitive from '@radix-ui/react-select' import { cn } from '@/lib/utils' @@ -26,7 +26,7 @@ const SelectTrigger = React.forwardRef< > {children} - + )) @@ -41,7 +41,7 @@ const SelectScrollUpButton = React.forwardRef< className={cn('flex cursor-default items-center justify-center py-1', className)} {...props} > - + )) SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName @@ -55,7 +55,7 @@ const SelectScrollDownButton = React.forwardRef< className={cn('flex cursor-default items-center justify-center py-1', className)} {...props} > - + )) SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName @@ -114,7 +114,7 @@ const SelectItem = React.forwardRef< > - + {children} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 15e4e53..9178b76 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,6 +65,12 @@ importers: react-dom: specifier: 18.2.0 version: 18.2.0(react@18.2.0) + react-icons: + specifier: ^5.2.1 + version: 5.2.1(react@18.2.0) + react-intersection-observer: + specifier: ^9.10.2 + version: 9.10.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0) sonner: specifier: ^1.4.41 version: 1.4.41(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -2454,6 +2460,20 @@ packages: peerDependencies: react: ^18.3.1 + react-icons@5.2.1: + resolution: {integrity: sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==} + peerDependencies: + react: '*' + + react-intersection-observer@9.10.2: + resolution: {integrity: sha512-j2hGADK2hCbAlfaq6L3tVLb4iqngoN7B1fT16MwJ4J16YW/vWLcmAIinLsw0lgpZeMi4UDUWtHC9QDde0/P1yQ==} + peerDependencies: + react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + react-dom: + optional: true + react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -5631,6 +5651,16 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 + react-icons@5.2.1(react@18.2.0): + dependencies: + react: 18.2.0 + + react-intersection-observer@9.10.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + react: 18.2.0 + optionalDependencies: + react-dom: 18.2.0(react@18.2.0) + react-is@16.13.1: {} react-remove-scroll-bar@2.3.6(@types/react@18.2.18)(react@18.2.0):