diff --git a/public/icons/menu.svg b/public/icons/menu.svg new file mode 100644 index 00000000..85e910be --- /dev/null +++ b/public/icons/menu.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/app/[ticker]/TickerInfo/TickerInfo.module.css b/src/app/[ticker]/TickerInfo/TickerInfo.module.css index b7a1d3d7..b0694c3b 100644 --- a/src/app/[ticker]/TickerInfo/TickerInfo.module.css +++ b/src/app/[ticker]/TickerInfo/TickerInfo.module.css @@ -6,6 +6,7 @@ height: auto; min-height: 100%; } + .assetInfo { display: flex; justify-content: center; @@ -146,3 +147,37 @@ font-weight: 600; margin: 0; } + +@media screen and (max-width: 600px) { + .container { + gap: 1rem; + } + + .assetInfo { + gap: 10px; + } + + .tickerTitle { + font-size: 20px; + } + + .assetInfo img { + width: 34px; + height: 34px; + } + + .actionButtons { + display: grid; + grid-template-columns: repeat(4, auto); + justify-content: stretch; + gap: 7px; + width: 100%; + } + + .supplyButton, + .borrowButton, + .withdrawButton, + .repayButton { + min-width: unset; + } +} diff --git a/src/app/[ticker]/ticker.module.css b/src/app/[ticker]/ticker.module.css index 0124273f..9b1ea0fc 100644 --- a/src/app/[ticker]/ticker.module.css +++ b/src/app/[ticker]/ticker.module.css @@ -91,6 +91,33 @@ width: 100%; } +@media screen and (max-width: 600px) { + .titleWrapper { + width: 90vw; + } + + .title { + font-size: 20px; + } + + .backIcon { + width: 20px; + height: 20px; + } + + .topContainer { + width: 90vw; + flex-direction: column; + justify-content: unset; + gap: 1.6rem; + } + + .grid { + grid-template-columns: auto; + width: 90vw; + } +} + .modalOverlay { position: fixed; top: 0; diff --git a/src/app/earn/earn.module.css b/src/app/earn/earn.module.css index f77fd412..677fb8e3 100644 --- a/src/app/earn/earn.module.css +++ b/src/app/earn/earn.module.css @@ -88,6 +88,37 @@ gap: 25px; } +@media screen and (max-width: 600px) { + .bodyContainer { + width: 90vw; + padding: 2rem 0; + } + + .topSection { + flex-direction: column; + align-items: flex-start; + gap: 1.25rem; + } + + .titleContainer { + gap: 0; + } + + .loBalanceContainer { + flex-direction: column-reverse; + } + + .loTitle { + text-align: left; + } + + .depositSection { + flex-direction: column; + justify-content: unset; + gap: 1rem; + } +} + .assetSquareContainer { position: relative; display: flex; diff --git a/src/app/home/ActionTab/ActionTab.tsx b/src/app/home/ActionTab/ActionTab.tsx index 5b7b2829..10f487d6 100644 --- a/src/app/home/ActionTab/ActionTab.tsx +++ b/src/app/home/ActionTab/ActionTab.tsx @@ -34,17 +34,13 @@ const ActionTab: React.FC = ({ ticker, mode, onClose }) => { const { data: walletBalance, isLoading: isLoadingBalance } = useUserBalance(tokenAddress); - const { data: aoBalance, isLoading: isLoadingAoBalance } = useUserBalance("0syT13r0s0tgPmIed95bJnuSqaD29HQNN8D3ElLSrsc"); - const hasAoForAction = useMemo( - () => { - if (isLoadingAoBalance) return true; - return Quantity.lt( - new Quantity(1n, 2n), - new Quantity(aoBalance, 12n) - ); - }, - [aoBalance, isLoadingAoBalance] + const { data: aoBalance, isLoading: isLoadingAoBalance } = useUserBalance( + "0syT13r0s0tgPmIed95bJnuSqaD29HQNN8D3ElLSrsc", ); + const hasAoForAction = useMemo(() => { + if (isLoadingAoBalance) return true; + return Quantity.lt(new Quantity(1n, 2n), new Quantity(aoBalance, 12n)); + }, [aoBalance, isLoadingAoBalance]); const { lend, isLending, lendError } = useLend({ onSuccess: onClose, @@ -241,7 +237,8 @@ const ActionTab: React.FC = ({ ticker, mode, onClose }) => { exit="hidden" > - You will need a minimal amount of AO for this message to be executed. + You will need a minimal amount of AO for this message to be + executed. )} diff --git a/src/app/home/AssetRow/AssetRow.module.css b/src/app/home/AssetRow/AssetRow.module.css index 6d10a5eb..a8a5f41d 100644 --- a/src/app/home/AssetRow/AssetRow.module.css +++ b/src/app/home/AssetRow/AssetRow.module.css @@ -100,6 +100,20 @@ gap: 5px; } +@media screen and (max-width: 600px) { + .assetRow { + display: grid; + grid-template-columns: auto auto; + gap: 0.85rem 0; + } + + .actionButtons { + grid-column: 1 / -1; + justify-content: flex-start; + padding-left: 52px; + } +} + .supplyBorrowButton { padding: 9px; border-radius: 50px; diff --git a/src/app/home/WithdrawRepay/WithdrawRepay.tsx b/src/app/home/WithdrawRepay/WithdrawRepay.tsx index 3e888dce..f8ad56b1 100644 --- a/src/app/home/WithdrawRepay/WithdrawRepay.tsx +++ b/src/app/home/WithdrawRepay/WithdrawRepay.tsx @@ -14,7 +14,10 @@ import { tokenInput } from "liquidops"; import { useGetPosition } from "@/hooks/LiquidOpsData/useGetPosition"; import { useLoadingScreen } from "@/components/LoadingScreen/useLoadingScreen"; import { useValueLimit } from "@/hooks/data/useValueLimit"; -import { useInfo, useProtocolStats } from "@/hooks/LiquidOpsData/useProtocolStats"; +import { + useInfo, + useProtocolStats, +} from "@/hooks/LiquidOpsData/useProtocolStats"; import { AnimatePresence, motion } from "framer-motion"; import { warningVariants } from "@/components/DropDown/FramerMotion"; import { useCooldown } from "@/hooks/data/useCooldown"; @@ -42,25 +45,21 @@ const WithdrawRepay: React.FC = ({ const { data: oTokenBalance, isLoading: isLoadingOTokenBalance } = useUserBalance(oTokenAddress); - const { data: aoBalance, isLoading: isLoadingAoBalance } = useUserBalance("0syT13r0s0tgPmIed95bJnuSqaD29HQNN8D3ElLSrsc"); - const hasAoForAction = useMemo( - () => { - if (isLoadingAoBalance) return true; - return Quantity.lt( - new Quantity(1n, 2n), - new Quantity(aoBalance, 12n) - ); - }, - [aoBalance, isLoadingAoBalance] + const { data: aoBalance, isLoading: isLoadingAoBalance } = useUserBalance( + "0syT13r0s0tgPmIed95bJnuSqaD29HQNN8D3ElLSrsc", ); + const hasAoForAction = useMemo(() => { + if (isLoadingAoBalance) return true; + return Quantity.lt(new Quantity(1n, 2n), new Quantity(aoBalance, 12n)); + }, [aoBalance, isLoadingAoBalance]); const currentBalance = useMemo( - () => mode === "withdraw" ? lentBalance : positionBalance, - [mode, lentBalance, positionBalance] + () => (mode === "withdraw" ? lentBalance : positionBalance), + [mode, lentBalance, positionBalance], ); const isLoadingCurrentBalance = useMemo( - () => mode === "withdraw" ? isLoadingBalance : isLoadingPosition, - [mode, isLoadingBalance, isLoadingPosition] + () => (mode === "withdraw" ? isLoadingBalance : isLoadingPosition), + [mode, isLoadingBalance, isLoadingPosition], ); const { unlend, isUnlending, unlendError } = useLend({ @@ -137,38 +136,40 @@ const WithdrawRepay: React.FC = ({ } const amount = Quantity.__div( - Quantity.__mul(currentBalance, new Quantity(0n, 12n).fromNumber(percentage)), + Quantity.__mul( + currentBalance, + new Quantity(0n, 12n).fromNumber(percentage), + ), new Quantity(0n, 12n).fromNumber(100), ); setInputValue(amount.toString()); }; - const currentPercentage = useMemo( - () => { - // no data - if ( - !currentBalance || - !inputValue || - Quantity.eq(currentBalance, new Quantity(0n, 12n)) - ) { - return 0; - } + const currentPercentage = useMemo(() => { + // no data + if ( + !currentBalance || + !inputValue || + Quantity.eq(currentBalance, new Quantity(0n, 12n)) + ) { + return 0; + } - if (isNaN(Number(inputValue.replace(/,/g, "")))) return 0; + if (isNaN(Number(inputValue.replace(/,/g, "")))) return 0; - const percentage = Quantity.__div( - Quantity.__mul( - new Quantity(0n, currentBalance.denomination).fromString(inputValue), - new Quantity(0n, currentBalance.denomination).fromNumber(100), - ), - currentBalance, - ); - return Math.min(100, Math.max(0, percentage.toNumber())); - }, - [currentBalance, inputValue] - ); + const percentage = Quantity.__div( + Quantity.__mul( + new Quantity(0n, currentBalance.denomination).fromString(inputValue), + new Quantity(0n, currentBalance.denomination).fromNumber(100), + ), + currentBalance, + ); + return Math.min(100, Math.max(0, percentage.toNumber())); + }, [currentBalance, inputValue]); - const { data: tokenInfo, isLoading: isLoadingTokenInfo } = useInfo(ticker.toUpperCase()); + const { data: tokenInfo, isLoading: isLoadingTokenInfo } = useInfo( + ticker.toUpperCase(), + ); const handleSubmit = () => { setHasUserInteracted(true); @@ -191,13 +192,18 @@ const WithdrawRepay: React.FC = ({ // x _underlying_ = x * totalSupply / totalPooled _oToken_ const { collateralDenomination, denomination } = tokenInfo; const totalPooled = new Quantity( - BigInt(tokenInfo.cash) + BigInt(tokenInfo.totalBorrows) - BigInt(tokenInfo.totalReserves), - BigInt(collateralDenomination) + BigInt(tokenInfo.cash) + + BigInt(tokenInfo.totalBorrows) - + BigInt(tokenInfo.totalReserves), + BigInt(collateralDenomination), + ); + const totalSupply = new Quantity( + tokenInfo.totalSupply, + BigInt(denomination), ); - const totalSupply = new Quantity(tokenInfo.totalSupply, BigInt(denomination)); quantity = Quantity.__convert( Quantity.__div(Quantity.__mul(quantity, totalSupply), totalPooled), - BigInt(denomination) + BigInt(denomination), ); if (oTokenBalance) { @@ -267,7 +273,8 @@ const WithdrawRepay: React.FC = ({ exit="hidden" className={styles.aoNotice} > - You will need a minimal amount of AO for this message to be executed. + You will need a minimal amount of AO for this message to be + executed. )} diff --git a/src/app/home/home.module.css b/src/app/home/home.module.css index 53b63b07..15bbbcc6 100644 --- a/src/app/home/home.module.css +++ b/src/app/home/home.module.css @@ -76,6 +76,17 @@ width: 100%; } +@media screen and (max-width: 600px) { + .grid { + width: 90vw; + grid-template-columns: 1fr; + } + + .widgetContainer { + width: 90vw; + } +} + .modalOverlay { position: fixed; top: 0; diff --git a/src/app/markets/MarketRow/MarketRow.module.css b/src/app/markets/MarketRow/MarketRow.module.css index fe39c932..f0678a54 100644 --- a/src/app/markets/MarketRow/MarketRow.module.css +++ b/src/app/markets/MarketRow/MarketRow.module.css @@ -29,6 +29,18 @@ flex-shrink: 0; } +@media screen and (max-width: 600px) { + .marketRow { + display: grid; + grid-template-columns: auto auto auto; + gap: 1rem; + } + + .assetInfo { + grid-column: 1 / 4; + } +} + .iconWrapper { width: 40px; height: 40px; diff --git a/src/app/markets/MarketStats/MarketStats.module.css b/src/app/markets/MarketStats/MarketStats.module.css index 8f7c84f9..dd9f8b42 100644 --- a/src/app/markets/MarketStats/MarketStats.module.css +++ b/src/app/markets/MarketStats/MarketStats.module.css @@ -15,6 +15,21 @@ border-radius: 24px; } +@media screen and (max-width: 600px) { + .marketStats { + flex-direction: column; + width: 90vw; + gap: 1rem; + } + + .marketContainer { + width: 100%; + justify-content: flex-start; + gap: 30px; + padding: 24px 30px; + } +} + .pieChart { display: flex; justify-content: center; diff --git a/src/app/markets/markets.module.css b/src/app/markets/markets.module.css index 25b2a08e..4fc28625 100644 --- a/src/app/markets/markets.module.css +++ b/src/app/markets/markets.module.css @@ -38,3 +38,11 @@ padding: 24px; border-radius: 24px; } + +@media screen and (max-width: 600px) { + .marketsList { + width: 90vw; + padding: 14px; + gap: 0.7rem; + } +} diff --git a/src/components/Connect/Connect.module.css b/src/components/Connect/Connect.module.css index 8dc9f877..c2733331 100644 --- a/src/components/Connect/Connect.module.css +++ b/src/components/Connect/Connect.module.css @@ -41,6 +41,12 @@ color: var(--primary-palatinate-blue); } +@media screen and (max-width: 600px) { + .profileName { + display: none; + } +} + .connectImage { height: 32px; width: 32px; diff --git a/src/components/Footer/Footer.module.css b/src/components/Footer/Footer.module.css index 9dd8608c..e95d62c8 100644 --- a/src/components/Footer/Footer.module.css +++ b/src/components/Footer/Footer.module.css @@ -15,6 +15,19 @@ gap: 10px; } +@media screen and (max-width: 600px) { + .footer { + padding: 20px 1.5rem; + align-items: flex-start; + } + + .left { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1rem; + } +} + .right { display: flex; justify-content: center; diff --git a/src/components/Footer/Footer.tsx b/src/components/Footer/Footer.tsx index d58aaf2c..a85be75c 100644 --- a/src/components/Footer/Footer.tsx +++ b/src/components/Footer/Footer.tsx @@ -66,20 +66,19 @@ const Footer = () => { Analytics

- + + Terms + + + Privacy + + + {gitHash} +
diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css index f8fbe04e..5cd04954 100644 --- a/src/components/Header/Header.module.css +++ b/src/components/Header/Header.module.css @@ -48,9 +48,9 @@ /* Existing header styles */ .header { display: flex; - justify-content: space-between; align-items: flex-start; - height: 150px; + flex-direction: column; + gap: 1.5rem; padding: 2rem 3rem; box-sizing: border-box; width: 100%; @@ -58,12 +58,23 @@ background-color: white; } -.leftSection { +.topSection { display: flex; - height: 100%; - flex-direction: column; - align-items: flex-start; + align-items: center; justify-content: space-between; + width: 100%; +} + +.connectAndMobileMenu { + display: flex; + align-items: center; + gap: 1rem; +} + +.menuIcon { + display: none; + -webkit-tap-highlight-color: transparent; + cursor: pointer; } .titleAndDropdown { @@ -93,6 +104,44 @@ gap: 1.5rem; } +@media screen and (max-width: 600px) { + .header { + padding: 1.6rem 1.8rem; + } + + .menuIcon { + display: block; + } + + .navLinks { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + width: 100vw; + height: 100vh; + z-index: 1000; + background-color: #fff; + flex-direction: column; + padding: 4rem; + } + + .navLinks:not(.showNavMobile) { + display: none; + } + + .navLinks a { + text-align: center; + } + + .navLinks .menuIcon { + margin-left: auto; + width: 1.3rem; + height: 1.3rem; + } +} + .navLinks a:hover { background-color: var(--primary-ghost-white); } diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index 5ac4a2b8..af99f08a 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -69,6 +69,8 @@ const Header: React.FC = ({ } }, [triggerConnect]); + const [showNavMobile, setShowNavMobile] = useState(false); + return ( <> {isClient && isBannerVisible && ( @@ -105,7 +107,7 @@ const Header: React.FC = ({
-
+
= ({
- +
+ + + Menu setShowNavMobile((val) => !val)} + /> +
- + +
); diff --git a/src/components/Header/MoreDropdown/MoreDropdown.module.css b/src/components/Header/MoreDropdown/MoreDropdown.module.css index 8084aa69..c2e2a077 100644 --- a/src/components/Header/MoreDropdown/MoreDropdown.module.css +++ b/src/components/Header/MoreDropdown/MoreDropdown.module.css @@ -33,6 +33,14 @@ gap: 5px; } +@media screen and (max-width: 600px) { + .moreDropdownContent { + left: 0; + right: 0; + width: 100%; + } +} + .moreDropdownItem { color: var(--primary-palatinate-blue); padding: 10px 15px; diff --git a/src/components/Header/MoreDropdown/MoreDropdown.tsx b/src/components/Header/MoreDropdown/MoreDropdown.tsx index 837e3c14..84866d5d 100644 --- a/src/components/Header/MoreDropdown/MoreDropdown.tsx +++ b/src/components/Header/MoreDropdown/MoreDropdown.tsx @@ -20,6 +20,7 @@ const MoreDropdown: React.FC = ({ items, label }) => { className={styles.moreDropDown} onMouseEnter={() => setIsOpen(true)} onMouseLeave={() => setIsOpen(false)} + onClick={() => setIsOpen((v) => !v)} ref={dropdownRef} >

{label}