Replace react-accessible-dropdown with headlessui

Fix more outdated blue color references
pull/29/head
J M Rossy 2 years ago
parent 92581e8d6e
commit ca65427a1d
  1. 2
      package.json
  2. 2
      public/browserconfig.xml
  3. 2
      src/components/input/Checkbox.module.css
  4. 3
      src/components/layout/AppLayout.tsx
  5. 84
      src/components/layout/Dropdown.tsx
  6. 64
      src/components/layout/Modal.tsx
  7. 79
      src/components/nav/Header.tsx
  8. 139
      src/components/search/SearchFilterBar.tsx
  9. 4
      src/consts/links.ts
  10. 2
      src/features/messages/MessageSearch.tsx
  11. 2
      src/images/icons/funnel.svg
  12. 1
      src/images/icons/gear.svg
  13. 2
      src/images/logos/hyperlane-chevron-single-blue.svg
  14. 2
      src/images/logos/hyperlane-explorer.svg
  15. 4
      src/pages/_document.tsx
  16. 2
      src/styles/Color.ts
  17. 17
      src/styles/global.css
  18. 23
      yarn.lock

@ -4,6 +4,7 @@
"version": "1.0.0",
"author": "J M Rossy",
"dependencies": {
"@headlessui/react": "^1.7.11",
"@hyperlane-xyz/sdk": "^1.0.0-beta6",
"@metamask/jazzicon": "https://github.com/jmrossy/jazzicon#7a8df28974b4e81129bfbe3cab76308b889032a6",
"@rainbow-me/rainbowkit": "^0.8.0",
@ -14,7 +15,6 @@
"graphql": "^16.6.0",
"next": "^13.0.5",
"react": "^18.2.0",
"react-accessible-dropdown-menu-hook": "^3.2.0",
"react-dom": "^18.2.0",
"react-toastify": "^9.1.1",
"urql": "^3.0.3",

@ -3,7 +3,7 @@
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#025aa1</TileColor>
<TileColor>#2362C1</TileColor>
</tile>
</msapplication>
</browserconfig>

@ -20,7 +20,7 @@
border-radius: 0.2rem;
transform: scale(0);
transition: 200ms all ease-in-out;
background-color: #025aa1;
background-color: #2362C1;
}
.checkbox:checked::before {

@ -4,7 +4,6 @@ import { PropsWithChildren } from 'react';
import { toTitleCase } from '../../utils/string';
import { Footer } from '../nav/Footer';
import { Header } from '../nav/Header';
import { InfoBanner } from '../nav/InfoBanner';
interface Props {
pathName: string;
@ -19,7 +18,7 @@ export function AppLayout({ pathName, children }: PropsWithChildren<Props>) {
<title>{`Hyperlane Explorer | ${getHeadTitle(pathName)}`}</title>
</Head>
<div id="app-content" className="h-full min-h-screen w-full min-w-screen">
<InfoBanner />
{/* <InfoBanner /> */}
<div className="max-w-5xl mx-auto flex flex-col justify-between min-h-screen">
<Header pathName={pathName} />
<main className="w-full grow">{children}</main>

@ -0,0 +1,84 @@
import { Menu, Popover, Transition } from '@headlessui/react';
import { Fragment, ReactElement, ReactNode } from 'react';
interface MenuProps {
buttonContent: ReactNode;
buttonClasses?: string;
buttonTitle?: string;
menuItems: ReactNode[];
menuClasses?: string;
}
// Uses Headless menu, which auto-closes on any item click
export function DropdownMenu({
buttonContent,
buttonClasses,
buttonTitle,
menuItems,
menuClasses,
}: MenuProps) {
return (
<Menu as="div" className="relative">
<Menu.Button title={buttonTitle} className={`flex ${buttonClasses}`}>
{buttonContent}
</Menu.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-100"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
className={`z-50 absolute -right-1.5 mt-3 origin-top-right rounded-md bg-white shadow-md drop-shadow-md ring-1 ring-black ring-opacity-5 focus:outline-none ${menuClasses}`}
>
{menuItems.map((mi, i) => (
<Menu.Item key={`menu-item-${i}`}>{mi}</Menu.Item>
))}
</Menu.Items>
</Transition>
</Menu>
);
}
interface ModalProps {
buttonContent: ReactNode;
buttonClasses?: string;
buttonTitle?: string;
modalContent: (close: () => void) => ReactElement;
modalClasses?: string;
}
// Uses Headless Popover, which is a more general purpose dropdown box
export function DropdownModal({
buttonContent,
buttonClasses,
buttonTitle,
modalContent,
modalClasses,
}: ModalProps) {
return (
<Popover className="relative">
<Popover.Button title={buttonTitle} className={`flex ${buttonClasses}`}>
{buttonContent}
</Popover.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-100"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Popover.Panel
className={`z-50 absolute mt-3 origin-top-right rounded-md bg-white shadow-md drop-shadow-md ring-1 ring-black ring-opacity-5 focus:outline-none ${modalClasses}`}
>
{({ close }) => modalContent(close)}
</Popover.Panel>
</Transition>
</Popover>
);
}

@ -0,0 +1,64 @@
import { Dialog, Transition } from '@headlessui/react';
import { Fragment, PropsWithChildren } from 'react';
import XCircle from '../../images/icons/x-circle.svg';
import { IconButton } from '../buttons/IconButton';
export function Modal({
isOpen,
title,
close,
width,
children,
}: PropsWithChildren<{ isOpen: boolean; title: string; close: () => void; width?: string }>) {
return (
<Transition appear show={isOpen} as={Fragment}>
<Dialog as="div" className="relative z-30" onClose={close}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black bg-opacity-25" />
</Transition.Child>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel
className={`w-full ${
width || 'max-w-xs'
} max-h-[90vh] transform overflow-auto rounded-md bg-white px-4 py-4 text-left shadow-lg transition-all`}
>
<Dialog.Title as="h3" className="text text-gray-700">
{title}
</Dialog.Title>
{children}
<div className="absolute right-3 top-3">
<IconButton
imgSrc={XCircle}
onClick={close}
title="Close"
classes="hover:rotate-90"
/>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition>
);
}

@ -1,6 +1,5 @@
import Image from 'next/image';
import Link from 'next/link';
import useDropdownMenu from 'react-accessible-dropdown-menu-hook';
import { links } from '../../consts/links';
import BookIcon from '../../images/icons/book.svg';
@ -11,16 +10,12 @@ import InfoIcon from '../../images/icons/info-circle.svg';
import Explorer from '../../images/logos/hyperlane-explorer.svg';
import Logo from '../../images/logos/hyperlane-logo.svg';
import Name from '../../images/logos/hyperlane-name.svg';
import { DropdownMenu } from '../layout/Dropdown';
import { MiniSearchBar } from '../search/MiniSearchBar';
const PAGES_EXCLUDING_SEARCH = ['/', '/debugger'];
export function Header({ pathName }: { pathName: string }) {
const { buttonProps, itemProps, isOpen, setIsOpen } = useDropdownMenu(4);
const closeDropdown = () => {
setIsOpen(false);
};
const showSearch = !PAGES_EXCLUDING_SEARCH.includes(pathName);
return (
@ -52,46 +47,42 @@ export function Header({ pathName }: { pathName: string }) {
</a>
{showSearch && <MiniSearchBar />}
</nav>
{/* Dropdown menu, used on mobile */}
<div className="relative flex item-center sm:hidden mr-2">
<button className="hover:opacity-70 transition-all" {...buttonProps}>
<Image src={HamburgerIcon} width={22} height={22} alt="..." />
</button>
<DropdownMenu
buttonContent={<Image src={HamburgerIcon} width={22} height={22} alt="..." />}
buttonClasses="hover:opacity-80 active:opacity-70 transition-all"
buttonTitle="Options"
menuItems={[
<Link href="/" className={styles.dropdownOption} key="dropdown-item-home">
<DropdownItemContent icon={HouseIcon} text="Home" />
</Link>,
<Link href="/api-docs" className={styles.dropdownOption} key="dropdown-item-api">
<DropdownItemContent icon={DatabaseIcon} text="API" />
</Link>,
<a
className={styles.dropdownOption}
target="_blank"
href={links.docs}
rel="noopener noreferrer"
key="dropdown-item-docs"
>
<DropdownItemContent icon={BookIcon} text="Docs" />
</a>,
<a
className={styles.dropdownOption}
target="_blank"
href={links.home}
rel="noopener noreferrer"
key="dropdown-item-about"
>
<DropdownItemContent icon={InfoIcon} text="About" />
</a>,
]}
menuClasses="p-2 w-[7.5rem] right-0"
/>
</div>
</div>
{/* Dropdown menu, used on mobile */}
<nav className={`${styles.dropdownContainer} ${!isOpen && 'hidden'} right-0`} role="menu">
<Link href="/" {...itemProps[0]} className={styles.dropdownOption} onClick={closeDropdown}>
<DropdownItemContent icon={HouseIcon} text="Home" />
</Link>
<Link
href="/api-docs"
{...itemProps[1]}
className={styles.dropdownOption}
onClick={closeDropdown}
>
<DropdownItemContent icon={DatabaseIcon} text="API" />
</Link>
<a
{...itemProps[2]}
onClick={closeDropdown}
className={styles.dropdownOption}
target="_blank"
href={links.docs}
rel="noopener noreferrer"
>
<DropdownItemContent icon={BookIcon} text="Docs" />
</a>
<a
{...itemProps[3]}
onClick={closeDropdown}
className={styles.dropdownOption}
target="_blank"
href={links.home}
rel="noopener noreferrer"
>
<DropdownItemContent icon={InfoIcon} text="About" />
</a>
</nav>
</header>
);
}
@ -108,8 +99,6 @@ function DropdownItemContent({ icon, text }: { icon: any; text: string }) {
const styles = {
navLink:
'pt-px flex items-center tracking-wide text-gray-600 text-[0.95rem] hover:underline hover:opacity-80 active:opacity-70 decoration-2 underline-offset-[6px] transition-all',
dropdownContainer: 'dropdown-menu w-[7.5rem] mt-1 mr-px bg-gray-50 shadow-md',
dropdownOption:
'flex items-center cursor-pointer p-2 mt-1 rounded text-gray-600 hover:underline decoration-2 underline-offset-4 transition-all',
activeEnv: 'font-medium cursor-default hover:no-underline',
};

@ -1,19 +1,19 @@
import Image from 'next/image';
import { useState } from 'react';
import useDropdownMenu from 'react-accessible-dropdown-menu-hook';
import { ChainMetadata, mainnetChainsMetadata, testnetChainsMetadata } from '@hyperlane-xyz/sdk';
import FunnelIcon from '../../images/icons/funnel.svg';
import CubeIcon from '../../images/icons/cube.svg';
import GearIcon from '../../images/icons/gear.svg';
import { getChainDisplayName } from '../../utils/chains';
import { arrayToObject } from '../../utils/objects';
import { BorderedButton } from '../buttons/BorderedButton';
import { TextButton } from '../buttons/TextButton';
import { ChainIcon } from '../icons/ChainIcon';
import { ChevronIcon } from '../icons/Chevron';
import { XIcon } from '../icons/XIcon';
import { CheckBox } from '../input/Checkbox';
import { DatetimeField } from '../input/DatetimeField';
import { DropdownMenu, DropdownModal } from '../layout/Dropdown';
const mainnetAndTestChains = [...mainnetChainsMetadata, ...testnetChainsMetadata];
@ -40,14 +40,6 @@ export function SearchFilterBar({
}: Props) {
return (
<div className="flex items-center space-x-2 md:space-x-4">
<div className="w-px h-8 bg-gray-200"></div>
<Image
src={FunnelIcon}
width={20}
height={20}
className="hidden sm:block opacity-20"
alt=""
/>
<ChainMultiSelector
text="Origin"
header="Origin Chains"
@ -68,6 +60,8 @@ export function SearchFilterBar({
endValue={endTimestamp}
onChangeEndValue={onChangeEndTimestamp}
/>
<div className="w-px h-8 bg-gray-200"></div>
<OptionsDropdownMenu />
</div>
);
}
@ -85,11 +79,6 @@ function ChainMultiSelector({
onChangeValue: (value: string | null) => void;
position?: string;
}) {
const { buttonProps, isOpen, setIsOpen } = useDropdownMenu(1);
const closeDropdown = () => {
setIsOpen(false);
};
// Need local state as buffer before user hits apply
const [checkedChains, setCheckedChains] = useState(
value ? arrayToObject(value.split(',')) : arrayToObject(mainnetAndTestChains.map((c) => c.id)),
@ -134,7 +123,7 @@ function ChainMultiSelector({
setCheckedChains({});
};
const onClickApply = () => {
const onClickApply = (closeDropdown?: () => void) => {
const checkedList = Object.keys(checkedChains).filter((c) => !!checkedChains[c]);
if (checkedList.length === 0 || checkedList.length === mainnetAndTestChains.length) {
// Use null value, indicating to filter needed
@ -142,32 +131,23 @@ function ChainMultiSelector({
} else {
onChangeValue(checkedList.join(','));
}
closeDropdown();
if (closeDropdown) closeDropdown();
};
return (
<div className="relative">
<button
className="text-sm sm:min-w-[5.8rem] px-1 sm:px-2.5 py-0.5 flex items-center justify-center rounded border border-gray-500 hover:opacity-70 active:opacity-60 transition-all"
{...buttonProps}
>
<span className="text-gray-700 py-px">{text}</span>
<ChevronIcon direction="s" width={9} height={5} classes="ml-2 opacity-80" />
</button>
<div
className={`dropdown-menu w-88 ${
position || 'right-0'
} top-10 bg-white shadow-md drop-shadow-md xs:border-blue-50 ${!isOpen && 'hidden'}`}
role="menu"
>
<div className="absolute top-1.5 right-1.5">
<XIcon onClick={closeDropdown} />
</div>
<div className="py-0.5 px-1.5">
<div className="flex items-center">
<DropdownModal
buttonContent={
<>
<span className="text-gray-700 py-px">{text}</span>
<ChevronIcon direction="s" width={9} height={5} classes="ml-2 opacity-80" />
</>
}
buttonClasses="text-sm sm:min-w-[5.8rem] px-1 sm:px-2.5 py-0.5 flex items-center justify-center rounded border border-gray-500 hover:opacity-70 active:opacity-60 transition-all"
modalContent={(closeDropdown) => (
<div className="p-4">
<div className="flex items-center justify-between">
<h3 className="text-gray-700 text-lg">{header}</h3>
<div className="flex ml-[4.7rem]">
<div className="flex mr-4">
<TextButton classes="text-sm underline underline-offset-2" onClick={onToggleAll}>
All
</TextButton>
@ -230,12 +210,16 @@ function ChainMultiSelector({
))}
</div>
</div>
<BorderedButton classes="mt-2.5 text-sm px-2 py-1 w-full" onClick={onClickApply}>
<BorderedButton
classes="mt-2.5 text-sm px-2 py-1 w-full"
onClick={() => onClickApply(closeDropdown)}
>
Apply
</BorderedButton>
</div>
</div>
</div>
)}
modalClasses={`w-88 ${position || 'right-0'}`}
/>
);
}
@ -250,11 +234,6 @@ function DatetimeSelector({
endValue: number | null;
onChangeEndValue: (value: number | null) => void;
}) {
const { buttonProps, isOpen, setIsOpen } = useDropdownMenu(1);
const closeDropdown = () => {
setIsOpen(false);
};
// Need local state as buffer before user hits apply
const [startTime, setStartTime] = useState<number | null>(startValue);
const [endTime, setEndTime] = useState<number | null>(endValue);
@ -264,35 +243,26 @@ function DatetimeSelector({
setEndTime(null);
};
const onClickApply = () => {
const onClickApply = (closeDropdown?: () => void) => {
onChangeStartValue(startTime);
onChangeEndValue(endTime);
closeDropdown();
if (closeDropdown) closeDropdown();
};
return (
<div className="relative">
<button
className="text-sm px-1 sm:px-2.5 py-0.5 flex items-center justify-center rounded border border-gray-500 hover:opacity-70 active:opacity-60 transition-all"
{...buttonProps}
>
<span className="text-gray-700 py-px px-2">Time</span>
<ChevronIcon direction="s" width={9} height={5} classes="ml-2 opacity-80" />
</button>
<div
className={`dropdown-menu w-60 top-10 right-0 bg-white shadow-md drop-shadow-md xs:border-blue-50 ${
!isOpen && 'hidden'
}`}
role="menu"
>
<div className="absolute top-1.5 right-1.5">
<XIcon onClick={closeDropdown} />
</div>
<div className="py-0.5 px-1.5">
<DropdownModal
buttonContent={
<>
<span className="text-gray-700 py-px px-2">Time</span>
<ChevronIcon direction="s" width={9} height={5} classes="ml-2 opacity-80" />
</>
}
buttonClasses="text-sm px-1 sm:px-2.5 py-0.5 flex items-center justify-center rounded border border-gray-500 hover:opacity-70 active:opacity-60 transition-all"
modalContent={(closeDropdown) => (
<div className="p-4" key="date-time-selector">
<div className="flex items-center justify-between">
<h3 className="text-gray-700 text-lg">Time Range</h3>
<div className="flex mr-6 pt-1">
<div className="flex pt-1">
<TextButton classes="text-sm underline underline-offset-2" onClick={onClickClear}>
Clear
</TextButton>
@ -304,11 +274,36 @@ function DatetimeSelector({
<h4 className="mt-3 mb-1 text-gray-700">End Time</h4>
<DatetimeField timestamp={endTime} onChange={setEndTime} />
</div>
<BorderedButton classes="mt-4 text-sm px-2 py-1 w-full" onClick={onClickApply}>
<BorderedButton
classes="mt-4 text-sm px-2 py-1 w-full"
onClick={() => onClickApply(closeDropdown)}
>
Apply
</BorderedButton>
</div>
</div>
</div>
)}
modalClasses="w-60 -right-8"
/>
);
}
function OptionsDropdownMenu() {
return (
<DropdownMenu
buttonContent={<Image src={GearIcon} width={24} height={24} className="opacity-40" alt="" />}
buttonClasses="hover:opacity-80 active:opacity-70 transition-all"
buttonTitle="Options"
menuItems={[
<button
className="w-full flex items-center px-4 py-3 mt-1 text-sm hover:bg-gray-100 active:bg-gray-200 transition-all"
onClick={() => alert('hi')}
key="configure-custom-chain"
>
<Image src={CubeIcon} width={16} height={16} alt="" />
<div className="ml-2">Configure Chains</div>
</button>,
]}
menuClasses="w-44 right-0"
/>
);
}

@ -2,8 +2,8 @@ export const links = {
home: 'https://www.hyperlane.xyz',
discord: 'https://discord.gg/VK9ZUy3aTV',
github: 'https://github.com/hyperlane-xyz',
docs: 'https://docs.hyperlane.xyz/hyperlane-docs',
chains: 'https://docs.hyperlane.xyz/hyperlane-docs/developers/domains',
docs: 'https://docs.hyperlane.xyz',
chains: 'https://docs.hyperlane.xyz/docs/resources/domains',
jobs: 'https://jobs.lever.co/Hyperlane',
twitter: 'https://twitter.com/hyperlane_xyz',
blog: 'https://medium.com/hyperlane',

@ -89,7 +89,7 @@ export function MessageSearch() {
/>
<div className="w-full min-h-[38rem] mt-5 bg-white shadow-md border border-blue-50 rounded overflow-auto relative">
<div className="px-2 py-3 sm:px-4 md:px-5 flex items-center justify-between">
<h2 className="pl-0.5 text-gray-700">
<h2 className="w-min sm:w-fit pl-0.5 text-gray-700">
{!hasInput ? 'Latest Messages' : 'Search Results'}
</h2>
<SearchFilterBar

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-funnel-fill" viewBox="0 0 16 16">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5v-2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 313 B

After

Width:  |  Height:  |  Size: 287 B

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48"><path d="m388 976-20-126q-19-7-40-19t-37-25l-118 54-93-164 108-79q-2-9-2.5-20.5T185 576q0-9 .5-20.5T188 535L80 456l93-164 118 54q16-13 37-25t40-18l20-127h184l20 126q19 7 40.5 18.5T669 346l118-54 93 164-108 77q2 10 2.5 21.5t.5 21.5q0 10-.5 21t-2.5 21l108 78-93 164-118-54q-16 13-36.5 25.5T592 850l-20 126H388Zm92-270q54 0 92-38t38-92q0-54-38-92t-92-38q-54 0-92 38t-38 92q0 54 38 92t92 38Z" fill=""/></svg>

After

Width:  |  Height:  |  Size: 490 B

@ -1 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="1.2370047569274902 1 139.0608673095703 322"><path d="M6.3 1h61.3a20 20 0 0 1 18.7 13L140 158.3a5 5 0 0 1 0 3.4l-.3.9-53.5 147.2A20 20 0 0 1 67.4 323H6.2a5 5 0 0 1-4.7-6.6l55.2-158.1L1.7 7.7A5 5 0 0 1 6.2 1Z" fill="#025AA1"></path></svg>
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="1.2370047569274902 1 139.0608673095703 322"><path d="M6.3 1h61.3a20 20 0 0 1 18.7 13L140 158.3a5 5 0 0 1 0 3.4l-.3.9-53.5 147.2A20 20 0 0 1 67.4 323H6.2a5 5 0 0 1-4.7-6.6l55.2-158.1L1.7 7.7A5 5 0 0 1 6.2 1Z" fill="#2362C1"></path></svg>

Before

Width:  |  Height:  |  Size: 297 B

After

Width:  |  Height:  |  Size: 297 B

@ -1 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122 32"><path d="M.97 22.92h2.74V4.15H.98V3.08h17.68v5.96h-1.07c-.04-.75-.1-1.42-.19-2-.08-.6-.25-1.1-.52-1.51-.53-.84-1.6-1.3-3.23-1.38H7.4v8.58h3.41a3.5 3.5 0 0 0 1.78-.36c.42-.26.68-.7.77-1.33l.04-.58.05-.61h1.15v7.05h-1.15a37.27 37.27 0 0 1-.1-1.4c-.08-.63-.34-1.07-.77-1.32a3.4 3.4 0 0 0-1.77-.38H7.4v9.13h5.85c2.4 0 3.85-1.1 4.36-3.32.15-.64.24-1.3.29-1.97h1.06V24H.97v-1.08Z" fill="#025AA1"/><path d="M21.1 22.93H23l4.28-5.08-5.07-6.77h-1.36v-1.07h7.3v1.07H26.2l3.23 4.27 3.51-4.27h-1.9v-1.07h4.98v1.07h-1.56l-4.34 5.18 5.08 6.67h1.38V24h-7.24v-1.07h1.75L28 18.76l-3.45 4.17h1.82V24H21.1v-1.07Z" fill="#025AA1"/><path d="M42.66 11.5c1.05-1.14 2.67-1.72 4.84-1.72a6.38 6.38 0 0 1 4.29 1.73c1.28 1.28 1.91 3.07 1.91 5.38 0 2.3-.66 4.12-1.98 5.43a6.63 6.63 0 0 1-4.84 1.95 7.61 7.61 0 0 1-3.38-.75 4.6 4.6 0 0 1-.84-.52v7.59h2.47v1.07h-8.08v-1.07h2.05V11.11h-2.18V10h5.74v1.5Zm3.65 11.6c2.38 0 3.57-2 3.57-6.02 0-2.98-.65-4.86-1.93-5.63a3.15 3.15 0 0 0-1.71-.4 4 4 0 0 0-2.01.6 4.7 4.7 0 0 0-1.57 1.5v8.39a4.9 4.9 0 0 0 2.7 1.45c.32.07.64.1.95.1Z" fill="#025AA1"/><path d="M55.17 22.93h2.13V2.06h-2.23V.98h5.85v21.95h2.3V24h-8.05v-1.07Z" fill="#025AA1"/><path d="M64.12 17c0-2.15.69-3.9 2.05-5.22a7.1 7.1 0 0 1 5.16-2c2.08 0 3.79.67 5.13 2A6.98 6.98 0 0 1 78.48 17c0 2.15-.67 3.9-2.01 5.25a6.89 6.89 0 0 1-5.13 2.02 7.07 7.07 0 0 1-5.18-2.02A7.08 7.08 0 0 1 64.12 17Zm7.18 6.14c1.84 0 2.92-1.25 3.24-3.76.1-.75.14-1.55.14-2.4 0-1.93-.22-3.37-.66-4.33a2.79 2.79 0 0 0-2.72-1.72c-1.84 0-2.92 1.21-3.24 3.64-.09.73-.14 1.54-.14 2.4 0 1.93.22 3.4.66 4.38a2.8 2.8 0 0 0 2.72 1.79Z" fill="#025AA1"/><path d="M85.71 11.9a6.76 6.76 0 0 1 4.76-2.12c.55 0 1.03.18 1.45.55.42.36.63.83.63 1.4s-.18 1.03-.54 1.39c-.35.35-.78.53-1.3.53a1.8 1.8 0 0 1-1.3-.52 1.8 1.8 0 0 1-.51-1.31c0-.21.03-.43.1-.64a7.2 7.2 0 0 0-3.29 2.03v9.74h3V24h-8.62v-1.05h2.04V11.08h-2.05v-1.07h5.63v1.89Z" fill="#025AA1"/><path d="M107 21.6c-1.43 1.78-3.47 2.67-6.11 2.67a7.6 7.6 0 0 1-5.16-2.07 7.05 7.05 0 0 1-2.06-5.23c0-2.12.7-3.85 2.08-5.18a7.3 7.3 0 0 1 5.28-2c3.13 0 5.1 1.32 5.91 3.94.27.84.4 1.78.4 2.83h-9.9v.41c0 2.82.8 4.67 2.4 5.55.53.3 1.18.45 1.92.45 1.66 0 3.17-.67 4.52-2.02l.72.66Zm-3.34-6.16a7.15 7.15 0 0 0-.67-3.33c-.42-.78-1.13-1.17-2.1-1.17-1.98 0-3.1 1.5-3.38 4.5h6.15Z" fill="#025AA1"/><path d="M114.92 11.9a6.76 6.76 0 0 1 4.75-2.12c.55 0 1.03.18 1.45.55.42.36.63.83.63 1.4s-.18 1.03-.53 1.39c-.36.35-.79.53-1.3.53s-.94-.17-1.3-.52c-.34-.35-.52-.8-.52-1.31 0-.21.04-.43.11-.64a7.2 7.2 0 0 0-3.3 2.03v9.74h3V24h-8.61v-1.05h2.03V11.08h-2.05v-1.07h5.64v1.89Z" fill="#025AA1"/></svg>
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122 32"><path d="M.97 22.92h2.74V4.15H.98V3.08h17.68v5.96h-1.07c-.04-.75-.1-1.42-.19-2-.08-.6-.25-1.1-.52-1.51-.53-.84-1.6-1.3-3.23-1.38H7.4v8.58h3.41a3.5 3.5 0 0 0 1.78-.36c.42-.26.68-.7.77-1.33l.04-.58.05-.61h1.15v7.05h-1.15a37.27 37.27 0 0 1-.1-1.4c-.08-.63-.34-1.07-.77-1.32a3.4 3.4 0 0 0-1.77-.38H7.4v9.13h5.85c2.4 0 3.85-1.1 4.36-3.32.15-.64.24-1.3.29-1.97h1.06V24H.97v-1.08Z" fill="#2362C1"/><path d="M21.1 22.93H23l4.28-5.08-5.07-6.77h-1.36v-1.07h7.3v1.07H26.2l3.23 4.27 3.51-4.27h-1.9v-1.07h4.98v1.07h-1.56l-4.34 5.18 5.08 6.67h1.38V24h-7.24v-1.07h1.75L28 18.76l-3.45 4.17h1.82V24H21.1v-1.07Z" fill="#2362C1"/><path d="M42.66 11.5c1.05-1.14 2.67-1.72 4.84-1.72a6.38 6.38 0 0 1 4.29 1.73c1.28 1.28 1.91 3.07 1.91 5.38 0 2.3-.66 4.12-1.98 5.43a6.63 6.63 0 0 1-4.84 1.95 7.61 7.61 0 0 1-3.38-.75 4.6 4.6 0 0 1-.84-.52v7.59h2.47v1.07h-8.08v-1.07h2.05V11.11h-2.18V10h5.74v1.5Zm3.65 11.6c2.38 0 3.57-2 3.57-6.02 0-2.98-.65-4.86-1.93-5.63a3.15 3.15 0 0 0-1.71-.4 4 4 0 0 0-2.01.6 4.7 4.7 0 0 0-1.57 1.5v8.39a4.9 4.9 0 0 0 2.7 1.45c.32.07.64.1.95.1Z" fill="#2362C1"/><path d="M55.17 22.93h2.13V2.06h-2.23V.98h5.85v21.95h2.3V24h-8.05v-1.07Z" fill="#2362C1"/><path d="M64.12 17c0-2.15.69-3.9 2.05-5.22a7.1 7.1 0 0 1 5.16-2c2.08 0 3.79.67 5.13 2A6.98 6.98 0 0 1 78.48 17c0 2.15-.67 3.9-2.01 5.25a6.89 6.89 0 0 1-5.13 2.02 7.07 7.07 0 0 1-5.18-2.02A7.08 7.08 0 0 1 64.12 17Zm7.18 6.14c1.84 0 2.92-1.25 3.24-3.76.1-.75.14-1.55.14-2.4 0-1.93-.22-3.37-.66-4.33a2.79 2.79 0 0 0-2.72-1.72c-1.84 0-2.92 1.21-3.24 3.64-.09.73-.14 1.54-.14 2.4 0 1.93.22 3.4.66 4.38a2.8 2.8 0 0 0 2.72 1.79Z" fill="#2362C1"/><path d="M85.71 11.9a6.76 6.76 0 0 1 4.76-2.12c.55 0 1.03.18 1.45.55.42.36.63.83.63 1.4s-.18 1.03-.54 1.39c-.35.35-.78.53-1.3.53a1.8 1.8 0 0 1-1.3-.52 1.8 1.8 0 0 1-.51-1.31c0-.21.03-.43.1-.64a7.2 7.2 0 0 0-3.29 2.03v9.74h3V24h-8.62v-1.05h2.04V11.08h-2.05v-1.07h5.63v1.89Z" fill="#2362C1"/><path d="M107 21.6c-1.43 1.78-3.47 2.67-6.11 2.67a7.6 7.6 0 0 1-5.16-2.07 7.05 7.05 0 0 1-2.06-5.23c0-2.12.7-3.85 2.08-5.18a7.3 7.3 0 0 1 5.28-2c3.13 0 5.1 1.32 5.91 3.94.27.84.4 1.78.4 2.83h-9.9v.41c0 2.82.8 4.67 2.4 5.55.53.3 1.18.45 1.92.45 1.66 0 3.17-.67 4.52-2.02l.72.66Zm-3.34-6.16a7.15 7.15 0 0 0-.67-3.33c-.42-.78-1.13-1.17-2.1-1.17-1.98 0-3.1 1.5-3.38 4.5h6.15Z" fill="#2362C1"/><path d="M114.92 11.9a6.76 6.76 0 0 1 4.75-2.12c.55 0 1.03.18 1.45.55.42.36.63.83.63 1.4s-.18 1.03-.53 1.39c-.36.35-.79.53-1.3.53s-.94-.17-1.3-.52c-.34-.35-.52-.8-.52-1.31 0-.21.04-.43.11-.64a7.2 7.2 0 0 0-3.3 2.03v9.74h3V24h-8.61v-1.05h2.03V11.08h-2.05v-1.07h5.64v1.89Z" fill="#2362C1"/></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

@ -10,9 +10,9 @@ export default function Document() {
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#025aa1" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#2362C1" />
<link rel="shortcut icon" href="/favicon.ico" />
<meta name="msapplication-TileColor" content="#025aa1" />
<meta name="msapplication-TileColor" content="#2362C1" />
<meta name="theme-color" content="#ffffff" />
<meta name="application-name" content="Hyperlane Explorer" />

@ -3,7 +3,7 @@ export enum Color {
primaryBlack = '#010101',
primaryWhite = '#FFFFFF',
primaryGray = '#6B7280',
primaryBlue = '#025AA1',
primaryBlue = '#2362C1',
primaryBeige = '#F1EDE9',
primaryRed = '#BF1B15',
}

@ -181,23 +181,6 @@ Common animations
}
}
/*
Dropdowns
=========
*/
.dropdown-menu {
position: absolute;
z-index: 100;
text-align: left;
padding: 0.5rem 0.6rem;
border: 1px solid #f1f1f1;
border-radius: 0.4rem;
/* box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); */
transition: transform 0.2s ease, opacity 0.2s ease, visibility 0s linear 0.2s;
will-change: transform;
}
/*
Toasts
======

@ -946,6 +946,18 @@ __metadata:
languageName: node
linkType: hard
"@headlessui/react@npm:^1.7.11":
version: 1.7.11
resolution: "@headlessui/react@npm:1.7.11"
dependencies:
client-only: ^0.0.1
peerDependencies:
react: ^16 || ^17 || ^18
react-dom: ^16 || ^17 || ^18
checksum: 3c9abbc5eaf039fccd309b34269aad761f518c4863e482afddf47579384243ecc0d7b69ecd2f05997e4e079237efa8846c568f5ed8d32df358814a239600de1f
languageName: node
linkType: hard
"@humanwhocodes/config-array@npm:^0.11.6":
version: 0.11.7
resolution: "@humanwhocodes/config-array@npm:0.11.7"
@ -995,6 +1007,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@hyperlane-xyz/explorer@workspace:."
dependencies:
"@headlessui/react": ^1.7.11
"@hyperlane-xyz/sdk": ^1.0.0-beta6
"@metamask/jazzicon": "https://github.com/jmrossy/jazzicon#7a8df28974b4e81129bfbe3cab76308b889032a6"
"@rainbow-me/rainbowkit": ^0.8.0
@ -1017,7 +1030,6 @@ __metadata:
postcss: ^8.4.19
prettier: ^2.8.0
react: ^18.2.0
react-accessible-dropdown-menu-hook: ^3.2.0
react-dom: ^18.2.0
react-toastify: ^9.1.1
tailwindcss: ^3.2.4
@ -2969,7 +2981,7 @@ __metadata:
languageName: node
linkType: hard
"client-only@npm:0.0.1":
"client-only@npm:0.0.1, client-only@npm:^0.0.1":
version: 0.0.1
resolution: "client-only@npm:0.0.1"
checksum: 0c16bf660dadb90610553c1d8946a7fdfb81d624adea073b8440b7d795d5b5b08beb3c950c6a2cf16279365a3265158a236876d92bce16423c485c322d7dfaf8
@ -6391,13 +6403,6 @@ __metadata:
languageName: node
linkType: hard
"react-accessible-dropdown-menu-hook@npm:^3.2.0":
version: 3.2.0
resolution: "react-accessible-dropdown-menu-hook@npm:3.2.0"
checksum: 207abf127d12f07e2bd25164023264f74fe1216eeb8cbbe084ce54cb1f0e60f1792120d84172a04f22710a96d12e58cf74a930dab6be333f82d33d3e39185c6d
languageName: node
linkType: hard
"react-dom@npm:^18.2.0":
version: 18.2.0
resolution: "react-dom@npm:18.2.0"

Loading…
Cancel
Save