Skip to content

Commit

Permalink
Set up animated card flow
Browse files Browse the repository at this point in the history
Upgrade framer-motion to v11
  • Loading branch information
jmrossy committed Dec 4, 2024
1 parent caeff7d commit 7a396d4
Show file tree
Hide file tree
Showing 13 changed files with 163 additions and 41 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"clsx": "^2.1.1",
"cosmjs-types": "^0.9.0",
"formik": "^2.4.6",
"framer-motion": "^10.16.4",
"framer-motion": "^11.13.1",
"next": "^15.0.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand Down
16 changes: 16 additions & 0 deletions src/components/buttons/BackButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ArrowIcon, Button } from '@hyperlane-xyz/widgets';
import { ComponentProps } from 'react';
import { CardPage } from '../../flows/CardPage';
import { useCardNav } from '../../flows/hooks';
import { Color } from '../../styles/Color';

export function BackButton({ page, ...rest }: ComponentProps<typeof Button> & { page: CardPage }) {
const { setPage } = useCardNav();

return (
<Button onClick={() => setPage(page)} {...rest} className="flex items-center gap-0.5">
<ArrowIcon direction="w" width={30} height={20} color={Color.accent} />
<span className="text-md text-accent-500">Back</span>
</Button>
);
}
2 changes: 1 addition & 1 deletion src/components/buttons/ConnectAwareSubmitButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function ConnectAwareSubmitButton<FormValues = any>({ chainName, text, cl
useTimeout(clearErrors, 3500);

return (
<SolidButton type={type} color={color} onClick={onClick} classes={classes}>
<SolidButton type={type} color={color} onClick={onClick} className={classes}>
{content}
</SolidButton>
);
Expand Down
7 changes: 4 additions & 3 deletions src/components/buttons/SolidButton.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import clsx from 'clsx';
import { PropsWithChildren, ReactElement } from 'react';

interface ButtonProps {
type?: 'submit' | 'reset' | 'button';
color?: 'white' | 'primary' | 'accent' | 'green' | 'red' | 'gray'; // defaults to primary
bold?: boolean;
classes?: string;
className?: string;
icon?: ReactElement;
}

Expand All @@ -15,7 +16,7 @@ export function SolidButton(
type,
onClick,
color: _color,
classes,
className,
bold,
icon,
disabled,
Expand Down Expand Up @@ -48,7 +49,7 @@ export function SolidButton(
}
const onDisabled = 'disabled:bg-gray-300 disabled:text-gray-500';
const weight = bold ? 'font-semibold' : '';
const allClasses = `${base} ${baseColors} ${onHover} ${onDisabled} ${weight} ${classes}`;
const allClasses = clsx(base, baseColors, onHover, onDisabled, weight, className);

return (
<button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { ProtocolType, errorToString } from '@hyperlane-xyz/utils';
import { AccountInfo, ChevronIcon, useAccounts } from '@hyperlane-xyz/widgets';
import { Form, Formik, useFormikContext } from 'formik';
import { useState } from 'react';
import { BackButton } from '../../components/buttons/BackButton';
import { ConnectAwareSubmitButton } from '../../components/buttons/ConnectAwareSubmitButton';
import { SolidButton } from '../../components/buttons/SolidButton';
import { config } from '../../consts/config';
import { CardPage } from '../../flows/CardPage';
import { Color } from '../../styles/Color';
import { logger } from '../../utils/logger';
import { ChainConnectionWarning } from '../chains/ChainConnectionWarning';
Expand All @@ -20,7 +22,7 @@ const initialValues = {
destination: arbitrum.name,
};

export function DeploymentForm() {
export function WarpDeploymentForm() {
const multiProvider = useMultiProvider();

const { accounts } = useAccounts(multiProvider, config.addressBlacklist);
Expand Down Expand Up @@ -108,11 +110,14 @@ function ButtonSection({

if (!isReview) {
return (
<ConnectAwareSubmitButton
chainName={values.origin}
text={isValidating ? 'Validating...' : 'Continue'}
classes="mt-4 px-3 py-1.5"
/>
<div className="mt-4 flex items-center justify-between">
<BackButton page={CardPage.Landing} />
<ConnectAwareSubmitButton
chainName={values.origin}
text={isValidating ? 'Validating...' : 'Continue'}
classes="px-3 py-1.5"
/>
</div>
);
}

Expand All @@ -122,7 +127,7 @@ function ButtonSection({
type="button"
color="primary"
onClick={() => setIsReview(false)}
classes="px-6 py-1.5"
className="px-6 py-1.5"
icon={<ChevronIcon direction="w" width={10} height={6} color={Color.white} />}
>
<span>Edit</span>
Expand All @@ -131,7 +136,7 @@ function ButtonSection({
type="button"
color="accent"
onClick={triggerTransactionsHandler}
classes="flex-1 px-3 py-1.5"
className="flex-1 px-3 py-1.5"
>
{`Send to ${chainDisplayName}`}
</SolidButton>
Expand Down
9 changes: 9 additions & 0 deletions src/features/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { toast } from 'react-toastify';
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { config } from '../consts/config';
import { CardPage } from '../flows/CardPage';
import { logger } from '../utils/logger';
import { assembleChainMetadata } from './chains/metadata';
import { DeploymentContext, DeploymentStatus, FinalDeploymentStatuses } from './deployment/types';
Expand Down Expand Up @@ -35,6 +36,9 @@ export interface AppState {
failUnconfirmedDeployments: () => void;

// Shared component state
cardPage: CardPage;
direction: 'forward' | 'backward';
setCardPage: (page: CardPage) => void;
deploymentLoading: boolean;
setDeploymentLoading: (isLoading: boolean) => void;
isSideBarOpen: boolean;
Expand Down Expand Up @@ -98,6 +102,11 @@ export const useStore = create<AppState>()(
},

// Shared component state
cardPage: CardPage.Landing,
direction: 'forward',
setCardPage: (page) => {
set((s) => ({ cardPage: page, direction: page >= s.cardPage ? 'forward' : 'backward' }));
},
deploymentLoading: false,
setDeploymentLoading: (isLoading) => {
set(() => ({ deploymentLoading: isLoading }));
Expand Down
2 changes: 1 addition & 1 deletion src/features/wallet/WalletFloatingButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function WalletFloatingButtons() {
}));

return (
<div className="absolute -right-8 top-2 hidden flex-col items-center justify-end gap-4 sm:flex">
<div className="absolute -top-8 right-2 hidden items-center gap-4 sm:flex">
<IconButton
className={`p-0.5 ${styles.roundedCircle} `}
title="History"
Expand Down
40 changes: 40 additions & 0 deletions src/flows/CardFlow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { AnimatePresence, motion } from 'framer-motion';
import { WarpDeploymentForm } from '../features/deployment/WarpDeploymentForm';
import { CardPage } from './CardPage';
import { LandingPage } from './LandingCard';
import { useCardNav } from './hooks';

export function CardFlow() {
const { page, direction } = useCardNav();

return (
<AnimatePresence mode="wait" custom={direction}>
<motion.div
key={page}
custom={direction}
variants={variants}
transition={transition}
initial="enter"
animate="center"
exit="exit"
>
{page === CardPage.Landing && <LandingPage />}
{page === CardPage.WarpForm && <WarpDeploymentForm />}
</motion.div>
;
</AnimatePresence>
);
}

const variants = {
enter: (direction: 'forward' | 'backward') => ({
opacity: 0,
x: direction === 'forward' ? 40 : -40,
}),
center: { opacity: 1, x: 0 },
exit: (direction: 'forward' | 'backward') => ({
opacity: 0,
x: direction === 'forward' ? -40 : 40,
}),
};
const transition = { duration: 0.3 };
8 changes: 8 additions & 0 deletions src/flows/CardPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export enum CardPage {
Landing,
WarpForm,
WarpReview,
WarpDeploy,
WarpSuccess,
WarpError,
}
39 changes: 39 additions & 0 deletions src/flows/LandingCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { SolidButton } from '../components/buttons/SolidButton';
import { links } from '../consts/links';
import { CardPage } from './CardPage';
import { useCardNav } from './hooks';

export function LandingPage() {
const { setPage } = useCardNav();

return (
<div className="space-y-6 p-4 text-center">
<h1 className="text-2xl text-primary-500">Deploy a Warp Route</h1>
<h2 className="text-md">
Anyone can permissionlessly create an interchain token bridge by deploying Hyperlane Warp
Route contracts.
</h2>
<p className="text-sm">
Follow three steps to create a new route: configure your options, deploy your contracts, and
set up a bridge UI.
</p>
<div className="flex justify-center gap-12">
<a
href={links.warpDocs}
target="_blank"
rel="noopener noreferrer"
className="w-36 rounded-lg border-2 border-accent-500 px-3 py-2 text-accent-500 transition-all hover:border-accent-600 hover:text-accent-600 active:scale-95"
>
Learn more
</a>
<SolidButton
color="accent"
onClick={() => setPage(CardPage.WarpForm)}
className="w-36 px-3 py-2"
>
Deploy
</SolidButton>
</div>
</div>
);
}
5 changes: 5 additions & 0 deletions src/flows/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { useStore } from '../features/store';

export function useCardNav() {
return useStore((s) => ({ page: s.cardPage, direction: s.direction, setPage: s.setCardPage }));
}
6 changes: 3 additions & 3 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { NextPage } from 'next';
import { Card } from '../components/layout/Card';
import { DeploymentForm } from '../features/deployment/DeploymentForm';
import { WalletFloatingButtons } from '../features/wallet/WalletFloatingButtons';
import { CardFlow } from '../flows/CardFlow';

const Home: NextPage = () => {
return (
<div className="space-y-3 pt-4">
<div className="relative">
<Card className="w-100 sm:w-[31rem]">
<DeploymentForm />
<Card className="w-100 overflow-x-hidden sm:w-[31rem]">
<CardFlow />
</Card>
<WalletFloatingButtons />
</div>
Expand Down
47 changes: 23 additions & 24 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2848,15 +2848,6 @@ __metadata:
languageName: node
linkType: hard

"@emotion/is-prop-valid@npm:^0.8.2":
version: 0.8.8
resolution: "@emotion/is-prop-valid@npm:0.8.8"
dependencies:
"@emotion/memoize": "npm:0.7.4"
checksum: 10/e85bdeb9d9d23de422f271e0f5311a0142b15055bb7e610440dbf250f0cdfd049df88af72a49e2c6081954481f1cbeca9172e2116ff536b38229397dfbed8082
languageName: node
linkType: hard

"@emotion/is-prop-valid@npm:^1.3.0":
version: 1.3.0
resolution: "@emotion/is-prop-valid@npm:1.3.0"
Expand All @@ -2866,13 +2857,6 @@ __metadata:
languageName: node
linkType: hard

"@emotion/memoize@npm:0.7.4":
version: 0.7.4
resolution: "@emotion/memoize@npm:0.7.4"
checksum: 10/4e3920d4ec95995657a37beb43d3f4b7d89fed6caa2b173a4c04d10482d089d5c3ea50bbc96618d918b020f26ed6e9c4026bbd45433566576c1f7b056c3271dc
languageName: node
linkType: hard

"@emotion/memoize@npm:^0.8.1":
version: 0.8.1
resolution: "@emotion/memoize@npm:0.8.1"
Expand Down Expand Up @@ -3932,7 +3916,7 @@ __metadata:
eslint-config-next: "npm:^15.0.2"
eslint-config-prettier: "npm:^9.1.0"
formik: "npm:^2.4.6"
framer-motion: "npm:^10.16.4"
framer-motion: "npm:^11.13.1"
next: "npm:^15.0.3"
postcss: "npm:^8.4.47"
prettier: "npm:^3.2.5"
Expand Down Expand Up @@ -15393,24 +15377,25 @@ __metadata:
languageName: node
linkType: hard

"framer-motion@npm:^10.16.4":
version: 10.16.4
resolution: "framer-motion@npm:10.16.4"
"framer-motion@npm:^11.13.1":
version: 11.13.1
resolution: "framer-motion@npm:11.13.1"
dependencies:
"@emotion/is-prop-valid": "npm:^0.8.2"
motion-dom: "npm:^11.13.0"
motion-utils: "npm:^11.13.0"
tslib: "npm:^2.4.0"
peerDependencies:
"@emotion/is-prop-valid": "*"
react: ^18.0.0
react-dom: ^18.0.0
dependenciesMeta:
peerDependenciesMeta:
"@emotion/is-prop-valid":
optional: true
peerDependenciesMeta:
react:
optional: true
react-dom:
optional: true
checksum: 10/1ef5e1f4444316e531ea4c1c23f1ce01379fe59a29e859f865d8307fbda5f88cb0c54619f8a1d28b372309813271b92e67d2f5984ea0e64308245da47f2a617b
checksum: 10/621419951160d1506931554595a977abf603a8ecb92c6481481c23c48b18f90691fcff3cc8570b4c86e8fe65d1fec98210c7d18ff5a3c6953e48bf603b833c02
languageName: node
linkType: hard

Expand Down Expand Up @@ -18006,6 +17991,20 @@ __metadata:
languageName: node
linkType: hard

"motion-dom@npm:^11.13.0":
version: 11.13.0
resolution: "motion-dom@npm:11.13.0"
checksum: 10/9c58f60cc693cb40f956477b831bd3a66f7f70887929324b0196c471c79eda896e7e85849d3b5a389617505654343522393e897c84ffd33cae9ade3b3c9f57c8
languageName: node
linkType: hard

"motion-utils@npm:^11.13.0":
version: 11.13.0
resolution: "motion-utils@npm:11.13.0"
checksum: 10/f0141d6b1ac8efd48208bfcfd64c3bf8e952322954c1d63726b1f067e2828d01c9ca5ad1c4751461886f12c16e68d49ad0a8a38f997772f24dbd45bf6dc56238
languageName: node
linkType: hard

"motion@npm:10.16.2":
version: 10.16.2
resolution: "motion@npm:10.16.2"
Expand Down

0 comments on commit 7a396d4

Please sign in to comment.