From 3adc2f92d1dda07081e93523ec84a56c3cac88fe Mon Sep 17 00:00:00 2001 From: Milan Steiner Date: Sun, 8 Jun 2025 16:23:51 +0200 Subject: [PATCH] Enhance Dashboard UI with improved animations, styling, and responsiveness - Updated `DashboardStats` component with new animation effects and hover states. - Refactored styles using centralized theme constants for colors, spacing, and typography. - Improved `MainStats` component with motion effects and gradient backgrounds. - Enhanced `WalletBalanceTable` with better styling, animations, and responsive design. - Added glow effects and background animations for a more dynamic user experience. --- packages/core/app/page.tsx | 291 +-- .../AssetInfoModal/AssetInfoModal.tsx | 1680 ++++++++++------- .../ui/src/Dashboard/CryptoCTA/CryptoCTA.tsx | 240 ++- .../ui/src/Dashboard/Dashboard/Overview.tsx | 28 - .../DashboardCharts/DashboardCharts.tsx | 321 ++-- .../DashboardStats/DashboardStats.tsx | 238 ++- .../ui/src/Dashboard/MainStats/MainStats.tsx | 135 +- .../WalletBalanceTable/WalletBalanceTable.tsx | 435 +++-- 8 files changed, 2058 insertions(+), 1310 deletions(-) diff --git a/packages/core/app/page.tsx b/packages/core/app/page.tsx index 996091a0..8f4ccbe6 100644 --- a/packages/core/app/page.tsx +++ b/packages/core/app/page.tsx @@ -575,170 +575,171 @@ export default function Page() { mt: { xs: 2, md: 4 }, }} > - {/* Phoenix-styled Welcome Banner with modern design */} + {/* Modern Welcome Hero Section - Matching Earn/Pools Design */} - {/* Enhanced background decoration */} - - - {/* Gradient overlay for better text readability */} - - - - - - - Welcome to Phoenix! - - - Your comprehensive DeFi hub on Stellar. Trade, earn, and - explore the future of decentralized finance. - - - - - - - - - - - - + + Welcome to Phoenix + + - {/* Main content grid with improved responsive design */} - - {/* Dashboard Stats - Full width */} - - {loadingDashboard ? ( - + Your comprehensive DeFi hub on Stellar. Trade, earn, and explore + the future of decentralized finance with cutting-edge protocols. + + + + + + + + - + + + {/* Main content grid with improved responsive design */} + {/* Main Content Area */} diff --git a/packages/ui/src/Dashboard/AssetInfoModal/AssetInfoModal.tsx b/packages/ui/src/Dashboard/AssetInfoModal/AssetInfoModal.tsx index 48f9bb16..8797b4d5 100644 --- a/packages/ui/src/Dashboard/AssetInfoModal/AssetInfoModal.tsx +++ b/packages/ui/src/Dashboard/AssetInfoModal/AssetInfoModal.tsx @@ -1,4 +1,4 @@ -import React, { useState, useCallback } from "react"; +import React, { useState, useCallback, useEffect } from "react"; import { Box, Typography, @@ -129,10 +129,13 @@ const TabPanel = (props: TabPanelProps) => { width: "100%", height: value === index ? "100%" : 0, overflow: "auto", + flex: value === index ? 1 : 0, + display: value === index ? "flex" : "none", + flexDirection: "column", }} > {value === index && ( - {children} + {children} )} ); @@ -150,6 +153,15 @@ const AssetInfoModal = ({ const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("md")); const [tabValue, setTabValue] = useState(0); + const [error, setError] = useState(null); + + // Reset tab and error when modal opens + useEffect(() => { + if (open) { + setTabValue(0); + setError(null); + } + }, [open]); const handleTabChange = (event: React.SyntheticEvent, newValue: number) => { setTabValue(newValue); @@ -159,6 +171,28 @@ const AssetInfoModal = ({ navigator.clipboard.writeText(text); }, []); + const handleClose = useCallback(() => { + setTabValue(0); + setError(null); + onClose(); + }, [onClose]); + + // Error handling for data validation + useEffect(() => { + if (open && asset) { + try { + // Validate required asset data + if (!asset.tomlInfo) { + setError("Asset information is incomplete"); + return; + } + setError(null); + } catch (err) { + setError("Failed to load asset data"); + } + } + }, [open, asset]); + // Chart data const volumeData = prepareVolumeChartData( (tradingVolume7d as TradingVolume[]) || [] @@ -166,22 +200,29 @@ const AssetInfoModal = ({ const priceData = preparePriceChartData(asset.price7d || []); - // Modal styles using the app's style constants - consistent with CardContainer + // Enhanced modal styles with better glassmorphism and backdrop const style = { position: "absolute" as "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)", - width: { xs: "95%", sm: "90%", md: "80%", lg: "70%" }, - maxWidth: "1000px", - height: { xs: "90vh", md: "80vh", lg: "75vh" }, - background: colors.neutral[900], - border: `1px solid ${colors.neutral[700]}`, + width: { xs: "95vw", sm: "90vw", md: "80vw", lg: "70vw" }, + maxWidth: "1200px", + height: { xs: "90vh", md: "85vh", lg: "80vh" }, + maxHeight: "900px", + minHeight: "600px", + background: + "linear-gradient(135deg, rgba(23, 23, 23, 0.97) 0%, rgba(38, 38, 38, 0.95) 50%, rgba(23, 23, 23, 0.97) 100%)", + backdropFilter: "blur(20px)", + WebkitBackdropFilter: "blur(20px)", + border: `1px solid rgba(115, 115, 115, 0.2)`, borderRadius: borderRadius.xl, - boxShadow: shadows.card, + boxShadow: + "0 32px 64px -12px rgba(0, 0, 0, 0.8), 0 20px 32px -8px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.1)", display: "flex", flexDirection: "column" as "column", overflow: "hidden", + outline: "none", }; // Chart height constant to ensure consistency - reduced for better space utilization @@ -253,211 +294,312 @@ const AssetInfoModal = ({ return ( - - - {loading ? ( - - - - Loading asset data... - - - ) : ( - <> - {/* Header */} - + + {loading ? ( + - {asset.tomlInfo.image && ( - + - )} - + + - {asset.tomlInfo.code} - {asset.domain && ( - - - - {asset.domain} - - - - )} + Loading asset data... - - {userBalance > 0 && ( + + + + ) : error ? ( + + + + ⚠️ + + + Unable to Load Asset + + + {error} + + + + ) : ( + <> + {/* Enhanced Header with premium styling */} + + + + - - Balance: {formatNumber(userBalance)}{" "} - {asset.tomlInfo.code} + {asset.tomlInfo?.orgName || + asset.tomlInfo?.code || + "Unknown Asset"} - )} + + {asset.tomlInfo?.code || "N/A"} • Asset Information + + - - - - - + + + + + + - {/* Content Area */} - - {/* Tabs */} + {/* Enhanced Tabs with gradient indicators */} @@ -467,80 +609,87 @@ const AssetInfoModal = ({ - {/* Loading State or Tab Content */} - {loading ? ( - - - - Loading asset data... - - - ) : ( - - {/* Tab content with scrollable area */} - {/* Overview Tab */} + }, + }} + > + {/* Tab content with scrollable area */} + {/* Overview Tab */} - - - {/* Quick Stats Row */} - - - + + + {/* Quick Stats Row */} + + + + - + + - - + + - - Payments - - - {formatNumber(asset.payments)} - - - - - - + - - Trustlines - - - {asset.trustlines[2]} /{" "} - {asset.trustlines[0]} - - - funded / total - - - + {formatNumber(asset.payments)} + + + - - - - Created - - - {new Date( - asset.created * 1000 - ).toLocaleDateString()} - - - - - - - {/* Issuer Information */} - - + + Trustlines + + - Issuer Information + {asset.trustlines[2]} / {asset.trustlines[0]} - stellar.expert - + funded / total + + + + Created + - {asset.tomlInfo.issuer} + {new Date( + asset.created * 1000 + ).toLocaleDateString()} - - - handleCopyToClipboard( - asset.tomlInfo.issuer - ) - } - sx={{ - color: colors.neutral[400], - "&:hover": { - color: colors.primary.main, - background: `${colors.primary.main}20`, - }, - transition: "all 0.2s ease-in-out", - }} - > - - - - - - - + - - {/* Charts Tab */} - - - {/* Price Chart */} - + {/* Issuer Information */} + + - + Issuer Information + + - + + + + + + {asset.tomlInfo.issuer} + + + + handleCopyToClipboard(asset.tomlInfo.issuer) + } sx={{ - color: colors.neutral[50], - fontSize: typography.fontSize.lg, - fontWeight: typography.fontWeights.medium, - fontFamily: typography.fontFamily, + color: colors.neutral[400], + "&:hover": { + color: colors.primary.main, + background: `${colors.primary.main}20`, + }, + transition: "all 0.2s ease-in-out", }} > - Price (USDC) - 7 Days - - + + - - 7D - - + + + + + + + + + + {/* Charts Tab */} + + + {/* Price Chart */} + + + + + Price (USDC) - 7 Days + + + + 7D + + - {priceData.length > 0 ? ( - - 0 ? ( + + + - + + + + + + - - - - - - - - - } - cursor={{ - stroke: colors.neutral[600], - strokeDasharray: "3 3", - }} - /> - - - - - ) : ( + axisLine={{ + stroke: colors.neutral[700], + }} + tickLine={{ + stroke: colors.neutral[700], + }} + /> + + } + cursor={{ + stroke: colors.neutral[600], + strokeDasharray: "3 3", + }} + /> + + + + + ) : ( + + 📈 + + No price data available - )} - - + + )} + + - {/* Volume Chart */} - + {/* Volume Chart */} + + + + Volume - 7 Days + - Volume - 7 Days + Total:{" "} + {formatNumber( + calculateTotalVolume( + tradingVolume7d as TradingVolume[] + ) + )}{" "} + USDC - - - Total:{" "} - {formatNumber( - calculateTotalVolume( - tradingVolume7d as TradingVolume[] - ) - )}{" "} - USDC - - + - {volumeData.length > 0 ? ( - - 0 ? ( + + + - + + + + + + - - - - - - - - - } - cursor={{ - fill: colors.neutral[800], - opacity: 0.3, - }} - /> - - - - - ) : ( + axisLine={{ + stroke: colors.neutral[700], + }} + tickLine={{ + stroke: colors.neutral[700], + }} + /> + + } + cursor={{ + fill: colors.neutral[800], + opacity: 0.3, + }} + /> + + + + + ) : ( + + 📊 + + No volume data available - )} - - + + )} + - + + - {/* Pools Tab */} - - {pools.length > 0 ? ( - - {pools.map((pool, index) => ( + {/* Pools Tab */} + + {pools.length > 0 ? ( + + {pools.map((pool, index) => ( + {}} /> - ))} - - ) : ( + + ))} + + ) : ( + - - - 💧 - - + + 💧 + + + @@ -1195,24 +1426,45 @@ const AssetInfoModal = ({ sx={{ color: colors.neutral[400], fontSize: typography.fontSize.sm, - maxWidth: 300, - lineHeight: 1.5, + maxWidth: 320, + lineHeight: 1.6, + mb: spacing.md, }} > No liquidity pools are currently available for this asset. Check back later or explore other - assets. + assets to find trading opportunities. + + + 💡 Tip: Pool availability depends on market + demand + + - )} - - - )} - - - )} - - + + )} + + + + )} + + + )} ); diff --git a/packages/ui/src/Dashboard/CryptoCTA/CryptoCTA.tsx b/packages/ui/src/Dashboard/CryptoCTA/CryptoCTA.tsx index 97235ddc..a9de9306 100644 --- a/packages/ui/src/Dashboard/CryptoCTA/CryptoCTA.tsx +++ b/packages/ui/src/Dashboard/CryptoCTA/CryptoCTA.tsx @@ -1,70 +1,212 @@ import { Box, Typography } from "@mui/material"; +import { motion } from "framer-motion"; import { Button } from "../../Button/Button"; import React from "react"; import { CryptoCTAProps } from "@phoenix-protocol/types"; +import { + colors, + typography, + spacing, + borderRadius, +} from "../../Theme/styleConstants"; const CryptoCTA = ({ onClick }: CryptoCTAProps) => { return ( - - - - Need More - - - Crypto? - - + + - You can easily deposit now! - - + + + + + + + Need More + + + + + + Crypto? + + + + + + You can easily deposit now! + + + + + + + - + ); }; diff --git a/packages/ui/src/Dashboard/Dashboard/Overview.tsx b/packages/ui/src/Dashboard/Dashboard/Overview.tsx index cc142f31..5ea53175 100644 --- a/packages/ui/src/Dashboard/Dashboard/Overview.tsx +++ b/packages/ui/src/Dashboard/Dashboard/Overview.tsx @@ -8,25 +8,6 @@ import WalletBalanceTable from "../WalletBalanceTable/WalletBalanceTable"; import React from "react"; import MailIcon from "@mui/icons-material/Mail"; import { AppBar } from "../../AppBar/AppBar"; -import DashBoardStats from "../DashboardStats/DashboardStats"; - -const stellarGainerAsset = { - name: "Stellar", - symbol: "XLM", - price: "$3.00", - change: 22.5, - icon: "/cryptoIcons/xlm.svg", - volume: "$100,000", -}; - -const usdcLoserAsset = { - name: "USDC", - symbol: "USDC", - price: "$1", - change: -0.8, - icon: "/cryptoIcons/usdc.svg", - volume: "$100,000", -}; const args = { mainstatsArgs: { @@ -91,12 +72,6 @@ const args = { connectWallet: () => {}, disconnectWallet: () => {}, }, - dashboardStatsArgs: { - gainer: stellarGainerAsset, - loser: usdcLoserAsset, - availableAssets: "$100,000", - lockedAssets: "$100,000", - }, }; export default function Overview() { @@ -141,9 +116,6 @@ export default function Overview() { spacing={largerThenMd ? 3 : 1} > - - - diff --git a/packages/ui/src/Dashboard/DashboardCharts/DashboardCharts.tsx b/packages/ui/src/Dashboard/DashboardCharts/DashboardCharts.tsx index 1ad77ec4..31861e68 100644 --- a/packages/ui/src/Dashboard/DashboardCharts/DashboardCharts.tsx +++ b/packages/ui/src/Dashboard/DashboardCharts/DashboardCharts.tsx @@ -7,6 +7,13 @@ import { DashboardData as Data, } from "@phoenix-protocol/types"; import { ArrowUpward } from "@mui/icons-material"; +import { + borderRadius, + colors, + spacing, + typography, + cardStyles, +} from "../../Theme/styleConstants"; /** * GlowingChart @@ -25,8 +32,13 @@ const GlowingChart = ({ }) => ( @@ -34,45 +46,60 @@ const GlowingChart = ({ ) : ( - + - {/* Filter for strong neon glowing effect */} - - - - - - - - - + {/* Enhanced gradient with better visibility */} + + + + + dataMin * 0.9, "dataMax"]} + domain={[ + (dataMin: number) => dataMin * 0.9, + (dataMax: number) => dataMax * 1.1, + ]} /> entry[1]} - stroke="#F97316" - strokeWidth={2} + stroke={colors.primary.main} + strokeWidth={2} // Slightly thinner line for compact display + fill="url(#chartGradient)" isAnimationActive={true} - fill="none" - filter="url(#neonGlow)" + dot={false} + activeDot={{ + r: 4, // Smaller active dot + stroke: colors.primary.main, + strokeWidth: 2, + fill: colors.primary.main, + }} /> @@ -108,167 +135,175 @@ const DashboardPriceCharts = ({ return 0; }, [data]); - // Force a reflow after animation to fix overflow issue + // Initialize animation and ensure proper chart rendering useEffect(() => { + const startAnimation = async () => { + await controls.start({ opacity: 1, y: 0 }); + + // Force chart visibility after animation + setTimeout(() => { + if (chartRef.current) { + const elements = chartRef.current.querySelectorAll( + ".recharts-wrapper, .recharts-surface" + ); + elements.forEach((element: any) => { + if (element?.style) { + element.style.overflow = "hidden"; // Prevent overflow on mobile + } + }); + + // Trigger a resize to ensure chart renders properly + window.dispatchEvent(new Event("resize")); + } + }, 150); + }; + if (!isLoading) { - controls.start({ opacity: 1, y: 0 }).then(() => { - setTimeout(() => { - if (chartRef.current) { - const elements = chartRef.current.querySelectorAll( - ".recharts-wrapper, .recharts-surface" - ); - elements.forEach((element) => { - element.style.overflow = "visible"; - }); - window.dispatchEvent(new Event("resize")); - } - }, 100); - }); + startAnimation(); } }, [isLoading, controls]); return ( + {" "} + {/* Header Section - Compact */} {isLoading ? ( - - ) : ( - - {""} - - )} - - {isLoading ? ( - <> + + + - - ) : ( - <> + + + ) : ( + + + + - {assetName == "XLM" ? "Stellar" : "Phoenix"} + {assetName === "XLM" ? "Stellar" : "Phoenix"} {assetName} - - )} - - + + + )} + + {/* Price and Change */} + {isLoading ? ( ) : ( <> ${" "} @@ -281,13 +316,26 @@ const DashboardPriceCharts = ({ display: "flex", alignItems: "center", gap: "4px", - ml: "8px", - color: differencePercent >= 0 ? "#66BB6A" : "#E57373", + padding: "4px 8px", + borderRadius: borderRadius.sm, + background: + differencePercent >= 0 + ? `linear-gradient(135deg, rgba(102, 187, 106, 0.15) 0%, rgba(102, 187, 106, 0.08) 100%)` + : `linear-gradient(135deg, rgba(229, 115, 115, 0.15) 0%, rgba(229, 115, 115, 0.08) 100%)`, + border: `1px solid ${ + differencePercent >= 0 + ? "rgba(102, 187, 106, 0.3)" + : "rgba(229, 115, 115, 0.3)" + }`, + color: + differencePercent >= 0 + ? colors.success.main + : colors.error.main, }} > = 0 ? "rotate(0deg)" @@ -296,8 +344,8 @@ const DashboardPriceCharts = ({ /> {differencePercent.toFixed(2)}% @@ -308,12 +356,15 @@ const DashboardPriceCharts = ({ - {/* Chart Section on the Right */} + {/* Chart Section - Compact */} diff --git a/packages/ui/src/Dashboard/DashboardStats/DashboardStats.tsx b/packages/ui/src/Dashboard/DashboardStats/DashboardStats.tsx index 9cae10e4..15345e46 100644 --- a/packages/ui/src/Dashboard/DashboardStats/DashboardStats.tsx +++ b/packages/ui/src/Dashboard/DashboardStats/DashboardStats.tsx @@ -13,6 +13,13 @@ import { GainerOrLooserAsset, } from "@phoenix-protocol/types"; import { ArrowUpward } from "@mui/icons-material"; +import { + borderRadius, + colors, + spacing, + typography, + cardStyles, +} from "../../Theme/styleConstants"; /** * GainerAndLooser @@ -38,37 +45,52 @@ const GainerAndLooser = ({ return ( @@ -79,16 +101,16 @@ const GainerAndLooser = ({ width={isMobile ? 80 : 100} height={isMobile ? 20 : 24} sx={{ - bgcolor: "var(--neutral-700, #404040)", - borderRadius: "8px", + bgcolor: colors.neutral[700], + borderRadius: borderRadius.sm, }} /> - + @@ -118,6 +140,7 @@ const GainerAndLooser = ({ justifyContent: "space-between", width: "100%", gap: 2, + mt: 2, }} > ) : ( <> - {/* Background Asset Icon */} + {/* Background Asset Icon with Glassmorphism Effect */} + {/* Glow Effect */} + + {/* Title */} {title} @@ -180,36 +227,49 @@ const GainerAndLooser = ({ alignItems: "center", gap: { xs: 1.5, sm: 2 }, width: "100%", + mb: 2, + position: "relative", + zIndex: 2, }} > - - + > + + + @@ -217,11 +277,15 @@ const GainerAndLooser = ({ {asset?.symbol} @@ -237,14 +301,19 @@ const GainerAndLooser = ({ justifyContent: "space-between", width: "100%", gap: 2, + position: "relative", + zIndex: 2, }} > @@ -255,14 +324,22 @@ const GainerAndLooser = ({ display: "flex", alignItems: "center", gap: { xs: "4px", sm: "6px" }, - padding: { xs: "4px 6px", sm: "6px 8px" }, - borderRadius: "8px", - backgroundColor: + padding: { xs: "6px 8px", sm: "8px 12px" }, + borderRadius: borderRadius.md, + background: + asset?.change && asset?.change > 0 + ? `linear-gradient(135deg, rgba(102, 187, 106, 0.15) 0%, rgba(102, 187, 106, 0.08) 100%)` + : `linear-gradient(135deg, rgba(229, 115, 115, 0.15) 0%, rgba(229, 115, 115, 0.08) 100%)`, + border: `1px solid ${ asset?.change && asset?.change > 0 - ? "rgba(102, 187, 106, 0.1)" - : "rgba(229, 115, 115, 0.1)", + ? "rgba(102, 187, 106, 0.3)" + : "rgba(229, 115, 115, 0.3)" + }`, color: - asset?.change && asset?.change > 0 ? "#66BB6A" : "#E57373", + asset?.change && asset?.change > 0 + ? colors.success.main + : colors.error.main, + backdropFilter: "blur(10px)", }} > diff --git a/packages/ui/src/Dashboard/MainStats/MainStats.tsx b/packages/ui/src/Dashboard/MainStats/MainStats.tsx index 19e419b1..8d811d3e 100644 --- a/packages/ui/src/Dashboard/MainStats/MainStats.tsx +++ b/packages/ui/src/Dashboard/MainStats/MainStats.tsx @@ -1,6 +1,14 @@ import { Box, Grid, Typography, useMediaQuery, useTheme } from "@mui/material"; import React from "react"; +import { motion } from "framer-motion"; import { MainStatsProps, TileProps } from "@phoenix-protocol/types"; +import { + colors, + spacing, + borderRadius, + typography, + cardStyles, +} from "../../Theme/styleConstants"; const Tile = ({ title, value, link, isMobile }: TileProps) => { const openInNewTab = () => { @@ -10,44 +18,111 @@ const Tile = ({ title, value, link, isMobile }: TileProps) => { }; return ( - - + + {/* Animated background glow */} + + + + + {title} + + - {title} + {value} - - {value} - - + ); }; diff --git a/packages/ui/src/Dashboard/WalletBalanceTable/WalletBalanceTable.tsx b/packages/ui/src/Dashboard/WalletBalanceTable/WalletBalanceTable.tsx index 2b50805f..13ac28b8 100644 --- a/packages/ui/src/Dashboard/WalletBalanceTable/WalletBalanceTable.tsx +++ b/packages/ui/src/Dashboard/WalletBalanceTable/WalletBalanceTable.tsx @@ -30,6 +30,13 @@ import { Lock, } from "@mui/icons-material"; import { useMediaQuery } from "@mui/system"; +import { + borderRadius, + colors, + spacing, + typography, + cardStyles, +} from "../../Theme/styleConstants"; /** * Accessibility properties for tabs. @@ -66,8 +73,8 @@ const FilterAndTabPanel = ({ sx={{ display: "flex", flexDirection: "column", - marginBottom: "16px", - gap: isMobile ? 0 : "24px", + marginBottom: spacing.lg, + gap: isMobile ? spacing.sm : spacing.lg, }} > @@ -75,12 +82,15 @@ const FilterAndTabPanel = ({ Assets @@ -168,41 +178,47 @@ const FilterAndTabPanel = ({ {/* Search Bar */} setSearchTerm(e.target.value)} sx={{ flexGrow: 1, minWidth: "180px", height: "40px", - borderRadius: "12px", - background: "var(--neutral-900, #171717)", - lineHeight: "16px", - fontSize: "12px", + borderRadius: borderRadius.md, + background: `linear-gradient(135deg, ${colors.neutral[800]}60 0%, ${colors.neutral[900]}80 100%)`, + backdropFilter: "blur(10px)", + border: `1px solid ${colors.neutral[600]}`, "& .MuiOutlinedInput-root": { height: "40px", - padding: "0 8px", + padding: "0 12px", + borderRadius: borderRadius.md, "& input": { padding: "8px 0", - fontSize: "12px", - color: "var(--neutral-300, #D4D4D4)", + fontSize: typography.fontSize.sm, + color: colors.neutral[50], + fontFamily: typography.fontFamily, + "&::placeholder": { + color: colors.neutral[400], + opacity: 0.8, + }, }, "& fieldset": { borderColor: "transparent", }, "&:hover fieldset": { - borderColor: "var(--primary-500, #F97316)", + borderColor: colors.primary.main, }, "&.Mui-focused fieldset": { - borderColor: "var(--primary-500, #F97316)", + borderColor: colors.primary.main, + boxShadow: `0 0 0 2px ${colors.primary.main}20`, }, }, - "& .MuiInputAdornment-root img": { - marginRight: "8px", - }, - "&::placeholder": { - color: "var(--neutral-400, #A3A3A3)", - opacity: 1, + "& .MuiInputAdornment-root": { + "& img": { + marginRight: spacing.xs, + filter: "opacity(0.7)", + }, }, }} InputProps={{ @@ -227,21 +243,37 @@ const FilterAndTabPanel = ({ value={sort} onChange={(e) => setSort(e.target.value as "highest" | "lowest")} displayEmpty - inputProps={{ "aria-label": "Without label" }} + inputProps={{ "aria-label": "Sort options" }} sx={{ height: "40px", - borderRadius: "12px", - background: "var(--neutral-900, #171717)", - border: "1px solid var(--neutral-700, #404040)", + borderRadius: borderRadius.md, + background: `linear-gradient(135deg, ${colors.neutral[800]}60 0%, ${colors.neutral[900]}80 100%)`, + backdropFilter: "blur(10px)", + border: `1px solid ${colors.neutral[600]}`, padding: "0 12px", - color: "var(--neutral-300, #D4D4D4)", - fontSize: "12px", + color: colors.neutral[50], + fontFamily: typography.fontFamily, + fontSize: typography.fontSize.sm, "& .MuiSelect-select": { - fontSize: "12px", + fontSize: typography.fontSize.sm, lineHeight: "16px", height: "40px", display: "flex", alignItems: "center", + color: colors.neutral[50], + }, + "& .MuiOutlinedInput-notchedOutline": { + borderColor: "transparent", + }, + "&:hover .MuiOutlinedInput-notchedOutline": { + borderColor: colors.primary.main, + }, + "&.Mui-focused .MuiOutlinedInput-notchedOutline": { + borderColor: colors.primary.main, + boxShadow: `0 0 0 2px ${colors.primary.main}20`, + }, + "& .MuiSelect-icon": { + color: colors.neutral[400], }, }} > @@ -280,41 +312,89 @@ const ListItem = ({ return ( onTokenClick(contractId) : undefined} > - + - - {name} - + + + + + {name} + + {/* Additional token info can go here */} + {/* If Name = PHO and has vesting, show a lock button */} {name === "PHO" && hasVesting && ( - Vesting - + )} @@ -371,38 +454,92 @@ const ListItem = ({ {amount} - - ${(usdValue * amount).toFixed(2)} - + + ${(usdValue * amount).toFixed(2)} + + - {!favorites.includes(name) ? ( - setFavorites([...favorites, name])}> - - - ) : ( - - setFavorites(favorites.filter((f) => f !== name)) - } - > - - - )} + + {!favorites.includes(name) ? ( + setFavorites([...favorites, name])} + sx={{ + background: `linear-gradient(135deg, ${colors.neutral[700]}40 0%, ${colors.neutral[800]}60 100%)`, + border: `1px solid ${colors.neutral[600]}`, + borderRadius: borderRadius.md, + width: 36, + height: 36, + "&:hover": { + background: `linear-gradient(135deg, ${colors.primary.main}20 0%, ${colors.primary.main}10 100%)`, + border: `1px solid ${colors.primary.main}40`, + transform: "translateY(-1px)", + }, + }} + > + + + ) : ( + + setFavorites(favorites.filter((f) => f !== name)) + } + sx={{ + background: `linear-gradient(135deg, ${colors.primary.main}30 0%, ${colors.primary.main}20 100%)`, + border: `1px solid ${colors.primary.main}50`, + borderRadius: borderRadius.md, + width: 36, + height: 36, + "&:hover": { + background: `linear-gradient(135deg, ${colors.primary.main}40 0%, ${colors.primary.main}30 100%)`, + transform: "translateY(-1px)", + }, + }} + > + + + )} + @@ -447,65 +584,103 @@ const WalletBalanceTable = ({ }, [tokens, category, searchTerm, sort]); return ( - - - {filteredTokens.length ? ( - filteredTokens.map((token, index) => ( - - )) - ) : ( - - Looks like you haven't acquired any tokens. - - )} + + + {filteredTokens.length ? ( + filteredTokens.map((token, index) => ( + + )) + ) : ( + + Looks like you haven't acquired any tokens. + + )} + - + ); };