Skip to content

Commit

Permalink
Create planet spinner animation
Browse files Browse the repository at this point in the history
  • Loading branch information
jmrossy committed Dec 16, 2024
1 parent 3098c6c commit f345160
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 11 deletions.
Binary file added public/backgrounds/planet-bg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 56 additions & 0 deletions src/components/animation/PlanetSpinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
motion,
useAnimation,
useAnimationFrame,
useMotionValue,
useTransform,
} from 'framer-motion';
import Image from 'next/image';
import { useEffect } from 'react';
import Planet1 from '../../images/illustrations/planet1.png';
import Planet2 from '../../images/illustrations/planet2.png';

export function PlanetSpinner() {
// Planet 1 animation:
// This rotates around the center of the div
const controls = useAnimation();
useEffect(() => {
controls.start({
rotate: 360,
transition: {
repeat: Infinity,
duration: 70,
ease: 'linear',
},
});
}, [controls]);

// Planet 2 animation:
// These transform functions calculate the x and y position based on the angle
const angle = useMotionValue(0);
const x = useTransform(angle, (value) => 70 * Math.cos(value));
const y = useTransform(angle, (value) => 70 * Math.sin(value));

useAnimationFrame((t) => {
angle.set(t / 5000); // Controls the speed of rotation
});

return (
<div
style={{
backgroundImage: 'url(/backgrounds/planet-bg.png)',
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
}}
className="relative flex items-center justify-center rounded-full p-10"
>
<motion.div animate={controls}>
<Image src={Planet1} width={90} height={90} alt="" />
</motion.div>
<motion.div style={{ position: 'absolute', x: x, y: y }}>
<Image src={Planet2} width={26} height={26} alt="" className="" />
</motion.div>
</div>
);
}
17 changes: 17 additions & 0 deletions src/components/icons/LogsIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { DefaultIconProps } from '@hyperlane-xyz/widgets';
import { memo } from 'react';
import { Color } from '../../styles/Color';

// TODO move to widgets lib
function _LogsIcon({ color, ...rest }: DefaultIconProps) {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" {...rest}>
<path
d="M0 10V8.57143H6.25V10H0ZM0 7.14286V5.71429H10V7.14286H0ZM0 4.28571V2.85714H10V4.28571H0ZM0 1.42857V0H10V1.42857H0Z"
fill={color || Color.black}
/>
</svg>
);
}

export const LogsIcon = memo(_LogsIcon);
58 changes: 47 additions & 11 deletions src/features/deployment/warp/WarpDeploymentDeploy.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { ArrowIcon, Button, WalletIcon } from '@hyperlane-xyz/widgets';
import { ArrowIcon, Button, Modal, useModal, WalletIcon } from '@hyperlane-xyz/widgets';
import { useState } from 'react';
import { toast } from 'react-toastify';
import { PlanetSpinner } from '../../../components/animation/PlanetSpinner';
import { SolidButton } from '../../../components/buttons/SolidButton';
import { GasIcon } from '../../../components/icons/GasIcon';
import { LogsIcon } from '../../../components/icons/LogsIcon';
import { StopIcon } from '../../../components/icons/StopIcon';
import { H1 } from '../../../components/text/H1';
import { CardPage } from '../../../flows/CardPage';
import { useCardNav } from '../../../flows/hooks';
import { Color } from '../../../styles/Color';
import { useMultiProvider } from '../../chains/hooks';
import { getChainDisplayName } from '../../chains/utils';
import { useWarpDeploymentConfig } from '../hooks';

export function WarpDeploymentDeploy() {
return (
<div className="flex w-full flex-col items-center space-y-8 py-2 xs:min-w-100">
<div className="flex w-full flex-col items-center space-y-5 py-2 xs:min-w-100">
<HeaderSection />
<StatusSection />
<MainSection />
<ButtonSection />
</div>
);
Expand All @@ -24,15 +28,13 @@ function HeaderSection() {
return <H1 className="text-center">Deploying Warp Route</H1>;
}

function StatusSection() {
function MainSection() {
const { deploymentConfig } = useWarpDeploymentConfig();
const _chains = deploymentConfig?.chains || [];

return (
<div className="space-y-3">
<FundAccounts />
</div>
);
const [isDeploying, _setIsDeploying] = useState(true);

return <div className="space-y-3">{isDeploying ? <DeployStatus /> : <FundAccounts />}</div>;
}

function FundAccounts() {
Expand All @@ -51,7 +53,7 @@ function FundAccounts() {
};

return (
<div className="flex flex-col items-center space-y-5">
<div className="flex flex-col items-center space-y-5 py-4">
<div className="flex items-center justify-center gap-3">
<WalletIcon width={40} height={40} color={Color.primary['500']} />
<ArrowIcon width={30} height={30} color={Color.primary['500']} direction="e" />
Expand All @@ -70,12 +72,46 @@ function FundAccounts() {
);
}

function DeployStatus() {
const multiProvider = useMultiProvider();
const { deploymentConfig } = useWarpDeploymentConfig();
const chains = deploymentConfig?.chains || [];
//TODO 'and' here
const chainListString = chains.map((c) => getChainDisplayName(multiProvider, c, true)).join(', ');

const { isOpen, open, close } = useModal();
const onClickViewLogs = () => {
// TODO get logs somehow
open();
};

return (
<div className="flex flex-col items-center text-center">
<div className="flex justify-center">
<PlanetSpinner />
</div>
<div className="mt-1">
<p className="max-w-sm text-gray-700">{`Deploying to ${chainListString}`}</p>
<p className="text-gray-700">This will take a few minutes.</p>
<p className="mt-2 text-sm">TODO status text</p>
</div>
<Button onClick={onClickViewLogs} className="mt-4 gap-2.5">
<LogsIcon width={14} height={14} color={Color.accent['500']} />
<span className="text-md text-accent-500">View deployment logs</span>
</Button>
<Modal isOpen={isOpen} close={close} panelClassname="p-4">
<div>TODO logs here</div>
</Modal>
</div>
);
}

function ButtonSection() {
const { setPage } = useCardNav();
const onClickCancel = () => {
// TODO cancel in SDK if possible?
toast.warn('Deployment cancelled');
setPage(CardPage.WarpReview);
setPage(CardPage.WarpForm);
};

return (
Expand Down
Binary file added src/images/illustrations/planet-bg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/illustrations/planet1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/illustrations/planet2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f345160

Please sign in to comment.