Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mobile layout #147

Open
wants to merge 1 commit into
base: eclipse-apps
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 87 additions & 53 deletions app/components/ExtendedDetails/index.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 16C3.5625 16 0 12.4375 0 8C0 3.59375 3.5625 0 8 0C12.4062 0 16 3.59375 16 8C16 12.4375 12.4062 16 8 16ZM7.25 8C7.25 8.25 7.375 8.5 7.5625 8.625L10.5625 10.625C10.9062 10.875 11.375 10.7812 11.5938 10.4375C11.8438 10.0938 11.75 9.625 11.4062 9.375L8.75 7.625V3.75C8.75 3.34375 8.40625 3 7.96875 3C7.5625 3 7.21875 3.34375 7.21875 3.75L7.25 8Z" fill="white" fill-opacity="0.3"/>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8 16C3.5625 16 0 12.4375 0 8C0 3.59375 3.5625 0 8 0C12.4062 0 16 3.59375 16 8C16 12.4375 12.4062 16 8 16ZM7.25 8C7.25 8.25 7.375 8.5 7.5625 8.625L10.5625 10.625C10.9062 10.875 11.375 10.7812 11.5938 10.4375C11.8438 10.0938 11.75 9.625 11.4062 9.375L8.75 7.625V3.75C8.75 3.34375 8.40625 3 7.96875 3C7.5625 3 7.21875 3.34375 7.21875 3.75L7.25 8Z"
fill="white"
fill-opacity="0.3"
/>
</svg>
);
}
};

const GasIcon: React.FC = () => {
return (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 2C1 0.90625 1.875 0 3 0H8C9.09375 0 10 0.90625 10 2V8H10.25C11.75 8 13 9.25 13 10.75V11.75C13 12.1875 13.3125 12.5 13.75 12.5C14.1562 12.5 14.5 12.1875 14.5 11.75V6.9375C13.625 6.71875 13 5.9375 13 5V3L12 2C11.7188 1.75 11.7188 1.28125 12 1C12.25 0.75 12.7188 0.75 13 1L15.4062 3.4375C15.7812 3.8125 16 4.3125 16 4.84375V11.75C16 13 14.9688 14 13.75 14C12.5 14 11.5 13 11.5 11.75V10.75C11.5 10.0625 10.9375 9.5 10.25 9.5H10V14C10.5312 14 11 14.4688 11 15C11 15.5625 10.5312 16 10 16H1C0.4375 16 0 15.5625 0 15C0 14.4688 0.4375 14 1 14V2ZM3 5.5C3 5.78125 3.21875 6 3.5 6H7.5C7.75 6 8 5.78125 8 5.5V2.5C8 2.25 7.75 2 7.5 2H3.5C3.21875 2 3 2.25 3 2.5V5.5Z" fill="white" fill-opacity="0.3"/>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 2C1 0.90625 1.875 0 3 0H8C9.09375 0 10 0.90625 10 2V8H10.25C11.75 8 13 9.25 13 10.75V11.75C13 12.1875 13.3125 12.5 13.75 12.5C14.1562 12.5 14.5 12.1875 14.5 11.75V6.9375C13.625 6.71875 13 5.9375 13 5V3L12 2C11.7188 1.75 11.7188 1.28125 12 1C12.25 0.75 12.7188 0.75 13 1L15.4062 3.4375C15.7812 3.8125 16 4.3125 16 4.84375V11.75C16 13 14.9688 14 13.75 14C12.5 14 11.5 13 11.5 11.75V10.75C11.5 10.0625 10.9375 9.5 10.25 9.5H10V14C10.5312 14 11 14.4688 11 15C11 15.5625 10.5312 16 10 16H1C0.4375 16 0 15.5625 0 15C0 14.4688 0.4375 14 1 14V2ZM3 5.5C3 5.78125 3.21875 6 3.5 6H7.5C7.75 6 8 5.78125 8 5.5V2.5C8 2.25 7.75 2 7.5 2H3.5C3.21875 2 3 2.25 3 2.5V5.5Z"
fill="white"
fill-opacity="0.3"
/>
</svg>
);
}
};

