diff --git a/nx-dev/ui-animations/src/lib/animated-beam.tsx b/nx-dev/ui-animations/src/lib/animated-beam.tsx index e4ee814875..cf7d768b4f 100644 --- a/nx-dev/ui-animations/src/lib/animated-beam.tsx +++ b/nx-dev/ui-animations/src/lib/animated-beam.tsx @@ -188,20 +188,16 @@ export const AnimatedCurvedBeam: FC = ({ animate={animateValue} transition={{ delay, - duration, + duration: bidirectional ? duration * 2 : duration, ease: [0.16, 1, 0.3, 1], // https://easings.net/#easeOutExpo repeat: Infinity, repeatDelay: 0, }} > - - - - + + + + @@ -361,8 +357,8 @@ export const AnimatedAngledBeam: FC = ({ - - + + diff --git a/nx-dev/ui-icons/src/index.ts b/nx-dev/ui-icons/src/index.ts index c626dcfe9a..d78f56e0ec 100644 --- a/nx-dev/ui-icons/src/index.ts +++ b/nx-dev/ui-icons/src/index.ts @@ -3,6 +3,7 @@ export * from './lib/ci-providers/azure-devops'; export * from './lib/ci-providers/bitbucket'; export * from './lib/ci-providers/github'; export * from './lib/ci-providers/gitlab'; +export * from './lib/ci-providers/google-cloud'; export * from './lib/ci-providers/jenkins'; export * from './lib/ci-providers/travis-ci'; diff --git a/nx-dev/ui-icons/src/lib/ci-providers/google-cloud.tsx b/nx-dev/ui-icons/src/lib/ci-providers/google-cloud.tsx new file mode 100644 index 0000000000..150175e707 --- /dev/null +++ b/nx-dev/ui-icons/src/lib/ci-providers/google-cloud.tsx @@ -0,0 +1,14 @@ +import { FC, SVGProps } from 'react'; + +export const GoogleCloudIcon: FC> = (props) => ( + + Google Cloud + + +); diff --git a/nx-dev/ui-powerpack/src/lib/powerpack-features.tsx b/nx-dev/ui-powerpack/src/lib/powerpack-features.tsx index 9d4b3dec30..ac06a0dd91 100644 --- a/nx-dev/ui-powerpack/src/lib/powerpack-features.tsx +++ b/nx-dev/ui-powerpack/src/lib/powerpack-features.tsx @@ -1,14 +1,20 @@ 'use client'; -import { forwardRef, ReactElement, ReactNode, useRef } from 'react'; +import { + forwardRef, + ReactElement, + ReactNode, + useCallback, + useEffect, + useRef, + useState, +} from 'react'; import { ButtonLink, SectionHeading, Strong } from '@nx/nx-dev/ui-common'; import { cx } from '@nx/nx-dev/ui-primitives'; -import { AnimatedAngledBeam } from '@nx/nx-dev/ui-animations'; -import { - CalendarDaysIcon, - CircleStackIcon, - ServerIcon, -} from '@heroicons/react/24/outline'; -import { NxIcon } from '@nx/nx-dev/ui-icons'; +import { AnimatedCurvedBeam } from '@nx/nx-dev/ui-animations'; +import { CircleStackIcon, ServerIcon } from '@heroicons/react/24/outline'; +import { AzureDevOpsIcon, GoogleCloudIcon, NxIcon } from '@nx/nx-dev/ui-icons'; +import Link from 'next/link'; +import { AnimatePresence, motion } from 'framer-motion'; export function PowerpackFeatures(): ReactElement { return ( @@ -146,15 +152,22 @@ export function PowerpackFeatures(): ReactElement { const Card = forwardRef< HTMLDivElement, - { className?: string; children?: ReactNode } ->(({ className, children }, ref) => { + { + className?: string; + children?: ReactNode; + onMouseEnter?: () => void; + onMouseLeave?: () => void; + } +>(({ className, children, onMouseEnter, onMouseLeave }, ref) => { return (
{children}
@@ -164,99 +177,241 @@ const Card = forwardRef< Card.displayName = 'Card'; export function CustomRemoteCacheAnimation(): ReactElement { + const awsRef = useRef(null); + const azureRef = useRef(null); const containerRef = useRef(null); - const gitHubRef = useRef(null); - const gitlabRef = useRef(null); + const gcpRef = useRef(null); + const networkDriveRef = useRef(null); const nxRef = useRef(null); - const computerRef = useRef(null); + + const animatedBeamMap: Record = { + aws: ( + + ), + azure: ( + + ), + gcp: ( + + ), + networkDrive: ( + + ), + }; + + const links = Object.keys(animatedBeamMap); + const duration = 6000; + const timeout = useRef(); + const [selected, setSelected] = useState('aws'); + const [autoplay, setAutoplay] = useState(true); + + const play = useCallback(() => { + timeout.current = setTimeout(next, duration); + }, [selected]); + + const next = () => { + if (links.length <= 1) return; // No change if there's only one or no items + + if (selected === null) + return setSelected(links[Math.floor(Math.random() * links.length)]); + + const availableLinks = links.filter((link) => link !== selected); + const randomIndex = Math.floor(Math.random() * availableLinks.length); + setSelected(availableLinks[randomIndex]); + }; + + useEffect(() => { + clearTimeout(timeout.current); + if (autoplay) play(); + }, [selected, autoplay, play]); return (
- +
-
- -
+
+ { + setAutoplay(false); + setSelected('aws'); + }} + onMouseLeave={() => { + setAutoplay(true); + setSelected(null); + }} + className={cx( + 'relative transition hover:bg-slate-50 dark:hover:bg-slate-800', + { 'bg-slate-50 dark:bg-slate-800': selected === 'aws' } + )} + > +
AWS
-
S3
+
S3
- + Get started - +
- -
+ { + setAutoplay(false); + setSelected('networkDrive'); + }} + onMouseLeave={() => { + setAutoplay(true); + setSelected(null); + }} + className={cx( + 'relative transition hover:bg-slate-50 dark:hover:bg-slate-800', + { 'bg-slate-50 dark:bg-slate-800': selected === 'networkDrive' } + )} + > +
Network drive
-
- -
- More soon! + { + setAutoplay(false); + setSelected('gcp'); + }} + onMouseLeave={() => { + setAutoplay(true); + setSelected(null); + }} + className={cx( + 'relative transition hover:bg-slate-50 dark:hover:bg-slate-800', + { 'bg-slate-50 dark:bg-slate-800': selected === 'gcp' } + )} + > +
+ GCP
-
- - - + + {selected ? ( + + {animatedBeamMap[selected]} + + ) : null} +
); }