diff --git a/app/components/ExtendedDetails/index.tsx b/app/components/ExtendedDetails/index.tsx index 90c9932..5c563a4 100644 --- a/app/components/ExtendedDetails/index.tsx +++ b/app/components/ExtendedDetails/index.tsx @@ -1,84 +1,118 @@ -import React, { useContext } from 'react'; -import { EthereumDataContext } from "@/app/context"; -import Skeleton from 'react-loading-skeleton' -import 'react-loading-skeleton/dist/skeleton.css' -import "./styles.css" +import React, { useContext } from "react"; +import { EthereumDataContext } from "@/app/context"; +import Skeleton from "react-loading-skeleton"; +import "react-loading-skeleton/dist/skeleton.css"; +import "./styles.css"; import { MIN_DEPOSIT_AMOUNT } from "../constants"; import { useWallets } from "@/app/hooks/useWallets"; -import MotionNumber from 'motion-number' +import MotionNumber from "motion-number"; export interface ExtendedDetailsProps { amountEther: undefined | string | number; - target: "Eclipse" | "Ethereum" + target: "Eclipse" | "Ethereum"; feeInEth: number | null; } const TimeIcon: React.FC = () => { return ( - - + + ); -} +}; const GasIcon: React.FC = () => { return ( - - + + ); -} +}; -const ExtendedDetails: React.FC = ({ amountEther, target, feeInEth }) => { +const ExtendedDetails: React.FC = ({ + amountEther, + target, + feeInEth, +}) => { const [gasPrice, ethPrice] = useContext(EthereumDataContext) ?? [null, null]; - const amountEth = (typeof amountEther === "string" ? parseFloat(amountEther) : amountEther) - const { evmWallet, solWallet } = useWallets(); - + const amountEth = + typeof amountEther === "string" ? parseFloat(amountEther) : amountEther; + const { evmWallet, solWallet } = useWallets(); return ( <> -
-
- Route -
Eclipse
-
-
-
- Receive - - -  ETH - +
+
+ Route +
+ Eclipse +
-
-
- - - { target === "Eclipse" ? "~5 mins" : "~7 days" } +
+
+ Receive + + +  ETH
- -
- - {(feeInEth && ethPrice) - ? (amountEth && amountEth >= MIN_DEPOSIT_AMOUNT) - ? <> - ${(feeInEth * ethPrice).toFixed(2)} - - : - - : - } +
+
+ + + {target === "Eclipse" ? "~5 mins" : "~7 days"} + +
+ +
+ + {feeInEth && ethPrice ? ( + amountEth && amountEth >= MIN_DEPOSIT_AMOUNT ? ( + <> + + ${(feeInEth * ethPrice).toFixed(2)} + + + ) : ( + - + ) + ) : ( + + )} +
-
); }; diff --git a/app/components/ExtendedDetails/styles.css b/app/components/ExtendedDetails/styles.css index a9cb197..8a8a003 100644 --- a/app/components/ExtendedDetails/styles.css +++ b/app/components/ExtendedDetails/styles.css @@ -1,4 +1,6 @@ -.tgreen { color: rgba(161, 254, 160, 1); } +.tgreen { + color: rgba(161, 254, 160, 1); +} .gray-text { font-size: 16px; line-height: 19.2px; @@ -19,7 +21,6 @@ font-size: 14px; font-weight: 500; - width: 480px; height: 88px; } @@ -40,4 +41,3 @@ .amount-sum { padding: 8px 16px; } - diff --git a/app/components/Header/ProfileAvatar.tsx b/app/components/Header/ProfileAvatar.tsx index 1d33594..742456e 100644 --- a/app/components/Header/ProfileAvatar.tsx +++ b/app/components/Header/ProfileAvatar.tsx @@ -1,11 +1,15 @@ -import { - DynamicConnectButton, -} from "@dynamic-labs/sdk-react-core"; +import { DynamicConnectButton } from "@dynamic-labs/sdk-react-core"; import { truncateWalletAddress } from "@/lib/stringUtils"; import { ConnectIcon, Chevron } from "../icons"; import ConnectedWallets from "../ConnectedWallets/index"; -import React, { useEffect, useRef, useState, useCallback, useMemo } from "react"; -import { usePathname } from 'next/navigation'; +import React, { + useEffect, + useRef, + useState, + useCallback, + useMemo, +} from "react"; +import { usePathname } from "next/navigation"; import { useWallets } from "@/app/hooks/useWallets"; export const ProfileAvatar: React.FC = () => { @@ -15,45 +19,53 @@ export const ProfileAvatar: React.FC = () => { const openModalRef = useRef(null); const pathname = usePathname(); - const ignoreEvmWallet = pathname === "/gas-station" + const ignoreEvmWallet = pathname === "/gas-station"; const content = useMemo(() => { - if (!solWallet || ( !evmWallet && !ignoreEvmWallet)) { + if (!solWallet || (!evmWallet && !ignoreEvmWallet)) { return ( {!solWallet && !evmWallet ? "Connect Wallets" : "Connect Wallet"} ); } - return truncateWalletAddress(solWallet?.address || ''); + return truncateWalletAddress(solWallet?.address || ""); }, [solWallet, evmWallet]); - const toggleModal = useCallback((e?: React.MouseEvent) => { - if (e) e.stopPropagation(); - if ((evmWallet || ignoreEvmWallet || isModalOpen) && solWallet) { - setIsModalOpen(prevState => !prevState); - } - }, [evmWallet, isModalOpen, solWallet]); + const toggleModal = useCallback( + (e?: React.MouseEvent) => { + if (e) e.stopPropagation(); + if ((evmWallet || ignoreEvmWallet || isModalOpen) && solWallet) { + setIsModalOpen((prevState) => !prevState); + } + }, + [evmWallet, isModalOpen, solWallet] + ); - const handleClickOutside = useCallback((e: MouseEvent) => { - const modalElement = modalRef.current; - const openButtonElement = openModalRef.current; - - const clickedOutsideModal = modalElement && !modalElement.contains(e.target as Node); - const clickedOutsideButton = openButtonElement && !openButtonElement.contains(e.target as Node); - if (clickedOutsideModal && clickedOutsideButton) { - toggleModal(); - } - }, [toggleModal]); + const handleClickOutside = useCallback( + (e: MouseEvent) => { + const modalElement = modalRef.current; + const openButtonElement = openModalRef.current; + + const clickedOutsideModal = + modalElement && !modalElement.contains(e.target as Node); + const clickedOutsideButton = + openButtonElement && !openButtonElement.contains(e.target as Node); + if (clickedOutsideModal && clickedOutsideButton) { + toggleModal(); + } + }, + [toggleModal] + ); useEffect(() => { if (isModalOpen) { - document.addEventListener('mousedown', handleClickOutside); + document.addEventListener("mousedown", handleClickOutside); } else { - document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener("mousedown", handleClickOutside); } return () => { - document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener("mousedown", handleClickOutside); }; }, [isModalOpen, handleClickOutside]); @@ -64,28 +76,27 @@ export const ProfileAvatar: React.FC = () => { } if (modalRef.current) { - modalRef.current.className = isModalOpen ? "connected-wallets-modal modal-active" : "connected-wallets-modal"; + modalRef.current.className = isModalOpen + ? "connected-wallets-modal modal-active" + : "connected-wallets-modal"; } }, [isModalOpen]); return ( -
-
+
- + > + {content} - {(solWallet && ( evmWallet || ignoreEvmWallet)) && } + {solWallet && (evmWallet || ignoreEvmWallet) && }
- +
); }; diff --git a/app/components/Header/index.tsx b/app/components/Header/index.tsx index 005f5cf..6852ab2 100644 --- a/app/components/Header/index.tsx +++ b/app/components/Header/index.tsx @@ -1,4 +1,4 @@ -'use client'; +"use client"; import React from "react"; import { ProfileAvatar } from "./ProfileAvatar"; @@ -6,11 +6,36 @@ import { ProfileAvatar } from "./ProfileAvatar"; export const Header: React.FC<{ isExtended: boolean }> = ({ isExtended }) => { return (
-
- { isExtended - ? Eclipse Logo - : Eclipse Logo - } +
+ {isExtended ? ( +
+ Eclipse Logo + Eclipse Logo +
+ ) : ( + Eclipse Logo + )}
diff --git a/app/components/Sidebar/index.tsx b/app/components/Sidebar/index.tsx index ea495f7..ce598a0 100644 --- a/app/components/Sidebar/index.tsx +++ b/app/components/Sidebar/index.tsx @@ -1,83 +1,171 @@ import "./sidebar.css"; -import Link from 'next/link'; -import { BridgeIcon, TethIcon, ScanIcon, GasStationIcon, EcosystemIcon } from "@/app/components/icons" +import Link from "next/link"; +import { + BridgeIcon, + TethIcon, + ScanIcon, + GasStationIcon, + EcosystemIcon, +} from "@/app/components/icons"; import { NetworkSwitcher } from "../Deposit/NetworkSwitcher"; import { useState, type ReactNode } from "react"; import { toKebabCase } from "@/lib/stringUtils"; -import { usePathname } from 'next/navigation' -import { composeEclipsescanUrl, useNetwork } from "@/app/contexts/NetworkContext"; - +import { usePathname } from "next/navigation"; +import { + composeEclipsescanUrl, + useNetwork, +} from "@/app/contexts/NetworkContext"; const ToggleIcon: React.FC<{ isExtended: boolean }> = ({ isExtended }) => { return ( - - + + ); -} +}; -const SidebarItem: React.FC<{name: string, icon: ReactNode, isExtended: boolean}> = ({ name, icon, isExtended }) => { - const { selectedOption } = useNetwork() +const SidebarItem: React.FC<{ + name: string; + icon: ReactNode; + isExtended: boolean; +}> = ({ name, icon, isExtended }) => { + const { selectedOption } = useNetwork(); const [hover, setHover] = useState(false); const pathName = usePathname(); - let targetHref = toKebabCase(name) - if (targetHref === "eclipsescan") { targetHref = composeEclipsescanUrl(selectedOption) } - if (targetHref === "ecosystem") { targetHref = "https://www.eclipse.xyz/ecosystem" } + let targetHref = toKebabCase(name); + if (targetHref === "eclipsescan") { + targetHref = composeEclipsescanUrl(selectedOption); + } + if (targetHref === "ecosystem") { + targetHref = "https://www.eclipse.xyz/ecosystem"; + } return ( - -
setHover(true)} - onMouseLeave={() => setHover(false)} - > -
- {icon} + +
setHover(true)} + onMouseLeave={() => setHover(false)} + > +
+ {icon} +
+ {isExtended && ( + {name} + )} + + {hover && !isExtended && ( + <> + + + +
+ {name} +
+ + )}
- { isExtended && {name} } - - { hover && !isExtended && ( - <> - - - -
- { name } -
- - )} -
); -} +}; -export const Sidebar: React.FC<{ isExtended: boolean, setIsExtended: React.Dispatch>}> = ({ isExtended, setIsExtended }) => { +export const Sidebar: React.FC<{ + isExtended: boolean; + setIsExtended: React.Dispatch>; +}> = ({ isExtended, setIsExtended }) => { return ( -
+
-
- } /> - } /> - } /> - } /> - } /> +
+ } + /> + } + /> + } + /> + } + /> + } + />
-
{setIsExtended((current) => !current)}}> - + onClick={() => { + setIsExtended((current) => !current); + }} + > +
); }; - diff --git a/app/globals.css b/app/globals.css index c9c6024..3c23f49 100644 --- a/app/globals.css +++ b/app/globals.css @@ -20,14 +20,14 @@ --ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06); --ease-in-expo: cubic-bezier(0.95, 0.05, 0.795, 0.035); --ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.335); - + --ease-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94); --ease-out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1); --ease-out-quart: cubic-bezier(0.165, 0.84, 0.44, 1); --ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1); --ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1); --ease-out-circ: cubic-bezier(0.075, 0.82, 0.165, 1); - + --ease-in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955); --ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1); --ease-in-out-quart: cubic-bezier(0.77, 0, 0.175, 1); @@ -37,8 +37,9 @@ } } -body, html { - font-family: 'IBM Plex Sans', sans-serif; +body, +html { + font-family: "IBM Plex Sans", sans-serif; height: 100%; overflow-x: hidden; color: rgb(var(--foreground-rgb)); @@ -50,21 +51,23 @@ body, html { rgb(var(--background-start-rgb)); } -body { background: black; } +body { + background: black; +} .dynamic-modal { position: absolute; } /* Hide the step arrows in input[type=number] for Chrome, Safari, Edge, Opera */ -input[type=number]::-webkit-outer-spin-button, -input[type=number]::-webkit-inner-spin-button { +input[type="number"]::-webkit-outer-spin-button, +input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } /* Hide the step arrows in input[type=number] for Firefox */ -input[type=number] { +input[type="number"] { -moz-appearance: textfield; } input:focus { @@ -73,7 +76,7 @@ input:focus { } .ecl-logo { - border-right: 1px solid rgba(255, 255, 255, 0.1); + border-right: 1px solid rgba(255, 255, 255, 0.1); overflow: hidden; transition: width 0.3s var(--ease-out-quad); width: 215px; @@ -90,7 +93,7 @@ input:focus { transition: background-color 0.1s var(--ease-out-quad); cursor: pointer; color: rgba(161, 254, 160, 1); - border: 1px solid rgba(161, 254, 160, 0.2) + border: 1px solid rgba(161, 254, 160, 0.2); } .connect-wallet-icon { @@ -113,8 +116,8 @@ input:focus { background: rgba(161, 254, 160, 0.1); } -img[data-testid='iconic-solana'] { - content: url('/eclipse.png'); +img[data-testid="iconic-solana"] { + content: url("/eclipse.png"); } footer { @@ -136,7 +139,7 @@ footer { } .legal-footer a:hover { - color: #A1FEA0; + color: #a1fea0; } /* @@ -175,8 +178,8 @@ footer { padding: 6px; font-size: 14px; div { - gap: 4px; - margin-left: 0px; + gap: 4px; + margin-left: 0px; } } } @@ -200,26 +203,29 @@ footer { } @media (max-height: 933px) { - .main-content, footer { + .main-content, + footer { margin-top: 50px; } } @media (max-height: 765px) { - .main-content, footer { + .main-content, + footer { margin-top: 100px; } } .thirdparty-bridge-pill { svg path { - transition: stroke-opacity 0.3s var(--ease-out-quad), stroke 0.3s var(--ease-out-quad); + transition: stroke-opacity 0.3s var(--ease-out-quad), + stroke 0.3s var(--ease-out-quad); } } .thirdparty-bridge-pill:hover { svg path { - stroke: #A1FEA0; + stroke: #a1fea0; stroke-opacity: 1; } } diff --git a/app/page.tsx b/app/page.tsx index fce4877..2200bf4 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,71 +1,88 @@ -'use client'; +"use client"; import { useEffect, useState } from "react"; import Deposit from "./components/Deposit"; -import { Header } from './components/Header'; -import { Sidebar } from './components/Sidebar'; -import { Footer } from './components/Footer'; -import { TosClickwrap } from './components/TosClickwrap'; +import { Header } from "./components/Header"; +import { Sidebar } from "./components/Sidebar"; +import { Footer } from "./components/Footer"; +import { TosClickwrap } from "./components/TosClickwrap"; import useEthereumData from "@/lib/ethUtils"; import { NetworkProvider } from "@/app/contexts/NetworkContext"; -import { useWalletClient } from "./hooks" -import { EthereumDataContext, WalletClientContext } from "./context" +import { useWalletClient } from "./hooks"; +import { EthereumDataContext, WalletClientContext } from "./context"; import { useSidebar } from "@/app/contexts/SidebarContext"; -import { ThirdpartyBridgeModalProvider } from '@/app/components/ThirdpartyBridgeModal/ThirdpartyBridgeModalContext'; -import { TransactionProvider } from './components/TransactionPool'; -import { SkeletonTheme } from 'react-loading-skeleton' +import { ThirdpartyBridgeModalProvider } from "@/app/components/ThirdpartyBridgeModal/ThirdpartyBridgeModalContext"; +import { TransactionProvider } from "./components/TransactionPool"; +import { SkeletonTheme } from "react-loading-skeleton"; import { Options } from "@/lib/networkUtils"; -import {ToastContainer} from 'react-toastify' +import { ToastContainer } from "react-toastify"; import "react-toastify/dist/ReactToastify.min.css"; export default function Main() { const { isSidebar, setIsSidebar } = useSidebar(); - const [selectedOption, setSelectedOption] = useState(Options.Mainnet) + const [selectedOption, setSelectedOption] = useState(Options.Mainnet); const { gasPrice, ethPrice, blockNumber } = useEthereumData(selectedOption); - const [amountEther, setAmountEther] = useState(undefined); + const [amountEther, setAmountEther] = useState( + undefined + ); const walletClient = useWalletClient(); return ( - + - - -
-
- - -
- -
-
- -
+ + +
+
+ + +
+ +
+
+ +
+
+
-
-
- - + + - + ); } -