const ExtendedDetails: React.FC<ExtendedDetailsProps> = ({ amountEther, target, feeInEth }) => {
const ExtendedDetails: React.FC<ExtendedDetailsProps> = ({
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 (
<>
<div className="tx-sum flex flex-col !h-[auto]">
<div className="route-box flex flex-row justify-between items-center">
<span style={{ color: "rgba(255, 255, 255, 0.6)" }}>Route</span>
<div className="route-text flex items-center justify-between">Eclipse</div>
</div>
<div className="amount-sum flex flex-row justify-between items-center">
<div className="flex gap-[4px]">
<span style={{ color: "rgba(255, 255, 255, 0.3)"}}>Receive</span>
<span className="tgreen flex items-center">
<MotionNumber
value={(parseFloat(String(amountEther ?? "0")) ? parseFloat(String(amountEther ?? "0")) : 0).toFixed(3)}
format={{ notation: 'standard' }}
transition={{
y: { type: 'spring', duration: 0.65, bounce: 0.25 }
}}
locales="en-US"
/>
<span>&nbsp;ETH</span>
</span>
<div className="tx-sum flex flex-col !h-[auto] w-auto">
<div className="route-box flex flex-row justify-between items-center">
<span style={{ color: "rgba(255, 255, 255, 0.6)" }}>Route</span>
<div className="route-text flex items-center justify-between">
Eclipse
</div>
</div>
<div className="flex flex-row items-center" style={{ gap: "8px" }}>
<div className="flex items-center gap-[4px]">
<TimeIcon />
<span className="tgreen">
{ target === "Eclipse" ? "~5 mins" : "~7 days" }
<div className="amount-sum flex flex-row justify-between items-center">
<div className="flex gap-[4px]">
<span style={{ color: "rgba(255, 255, 255, 0.3)" }}>Receive</span>
<span className="tgreen flex items-center">
<MotionNumber
value={(parseFloat(String(amountEther ?? "0"))
? parseFloat(String(amountEther ?? "0"))
: 0
).toFixed(3)}
format={{ notation: "standard" }}
transition={{
y: { type: "spring", duration: 0.65, bounce: 0.25 },
}}
locales="en-US"
/>
<span>&nbsp;ETH</span>
</span>
</div>
<span style={{ color: "rgba(255, 255, 255, 0.3)"}}>•</span>
<div className="flex items-center gap-[4px]">
<GasIcon />
{(feeInEth && ethPrice)
? (amountEth && amountEth >= MIN_DEPOSIT_AMOUNT)
? <>
<span className="tgreen">${(feeInEth * ethPrice).toFixed(2)}</span>
</>
: <span className="gray-text">-</span>
: <Skeleton width={80} />
}
<div className="flex flex-row items-center" style={{ gap: "8px" }}>
<div className="flex items-center gap-[4px]">
<TimeIcon />
<span className="tgreen">
{target === "Eclipse" ? "~5 mins" : "~7 days"}
</span>
</div>
<span style={{ color: "rgba(255, 255, 255, 0.3)" }}>•</span>
<div className="flex items-center gap-[4px]">
<GasIcon />
{feeInEth && ethPrice ? (
amountEth && amountEth >= MIN_DEPOSIT_AMOUNT ? (
<>
<span className="tgreen">
${(feeInEth * ethPrice).toFixed(2)}
</span>
</>
) : (
<span className="gray-text">-</span>
)
) : (
<Skeleton width={80} />
)}
</div>
</div>
</div>
</div>
</div>
</>
);
};
Expand Down
6 changes: 3 additions & 3 deletions app/components/ExtendedDetails/styles.css
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -19,7 +21,6 @@
font-size: 14px;
font-weight: 500;

width: 480px;
height: 88px;
}

Expand All @@ -40,4 +41,3 @@
.amount-sum {
padding: 8px 16px;
}

89 changes: 50 additions & 39 deletions app/components/Header/ProfileAvatar.tsx
Original file line number Diff line number Diff line change
@@ -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 = () => {
Expand All @@ -15,45 +19,53 @@ export const ProfileAvatar: React.FC = () => {
const openModalRef = useRef<HTMLDivElement>(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 (
<DynamicConnectButton buttonClassName="connect-button-header">
{!solWallet && !evmWallet ? "Connect Wallets" : "Connect Wallet"}
</DynamicConnectButton>
);
}
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]);

Expand All @@ -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 (
<div className="flex items-center space-x-2 p-2">
<div
onClick={toggleModal}
ref={openModalRef}
<div className="flex items-center space-x-2 p-2 flex-1 sm:flex-none justify-end">
<div
onClick={toggleModal}
ref={openModalRef}
className="connect-wallet"
role="button"
aria-haspopup="true"
aria-expanded={isModalOpen}
>
<ConnectIcon connectClassName="connect-wallet-icon" />
>
<ConnectIcon connectClassName="connect-wallet-icon" />
{content}
{(solWallet && ( evmWallet || ignoreEvmWallet)) && <Chevron />}
{solWallet && (evmWallet || ignoreEvmWallet) && <Chevron />}
</div>
<ConnectedWallets
ref={modalRef}
close={toggleModal}
/>
<ConnectedWallets ref={modalRef} close={toggleModal} />
</div>
);
};
37 changes: 31 additions & 6 deletions app/components/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,41 @@
'use client';
"use client";

import React from "react";
import { ProfileAvatar } from "./ProfileAvatar";

export const Header: React.FC<{ isExtended: boolean }> = ({ isExtended }) => {
return (
<header className="header w-full bg-black text-green-500 flex items-center justify-between border-b border-white border-opacity-10">
<div className="ecl-logo flex items-center space-x-2" style={{ width: isExtended ? "215px" : "66px"}}>
{ isExtended
? <img src="/wordmark.png" className="desktop-logo" alt="Eclipse Logo" width={183} height={34} style={{ marginLeft: "14px", maxWidth: "none" }} />
: <img src="/eclipse-e.png" className="mobile-logo" alt="Eclipse Logo" width={35} height={34} style={{ marginLeft: "14px", maxWidth: "none" }} />
}
<div className="flex items-center space-x-2 flex-none sm:flex-1 !w-auto">
{isExtended ? (
<div className="pr-2">
<img
src="/wordmark.png"
className="desktop-logo hidden sm:block"
alt="Eclipse Logo"
width={183}
height={34}
style={{ marginLeft: "14px", maxWidth: "none" }}
/>
<img
src="/eclipse-e.png"
className="mobile-logo block sm:hidden"
alt="Eclipse Logo"
width={35}
height={34}
style={{ marginLeft: "14px", maxWidth: "none" }}
/>
</div>
) : (
<img
src="/eclipse-e.png"
className="mobile-logo"
alt="Eclipse Logo"
width={35}
height={34}
style={{ marginLeft: "14px", maxWidth: "none" }}
/>
)}
</div>
<ProfileAvatar />
</header>
Expand Down
Loading