Show add chain menu when metadata is required in tx card

Tweak footer fonts
pull/114/head
J M Rossy 2 months ago
parent bc6f4f6235
commit 1878af0892
  1. 6
      src/components/nav/Footer.tsx
  2. 8
      src/components/nav/Header.tsx
  3. 52
      src/components/search/SearchFilterBar.tsx
  4. 40
      src/features/chains/ChainSearchModal.tsx
  5. 7
      src/features/chains/MissingChainConfigToast.tsx
  6. 2
      src/features/chains/queries/useScrapedChains.ts
  7. 40
      src/features/messages/cards/TransactionCard.tsx

@ -36,15 +36,15 @@ export function Footer() {
<footer className="text-white px-8 pt-14 pb-5 bg-gradient-to-b from-transparent to-black/40">
<div className="flex flex-col sm:flex-row gap-10 items-center justify-between">
<div className="flex items-center justify-center">
<div className="ml-2 w-14 sm:w-16 h-14 sm:h-16">
<div className="ml-2 w-12 sm:w-14 h-12 sm:h-14">
<HyperlaneLogo color={Color.white} />
</div>
<div className="text-xl sm:text-2xl font-medium ml-6 space-y-1 ">
<div className="text-lg sm:text-xl font-medium ml-6 space-y-1 ">
<div>Go interchain</div>
<div>with Hyperlane</div>
</div>
</div>
<nav className="flex text-lg font-medium">
<nav className="flex font-medium">
<ul className={`${styles.linkCol} mr-14`}>
{footerLinks1.map((item) => (
<li className="" key={item.title}>

@ -63,9 +63,6 @@ export function Header({ pathName }: { pathName: string }) {
>
Docs
</a>
{/* <Link href="/settings" className={navLinkClass('/settings')}>
Settings
</Link> */}
{showSearch && <MiniSearchBar />}
</nav>
{/* Dropdown menu, used on mobile */}
@ -79,11 +76,6 @@ export function Header({ pathName }: { pathName: string }) {
Home
</MobileNavLink>
),
// ({ close }) => (
// <MobileNavLink href="/settings" closeDropdown={close} key="Settings">
// Settings
// </MobileNavLink>
// ),
// ({ close }) => (
// <MobileNavLink href="/api" closeDropdown={c} key="API">
// API

@ -3,18 +3,11 @@ import { useState } from 'react';
import { ChainMetadata } from '@hyperlane-xyz/sdk';
import { trimToLength } from '@hyperlane-xyz/utils';
import {
ChainSearchMenu,
ChevronIcon,
IconButton,
Modal,
Popover,
XIcon,
} from '@hyperlane-xyz/widgets';
import { useScrapedEvmChains } from '../../features/chains/queries/useScrapedChains';
import { ChevronIcon, IconButton, Popover, XIcon, useModal } from '@hyperlane-xyz/widgets';
import { ChainSearchModal } from '../../features/chains/ChainSearchModal';
import { getChainDisplayName } from '../../features/chains/utils';
import { useMultiProvider, useStore } from '../../store';
import { useMultiProvider } from '../../store';
import { Color } from '../../styles/Color';
import { SolidButton } from '../buttons/SolidButton';
import { TextButton } from '../buttons/TextButton';
@ -68,31 +61,22 @@ function ChainSelector({
value: ChainId | null;
onChangeValue: (value: string | null) => void;
}) {
const { isOpen, open, close } = useModal();
const multiProvider = useMultiProvider();
const { chains } = useScrapedEvmChains(multiProvider);
const { chainMetadataOverrides, setChainMetadataOverrides } = useStore((s) => ({
chainMetadataOverrides: s.chainMetadataOverrides,
setChainMetadataOverrides: s.setChainMetadataOverrides,
}));
const [showModal, setShowModal] = useState(false);
const closeModal = () => {
setShowModal(false);
};
const chainName = value
? trimToLength(getChainDisplayName(multiProvider, value, true), 12)
: undefined;
const onClickChain = (c: ChainMetadata) => {
onChangeValue(c.chainId.toString());
closeModal();
close();
};
const onClear = () => {
onChangeValue(null);
};
const chainName = value
? trimToLength(getChainDisplayName(multiProvider, value, true), 12)
: undefined;
return (
<div className="relative">
<button
@ -101,7 +85,7 @@ function ChainSelector({
'text-sm sm:min-w-[5.8rem] px-1.5 sm:px-2.5 py-1 flex items-center justify-center font-medium rounded-lg border border-pink-500 hover:opacity-80 active:opacity-70 transition-all',
value ? 'bg-pink-500 text-white pr-7 sm:pr-8' : 'text-pink-500',
)}
onClick={() => setShowModal(!showModal)}
onClick={open}
>
<span>{chainName || text} </span>
{!value && (
@ -115,19 +99,7 @@ function ChainSelector({
)}
</button>
{value && <ClearButton onClick={onClear} />}
<Modal
isOpen={showModal}
close={closeModal}
panelClassname="p-4 sm:p-5 max-w-lg min-h-[40vh]"
>
<ChainSearchMenu
chainMetadata={chains}
onClickChain={onClickChain}
overrideChainMetadata={chainMetadataOverrides}
onChangeOverrideMetadata={setChainMetadataOverrides}
showAddChainButton={true}
/>
</Modal>
<ChainSearchModal isOpen={isOpen} close={close} onClickChain={onClickChain} />
</div>
);
}

@ -0,0 +1,40 @@
import { ChainMetadata } from '@hyperlane-xyz/sdk';
import { ChainSearchMenu, Modal } from '@hyperlane-xyz/widgets';
import { useMultiProvider, useStore } from '../../store';
import { useScrapedEvmChains } from './queries/useScrapedChains';
export function ChainSearchModal({
isOpen,
close,
onClickChain,
showAddChainMenu,
}: {
isOpen: boolean;
close: () => void;
onClickChain?: (metadata: ChainMetadata) => void;
showAddChainMenu?: boolean;
}) {
const multiProvider = useMultiProvider();
const { chains } = useScrapedEvmChains(multiProvider);
const { chainMetadataOverrides, setChainMetadataOverrides } = useStore((s) => ({
chainMetadataOverrides: s.chainMetadataOverrides,
setChainMetadataOverrides: s.setChainMetadataOverrides,
}));
const onClick = onClickChain || (() => {});
return (
<Modal isOpen={isOpen} close={close} panelClassname="p-4 sm:p-5 max-w-lg min-h-[40vh]">
<ChainSearchMenu
chainMetadata={chains}
onClickChain={onClick}
overrideChainMetadata={chainMetadataOverrides}
onChangeOverrideMetadata={setChainMetadataOverrides}
showAddChainButton={true}
showAddChainMenu={showAddChainMenu}
/>
</Modal>
);
}

@ -1,5 +1,3 @@
import Link from 'next/link';
export function MissingChainConfigToast({
domainId,
chainId,
@ -14,10 +12,7 @@ export function MissingChainConfigToast({
: 'unknown message chain';
return (
<div>
<span>{`No chain config found for ${errorDesc}. `}</span>
<Link href="/settings" className="underline">
Add a config
</Link>
<span>{`No chain config found for ${errorDesc}. You can add a config in the origin/destination chain selector.`}</span>
</div>
);
}

@ -50,7 +50,7 @@ export function useScrapedEvmChains(multiProvider: MultiProvider) {
);
// Return only evmChains because of graphql only accept query non-evm chains (with bigint type not string)
return { chains: scrapedEvmChains };
}, [multiProvider, scrapedChains]);
}, [multiProvider, chainMetadata, scrapedChains]);
return { chains, isFetching, isError };
}

@ -1,10 +1,9 @@
import BigNumber from 'bignumber.js';
import Link from 'next/link';
import { PropsWithChildren, ReactNode, useState } from 'react';
import { MultiProvider } from '@hyperlane-xyz/sdk';
import { isAddress, isZeroish } from '@hyperlane-xyz/utils';
import { Modal } from '@hyperlane-xyz/widgets';
import { Modal, useModal } from '@hyperlane-xyz/widgets';
import { Spinner } from '../../../components/animations/Spinner';
import { ChainLogo } from '../../../components/icons/ChainLogo';
@ -14,6 +13,7 @@ import { links } from '../../../consts/links';
import { useMultiProvider } from '../../../store';
import { MessageStatus, MessageTx } from '../../../types';
import { getDateTimeString, getHumanReadableTimeString } from '../../../utils/time';
import { ChainSearchModal } from '../../chains/ChainSearchModal';
import { getChainDisplayName, isEvmChain } from '../../chains/utils';
import { debugStatusToDesc } from '../../debugger/strings';
import { MessageDebugResult } from '../../debugger/types';
@ -70,6 +70,8 @@ export function DestinationTransactionCard({
const isDestinationEvmChain = isEvmChain(multiProvider, chainId);
const { isOpen, open, close } = useModal();
let content: ReactNode;
if (transaction) {
content = (
@ -104,22 +106,26 @@ export function DestinationTransactionCard({
);
} else if (!hasChainConfig) {
content = (
<DeliveryStatus>
<div className="flex flex-col items-center">
<div>Delivery status is unknown.</div>
<div className="mt-2 text-sm max-w-xs">
Permissionless Interoperability (PI) chains require a config.
</div>
<div className="mt-2 mb-6 text-sm max-w-xs">
Please{' '}
<Link href="/settings" className="underline underline-offset-2">
add a config
</Link>{' '}
for this chain.
<>
<DeliveryStatus>
<div className="flex flex-col items-center">
<div>Delivery status is unknown.</div>
<div className="mt-2 text-sm max-w-xs">
Permissionless Interoperability (PI) chains require a config.
</div>
<div className="mt-2 mb-6 text-sm max-w-xs">
Please{' '}
<button className="underline underline-offset-2" onClick={open}>
add metadata
</button>{' '}
for this chain.
</div>
<CallDataModal debugResult={debugResult} />
</div>
<CallDataModal debugResult={debugResult} />
</div>
</DeliveryStatus>
</DeliveryStatus>
{/* TODO get modal to auto-close after adding chain metadata */}
<ChainSearchModal isOpen={isOpen} close={close} showAddChainMenu={true} />
</>
);
} else if (status === MessageStatus.Pending) {
if (isDestinationEvmChain) {

Loading…
Cancel
Save