diff --git a/packages/ui/.eslintrc.json b/packages/ui/.eslintrc.json index ff2d152f73..0702626e84 100644 --- a/packages/ui/.eslintrc.json +++ b/packages/ui/.eslintrc.json @@ -32,6 +32,8 @@ }, "rules": { "prettier/prettier": ["error", {}, { "usePrettierrc": true }], + "@typescript-eslint/no-unused-vars": "warn", + "unused-imports/no-unused-imports": "warn", "import/order": [ "error", { @@ -83,7 +85,6 @@ ], "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/no-explicit-any": "warn", - "@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/sort-type-constituents": "error", "no-console": ["error", { "allow": ["warn", "error"] }], "react/self-closing-comp": ["error", { "component": true, "html": true }], @@ -91,7 +92,6 @@ "react-hooks/rules-of-hooks": "error", "react/display-name": "off", "react/prop-types": "off", - "unused-imports/no-unused-imports": "error", "unused-imports/no-unused-vars": [ "warn", { diff --git a/packages/ui/app/_components/CustomTooltip.tsx b/packages/ui/app/_components/CustomTooltip.tsx new file mode 100644 index 0000000000..dda934f529 --- /dev/null +++ b/packages/ui/app/_components/CustomTooltip.tsx @@ -0,0 +1,36 @@ +import { Info } from 'lucide-react'; + +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger +} from '@ui/components/ui/tooltip'; + +const CustomTooltip = ({ + content, + color +}: { + content: string; + color?: string; +}) => ( + + + +
+ +
+
+ +

{content}

+
+
+
+); + +export default CustomTooltip; diff --git a/packages/ui/app/_components/Navbar.tsx b/packages/ui/app/_components/Navbar.tsx index 080b927906..26c64c5473 100644 --- a/packages/ui/app/_components/Navbar.tsx +++ b/packages/ui/app/_components/Navbar.tsx @@ -12,7 +12,7 @@ import { http, createConfig, useChainId } from 'wagmi'; import { base, mode } from 'wagmi/chains'; import { coinbaseWallet } from 'wagmi/connectors'; -import { useStore } from 'ui/store/Store'; +import { useStore } from '@ui/store/Store'; import ConnectButton from './ConnectButton'; import DynamicSubNav from './DynamicSubNav'; diff --git a/packages/ui/app/_components/dashboards/CollateralSwapPopup.tsx b/packages/ui/app/_components/dashboards/CollateralSwapPopup.tsx index 8ad9dd1197..dce68e9dc8 100644 --- a/packages/ui/app/_components/dashboards/CollateralSwapPopup.tsx +++ b/packages/ui/app/_components/dashboards/CollateralSwapPopup.tsx @@ -47,7 +47,7 @@ import MaxDeposit from './MaxDeposit'; import SwapTo from './SwapTo'; import { SlippageDropdown } from '../SlippageDropdown'; -import { collateralSwapAbi } from '@ionicprotocol/sdk'; +import { collateralSwapAbi } from '@ionicprotocol/sdk/src'; createConfig({ integrator: 'ionic', diff --git a/packages/ui/app/_components/dashboards/InfoRows.tsx b/packages/ui/app/_components/dashboards/InfoRows.tsx index 44e5297ee5..add1c2cc65 100644 --- a/packages/ui/app/_components/dashboards/InfoRows.tsx +++ b/packages/ui/app/_components/dashboards/InfoRows.tsx @@ -19,9 +19,10 @@ import BorrowPopover from '../markets/BorrowPopover'; import SupplyPopover from '../markets/SupplyPopover'; import { PopupMode } from '../popup/page'; -import type { FlywheelReward } from 'types/dist'; import type { Address } from 'viem'; +import type { FlywheelReward } from '@ionicprotocol/types'; + export enum InfoMode { SUPPLY = 0, BORROW = 1 diff --git a/packages/ui/app/_components/markets/FeaturedMarketTile.tsx b/packages/ui/app/_components/markets/FeaturedMarketTile.tsx index a5b21b6e2d..fc235a14a3 100644 --- a/packages/ui/app/_components/markets/FeaturedMarketTile.tsx +++ b/packages/ui/app/_components/markets/FeaturedMarketTile.tsx @@ -2,8 +2,7 @@ 'use client'; import type { Dispatch, SetStateAction } from 'react'; -import { useStore } from 'ui/store/Store'; - +import { useStore } from '@ui/store/Store'; import { handleSwitchOriginChain } from '@ui/utils/NetworkChecker'; import WrapEthSwaps from './WrapEthSwaps'; diff --git a/packages/ui/app/_components/markets/NetworkSelector.tsx b/packages/ui/app/_components/markets/NetworkSelector.tsx index 6d90803bcd..56a0592ff7 100644 --- a/packages/ui/app/_components/markets/NetworkSelector.tsx +++ b/packages/ui/app/_components/markets/NetworkSelector.tsx @@ -1,99 +1,145 @@ -/* eslint-disable @next/next/no-img-element */ -'use client'; -/* eslint-disable @typescript-eslint/no-explicit-any */ import React from 'react'; -import dynamic from 'next/dynamic'; +import Image from 'next/image'; import Link from 'next/link'; -import { usePathname } from 'next/navigation'; - -import { useStore } from 'ui/store/Store'; +import { usePathname, useSearchParams } from 'next/navigation'; +import { Button } from '@ui/components/ui/button'; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger +} from '@ui/components/ui/tooltip'; import { pools } from '@ui/constants/index'; +import { useStore } from '@ui/store/Store'; + interface INetworkSelector { - chain?: string; dropdownSelectedChain: number; nopool?: boolean; enabledChains?: number[]; upcomingChains?: string[]; } +const NETWORK_ORDER = ['Mode', 'Base', 'Optimism', 'Fraxtal', 'Lisk', 'BoB']; function NetworkSelector({ dropdownSelectedChain, nopool = false, enabledChains, - chain, upcomingChains }: INetworkSelector) { const pathname = usePathname(); + const searchParams = useSearchParams(); const setDropChain = useStore((state) => state.setDropChain); + + const orderedNetworks = NETWORK_ORDER.map((networkName) => + // eslint-disable-next-line @typescript-eslint/no-unused-vars + Object.entries(pools).find(([_, pool]) => pool.name === networkName) + ).filter( + (entry): entry is [string, any] => + entry !== undefined && + (!enabledChains || enabledChains.includes(+entry[0])) + ); + + const getUrlWithParams = (chainId: string) => { + const params = new URLSearchParams(searchParams.toString()); + params.set('chain', chainId); + if (!nopool && !params.has('pool')) { + params.set('pool', '0'); + } + if (nopool && params.has('pool')) { + params.delete('pool'); + } + return `${pathname}?${params.toString()}`; + }; + return ( -
- - checkmark--v1{' '} - {pools[dropdownSelectedChain].name} - - {Object.entries(pools) - .filter(([chainId]) => - enabledChains - ? enabledChains?.includes(+chainId) && - +chainId !== dropdownSelectedChain - : +chainId !== dropdownSelectedChain - ) - .sort((a, b) => { - const sortingOrder = ['Mode', 'Base', 'Optimism', 'Fraxtal', 'Bob']; - const indexA = sortingOrder.indexOf(a[1].name); - const indexB = sortingOrder.indexOf(b[1].name); +
+ {orderedNetworks.map(([chainId, network], idx) => { + const isSelected = +chainId === +dropdownSelectedChain; + + return ( + + + +
+ +
+
+ + {network.name} +

{network.name}

+ Active +
+
+
+ ); + })} - if (indexA === -1 || indexB === -1) { - return 0; // if the network name is not found, don't change the order - } - return indexA - indexB; - }) - .map(([chainId, network], idx: number) => ( - setDropChain(chainId)} - > - checkmark--v1{' '} - {network.name} - - ))} - {!!upcomingChains && - upcomingChains.map((upcomingChain, idx) => ( -
- checkmark--v1{' '} - {upcomingChain} -
-
- ))} + {upcomingChains?.map((upcomingChain, idx) => ( + + + +
+ +
+
+ + {upcomingChain} +

{upcomingChain}

+ Coming Soon +
+
+
+ ))}
); } -export default dynamic(() => Promise.resolve(NetworkSelector), { ssr: false }); +export default NetworkSelector; diff --git a/packages/ui/app/_components/markets/PoolRows.tsx b/packages/ui/app/_components/markets/PoolRows.tsx index 12eb1f7782..f8cc89fc94 100644 --- a/packages/ui/app/_components/markets/PoolRows.tsx +++ b/packages/ui/app/_components/markets/PoolRows.tsx @@ -4,8 +4,6 @@ import { useEffect, useMemo, type Dispatch, type SetStateAction } from 'react'; import Link from 'next/link'; -import { useStore } from 'ui/store/Store'; - import { FLYWHEEL_TYPE_MAP, pools, @@ -15,6 +13,7 @@ import { useMultiIonic } from '@ui/context/MultiIonicContext'; import { useBorrowCapsDataForAsset } from '@ui/hooks/ionic/useBorrowCapsDataForAsset'; import type { LoopMarketData } from '@ui/hooks/useLoopMarkets'; import { useMerklApr } from '@ui/hooks/useMerklApr'; +import { useStore } from '@ui/store/Store'; import type { MarketData } from '@ui/types/TokensDataMap'; import { handleSwitchOriginChain } from '@ui/utils/NetworkChecker'; diff --git a/packages/ui/app/_components/xION/Quote.tsx b/packages/ui/app/_components/xION/Quote.tsx index f85a108720..a2292d90c1 100644 --- a/packages/ui/app/_components/xION/Quote.tsx +++ b/packages/ui/app/_components/xION/Quote.tsx @@ -3,12 +3,13 @@ import { useEffect } from 'react'; import { Options } from '@layerzerolabs/lz-v2-utilities'; -import { xErc20LayerZeroAbi } from 'sdk/src'; import { formatEther, type Hex, type Address } from 'viem'; import { useReadContract } from 'wagmi'; import { BridgingContractAddress, getToken } from '@ui/utils/getStakingTokens'; +import { xErc20LayerZeroAbi } from '@ionicprotocol/sdk'; + export const lzOptions = Options.newOptions() .addExecutorLzReceiveOption(100_000, 0) .toHex(); diff --git a/packages/ui/app/dashboard/page.tsx b/packages/ui/app/dashboard/page.tsx index c2647c02d1..a7038e6222 100644 --- a/packages/ui/app/dashboard/page.tsx +++ b/packages/ui/app/dashboard/page.tsx @@ -513,10 +513,7 @@ export default function Dashboard() { pool={pool || '0'} setOpen={setOpen} /> */} - +
{/*
diff --git a/packages/ui/app/globals.css b/packages/ui/app/globals.css index 913982ffc0..781608232e 100644 --- a/packages/ui/app/globals.css +++ b/packages/ui/app/globals.css @@ -29,9 +29,11 @@ 0% { transform: scale(1); } + 50% { transform: scale(1.05); } + 100% { transform: scale(1); } @@ -41,55 +43,68 @@ .grid-cols-21 { grid-template-columns: repeat(21, minmax(0, 1fr)); } + .grid-cols-19 { grid-template-columns: repeat(19, minmax(0, 1fr)); } + .grid-cols-20 { grid-template-columns: repeat(20, minmax(0, 1fr)); } + .grid-cols-18 { grid-template-columns: repeat(18, minmax(0, 1fr)); } + .grid-cols-15 { grid-template-columns: repeat(15, minmax(0, 1fr)); } + .grid-cols-13 { grid-template-columns: repeat(13, minmax(0, 1fr)); } + .col-span-15 { grid-column: span 15 / span 15; } + input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-outer-spin-button { -webkit-appearance: none; appearance: none; } - + .amount-field { color: #fff; } + .amount-field::-webkit-input-placeholder { /* WebKit, Blink, Edge */ color: rgb(255 255 255 / 0.5); } + .amount-field:-moz-placeholder { /* Mozilla Firefox 4 to 18 */ color: rgb(255 255 255 / 0.5); opacity: 1; } + .amount-field::-moz-placeholder { /* Mozilla Firefox 19+ */ color: rgb(255 255 255 / 0.5); opacity: 1; } + .amount-field:-ms-input-placeholder { /* Internet Explorer 10-11 */ color: rgb(255 255 255 / 0.5); } + .amount-field::-ms-input-placeholder { /* Microsoft Edge */ color: rgb(255 255 255 / 0.5); } + .amount-field::placeholder { /* Most modern browsers support this now. */ color: rgb(255 255 255 / 0.5); @@ -98,12 +113,20 @@ .expand { animation: expand 2s linear infinite; } + .pause { animation-play-state: paused; /* animation-duration: 40s; */ } + + .react-calendar__tile--now:enabled:hover, + .react-calendar__tile--now:enabled:focus { + @apply bg-[#ffffa9]; + } } + + .bg-pink { background: #ff007f; } @@ -168,16 +191,19 @@ .btn-green { @apply font-bold rounded-md px-3 py-1 text-center transition-colors bg-accent text-darkone; } + .btn-green[disabled] { @apply bg-stone-500; } .popover-container { - @apply relative; + @apply relative; } + .popover-container .popover { transform-origin: 50% 0; } + .popover-container:hover .popover { @apply opacity-100 visible; } @@ -209,11 +235,13 @@ .nav-btn.nav-opened { background: transparent; } + .nav-btn.nav-opened:before { bottom: 0; margin: 0; transform: rotate(45deg); } + .nav-btn.nav-opened:after { top: 0; margin: 0; @@ -224,6 +252,7 @@ bottom: 100%; margin-bottom: 3px; } + .nav-btn:after { top: 100%; margin-top: 3px; @@ -270,6 +299,7 @@ vertical-align: middle; background: #3bff89ff; } + .success-icon:before { width: 6px; height: 2px; @@ -278,6 +308,7 @@ transform-origin: 0 0; transform: rotate(45deg); } + .success-icon:after { width: 12px; height: 2px; @@ -304,9 +335,11 @@ vertical-align: middle; background: #df1515; } + .error-icon:before { transform: rotate(45deg); } + .error-icon:after { transform: rotate(-45deg); } @@ -336,12 +369,15 @@ transition: background 0.15s; cursor: pointer; } + .toggle.is-on { background: #3bff89ff; } + .toggle.is-on:before { transform: translateX(20px); } + .toggle:before { content: ''; display: block; @@ -364,6 +400,7 @@ .animate-fade-in { opacity: 0; } + .animate-fade-in.animated { opacity: 1; } @@ -372,18 +409,17 @@ transform: scale(0.8); opacity: 0; } + .animate-pop-in.animated { transform: scale(1); opacity: 1; } .bg-health-ratio-gradient { - background: linear-gradient( - 90deg, - #ff3864 8.12%, - #f1f996 60.25%, - #39ff88 98.45% - ); + background: linear-gradient(90deg, + #ff3864 8.12%, + #f1f996 60.25%, + #39ff88 98.45%); } .shadow-health-ratio-handle { @@ -406,12 +442,69 @@ @apply w-[1px] bg-white/30 mx-auto my-1 self-stretch; } -body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 240 10% 3.9%; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + --radius: 0.5rem; + } + + .dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 240 4.9% 83.9%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + } } + +@layer base { + * { + @apply border-border; + } + + body { + @apply bg-background text-foreground; + } +} \ No newline at end of file diff --git a/packages/ui/app/layout.tsx b/packages/ui/app/layout.tsx index 894ea7d29b..a336db2d32 100644 --- a/packages/ui/app/layout.tsx +++ b/packages/ui/app/layout.tsx @@ -269,6 +269,15 @@ export default function RootLayout({ Dune +
  • + + ID + +
  • - - - - - - - - - - - - - - - - - - + logo
  • diff --git a/packages/ui/app/market/details/[asset]/page.tsx b/packages/ui/app/market/details/[asset]/page.tsx index d746875f03..3676d5bf19 100644 --- a/packages/ui/app/market/details/[asset]/page.tsx +++ b/packages/ui/app/market/details/[asset]/page.tsx @@ -20,7 +20,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import { Doughnut, Line } from 'react-chartjs-2'; import { mode } from 'viem/chains'; import { useBalance, useAccount } from 'wagmi'; -// import { useGetMaxBorrow } from 'ui/app/util/utils'; +// import { useGetMaxBorrow } from '@ui/app/util/utils'; //-------------------Interfaces------------ interface IProp { params: { asset: string }; @@ -59,10 +59,10 @@ import { // ]; // const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042']; import { INFO } from '@ui/constants/index'; -import Popup, { PopupMode } from 'ui/app/_components/popup/page'; +import Popup, { PopupMode } from '@ui/app/_components/popup/page'; import { extractAndConvertStringTOValue } from '@ui/utils/stringToValue'; import { handleSwitchOriginChain } from '@ui/utils/NetworkChecker'; -import Swap from 'ui/app/_components/popup/Swap'; +import Swap from '@ui/app/_components/popup/Swap'; import { MarketData, PoolData } from '@ui/types/TokensDataMap'; import { useFusePoolData } from '@ui/hooks/useFusePoolData'; import { useLoopMarkets } from '@ui/hooks/useLoopMarkets'; @@ -71,7 +71,7 @@ import { Address, formatEther, formatUnits } from 'viem'; import { useBorrowCapsDataForAsset } from '@ui/hooks/fuse/useBorrowCapsDataForAsset'; import { useUsdPrice } from '@ui/hooks/useAllUsdPrices'; import { useSupplyCapsDataForAsset } from '@ui/hooks/fuse/useSupplyCapsDataForPool'; -import BorrowAmount from 'ui/app/_components/markets/BorrowAmount'; +import BorrowAmount from '@ui/app/_components/markets/BorrowAmount'; // import { useBorrowAPYs } from '@ui/hooks/useBorrowAPYs'; // import { useSupplyAPYs } from '@ui/hooks/useSupplyAPYs'; diff --git a/packages/ui/app/market/page.tsx b/packages/ui/app/market/page.tsx index d8020c5e73..38d26d3168 100644 --- a/packages/ui/app/market/page.tsx +++ b/packages/ui/app/market/page.tsx @@ -141,10 +141,20 @@ export default function Market() { {/* //............................................ */} -
    +
    import('../_components/xION/TxPopup'), { ssr: false }); diff --git a/packages/ui/components.json b/packages/ui/components.json new file mode 100644 index 0000000000..3cce526aeb --- /dev/null +++ b/packages/ui/components.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "app/globals.css", + "baseColor": "slate", + "cssVariables": true + }, + "aliases": { + "components": "@ui/components", + "utils": "@ui/lib/utils" + } +} \ No newline at end of file diff --git a/packages/ui/components/ui/button.tsx b/packages/ui/components/ui/button.tsx new file mode 100644 index 0000000000..7b59cd0ccb --- /dev/null +++ b/packages/ui/components/ui/button.tsx @@ -0,0 +1,57 @@ +import * as React from 'react'; + +import { Slot } from '@radix-ui/react-slot'; +import { cva, type VariantProps } from 'class-variance-authority'; + +import { cn } from '@ui/lib/utils'; + +const buttonVariants = cva( + 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-xl text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', + { + variants: { + variant: { + default: 'bg-primary text-primary-foreground hover:bg-primary/90', + destructive: + 'bg-destructive text-destructive-foreground hover:bg-destructive/90', + outline: + 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', + secondary: + 'bg-secondary text-secondary-foreground hover:bg-secondary/80', + ghost: 'hover:bg-accent hover:text-accent-foreground', + link: 'text-primary underline-offset-4 hover:underline' + }, + size: { + default: 'h-10 px-4 py-2', + sm: 'h-9 rounded-xl px-3', + lg: 'h-11 rounded-xl px-8', + icon: 'h-10 w-10' + } + }, + defaultVariants: { + variant: 'default', + size: 'default' + } + } +); + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : 'button'; + return ( + + ); + } +); +Button.displayName = 'Button'; + +export { Button, buttonVariants }; diff --git a/packages/ui/components/ui/tooltip.tsx b/packages/ui/components/ui/tooltip.tsx new file mode 100644 index 0000000000..c57c81fbb9 --- /dev/null +++ b/packages/ui/components/ui/tooltip.tsx @@ -0,0 +1,31 @@ +'use client'; + +import * as React from 'react'; + +import * as TooltipPrimitive from '@radix-ui/react-tooltip'; + +import { cn } from '@ui/lib/utils'; + +const TooltipProvider = TooltipPrimitive.Provider; + +const Tooltip = TooltipPrimitive.Root; + +const TooltipTrigger = TooltipPrimitive.Trigger; + +const TooltipContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + +)); +TooltipContent.displayName = TooltipPrimitive.Content.displayName; + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; diff --git a/packages/ui/hooks/leverage/usePositions.ts b/packages/ui/hooks/leverage/usePositions.ts index 9ebbcf24c9..fc1ef6fb3c 100644 --- a/packages/ui/hooks/leverage/usePositions.ts +++ b/packages/ui/hooks/leverage/usePositions.ts @@ -2,7 +2,7 @@ import { useQuery } from '@tanstack/react-query'; import { useMultiIonic } from '@ui/context/MultiIonicContext'; -import type { NewPosition, OpenPosition } from 'types/dist'; +import type { NewPosition, OpenPosition } from '@ionicprotocol/types'; export const usePositionsQuery = (chain: number) => { const { address, getSdk } = useMultiIonic(); diff --git a/packages/ui/hooks/useSugarAPR.ts b/packages/ui/hooks/useSugarAPR.ts index 0f9b938893..f4e999f740 100644 --- a/packages/ui/hooks/useSugarAPR.ts +++ b/packages/ui/hooks/useSugarAPR.ts @@ -2,7 +2,7 @@ import { formatEther } from 'viem'; import { mode } from 'viem/chains'; import { useReadContract } from 'wagmi'; -import { lpSugarAbi } from 'ui/app/stake/abi/lpSugar'; +import { lpSugarAbi } from '@ui/app/stake/abi/lpSugar'; import { useAllUsdPrices } from './useAllUsdPrices'; import { useIonPrice, useTokenPrice } from './useDexScreenerPrices'; diff --git a/packages/ui/lib/utils.ts b/packages/ui/lib/utils.ts new file mode 100644 index 0000000000..2819a830d2 --- /dev/null +++ b/packages/ui/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/packages/ui/package.json b/packages/ui/package.json index 5a40476f2d..bdd184acae 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -16,6 +16,8 @@ "@lifi/sdk": "^3.3.1", "@lifi/widget": "^3.8.2", "@netlify/plugin-nextjs": "^5.8.1", + "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-tooltip": "^1.1.3", "@reown/appkit": "^1.2.0", "@reown/appkit-adapter-wagmi": "^1.2.0", "@sentry/nextjs": "^8.35.0", @@ -23,6 +25,9 @@ "@tanstack/react-query": "^5.59.16", "@wagmi/connectors": "^5.3.3", "chart.js": "^4.4.3", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "lucide-react": "^0.454.0", "mathjs": "^13.2.0", "millify": "^6.1.0", "next": "^14.2.5", @@ -34,7 +39,9 @@ "react-dom": "^18.3.1", "react-hot-toast": "^2.4.1", "react-loader-spinner": "^6.1.6", + "tailwind-merge": "^2.5.4", "tailwind-scrollbar-hide": "^1.1.7", + "tailwindcss-animate": "^1.0.7", "viem": "^2.21.34", "wagmi": "^2.12.25", "zustand": "^4.5.4" diff --git a/packages/ui/public/img/logo/CAMP.png b/packages/ui/public/img/logo/CAMP.png new file mode 100644 index 0000000000..19ff7d627f Binary files /dev/null and b/packages/ui/public/img/logo/CAMP.png differ diff --git a/packages/ui/public/img/logo/FX.png b/packages/ui/public/img/logo/FX.png new file mode 100644 index 0000000000..c2e78f0347 Binary files /dev/null and b/packages/ui/public/img/logo/FX.png differ diff --git a/packages/ui/public/img/logo/INK.png b/packages/ui/public/img/logo/INK.png new file mode 100644 index 0000000000..db0d1b01fa Binary files /dev/null and b/packages/ui/public/img/logo/INK.png differ diff --git a/packages/ui/public/img/logo/KROMA.png b/packages/ui/public/img/logo/KROMA.png new file mode 100644 index 0000000000..37f73bc30b Binary files /dev/null and b/packages/ui/public/img/logo/KROMA.png differ diff --git a/packages/ui/public/img/logo/UNICHAIN.png b/packages/ui/public/img/logo/UNICHAIN.png new file mode 100644 index 0000000000..6d3513a65f Binary files /dev/null and b/packages/ui/public/img/logo/UNICHAIN.png differ diff --git a/packages/ui/public/img/logo/WORLDCHAIN.png b/packages/ui/public/img/logo/WORLDCHAIN.png new file mode 100644 index 0000000000..ade796d527 Binary files /dev/null and b/packages/ui/public/img/logo/WORLDCHAIN.png differ diff --git a/packages/ui/public/img/pyth.svg b/packages/ui/public/img/pyth.svg new file mode 100644 index 0000000000..d9ee541f47 --- /dev/null +++ b/packages/ui/public/img/pyth.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/ui/store/Store.ts b/packages/ui/store/Store.ts index 642200dba0..2b44adbca1 100644 --- a/packages/ui/store/Store.ts +++ b/packages/ui/store/Store.ts @@ -1,9 +1,9 @@ // import type { Dispatch, SetStateAction } from 'react'; import { create } from 'zustand'; -import type { BorrowPopoverProps } from 'ui/app/_components/markets/BorrowPopover'; -import type { SupplyPopoverProps } from 'ui/app/_components/markets/SupplyPopover'; -// import type { PopupMode } from 'ui/app/_components/popup/page'; +import type { BorrowPopoverProps } from '@ui/app/_components/markets/BorrowPopover'; +import type { SupplyPopoverProps } from '@ui/app/_components/markets/SupplyPopover'; +// import type { PopupMode } from '@ui/app/_components/popup/page'; interface IFeaturedBorrow extends BorrowPopoverProps { // asset: string; diff --git a/packages/ui/tailwind.config.ts b/packages/ui/tailwind.config.ts index dbf59a162b..04c437131b 100644 --- a/packages/ui/tailwind.config.ts +++ b/packages/ui/tailwind.config.ts @@ -6,8 +6,8 @@ const config: Config = { './components/**/*.{js,ts,jsx,tsx,mdx}', './app/**/*.{js,ts,jsx,tsx,mdx}' ], - darkMode: 'class', - plugins: [require('tailwind-scrollbar-hide')], + darkMode: ['class', 'class'], + plugins: [require('tailwind-scrollbar-hide'), require('tailwindcss-animate')], theme: { extend: { backgroundImage: { @@ -20,7 +20,43 @@ const config: Config = { darkone: '#0a0a0aff', grayUnselect: '#2c2e33ff', graylite: '#34363dff', - grayone: '#212126ff' + grayone: '#212126ff', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' + }, + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + chart: { + '1': 'hsl(var(--chart-1))', + '2': 'hsl(var(--chart-2))', + '3': 'hsl(var(--chart-3))', + '4': 'hsl(var(--chart-4))', + '5': 'hsl(var(--chart-5))' + } }, fontFamily: { inter: ['Inter', 'sans-serif'] @@ -37,6 +73,11 @@ const config: Config = { transform: 'translateX(-100%)' } } + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' } } } diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index fd42cf5308..8447041315 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -18,8 +18,13 @@ { "name": "next" } - ] + ], + "baseUrl": ".", + "paths": { + "@ui/*": ["./*"], + "@/app/_components/*": ["app/_components/*"] + } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "exclude": ["node_modules"] -} +} \ No newline at end of file diff --git a/packages/ui/utils/NetworkChecker.ts b/packages/ui/utils/NetworkChecker.ts index 6a9b1ce4ac..38abcdae0f 100644 --- a/packages/ui/utils/NetworkChecker.ts +++ b/packages/ui/utils/NetworkChecker.ts @@ -1,6 +1,6 @@ import { switchChain } from '@wagmi/core'; -import { wagmiAdapter } from 'ui/app/layout'; +import { wagmiAdapter } from '@ui/app/layout'; export const handleSwitchOriginChain = async ( selectedDropdownChain: number, diff --git a/yarn.lock b/yarn.lock index fa61d08e36..fcbfae20f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2211,6 +2211,8 @@ __metadata: "@lifi/sdk": "npm:^3.3.1" "@lifi/widget": "npm:^3.8.2" "@netlify/plugin-nextjs": "npm:^5.8.1" + "@radix-ui/react-slot": "npm:^1.1.0" + "@radix-ui/react-tooltip": "npm:^1.1.3" "@reown/appkit": "npm:^1.2.0" "@reown/appkit-adapter-wagmi": "npm:^1.2.0" "@sentry/nextjs": "npm:^8.35.0" @@ -2222,6 +2224,8 @@ __metadata: "@wagmi/connectors": "npm:^5.3.3" autoprefixer: "npm:^10.4.19" chart.js: "npm:^4.4.3" + class-variance-authority: "npm:^0.7.0" + clsx: "npm:^2.1.1" eslint: "npm:^8" eslint-config-next: "npm:^14.1.4" eslint-config-prettier: "npm:^9.0.0" @@ -2232,6 +2236,7 @@ __metadata: eslint-plugin-sort-keys: "npm:^2.3.5" eslint-plugin-typescript-sort-keys: "npm:^3.0.0" eslint-plugin-unused-imports: "npm:^3.0.0" + lucide-react: "npm:^0.454.0" mathjs: "npm:^13.2.0" millify: "npm:^6.1.0" next: "npm:^14.2.5" @@ -2244,8 +2249,10 @@ __metadata: react-dom: "npm:^18.3.1" react-hot-toast: "npm:^2.4.1" react-loader-spinner: "npm:^6.1.6" + tailwind-merge: "npm:^2.5.4" tailwind-scrollbar-hide: "npm:^1.1.7" tailwindcss: "npm:^3.4.4" + tailwindcss-animate: "npm:^1.0.7" typescript: "npm:^5.5.3" viem: "npm:^2.21.34" wagmi: "npm:^2.12.25" @@ -5174,6 +5181,19 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-context@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-context@npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/f6469583bf11cc7bff3ea5c95c56b0774a959512adead00dc64b0527cca01b90b476ca39a64edfd7e18e428e17940aa0339116b1ce5b6e8eab513cfd1065d391 + languageName: node + linkType: hard + "@radix-ui/react-dialog@npm:^1.0.5": version: 1.1.1 resolution: "@radix-ui/react-dialog@npm:1.1.1" @@ -5242,6 +5262,29 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-dismissable-layer@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-dismissable-layer@npm:1.1.1" + dependencies: + "@radix-ui/primitive": "npm:1.1.0" + "@radix-ui/react-compose-refs": "npm:1.1.0" + "@radix-ui/react-primitive": "npm:2.0.0" + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + "@radix-ui/react-use-escape-keydown": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/4f2346846f15f3482b8b6cd850448838d01520366deef840d8e80f5a3443aa7f21f86bd5b9a26f2709dcf94f1ec3f2bdfe80d5c37cba504c41e487c7ff8af3de + languageName: node + linkType: hard + "@radix-ui/react-focus-guards@npm:1.1.0": version: 1.1.0 resolution: "@radix-ui/react-focus-guards@npm:1.1.0" @@ -5372,6 +5415,26 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-portal@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-portal@npm:1.1.2" + dependencies: + "@radix-ui/react-primitive": "npm:2.0.0" + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/2f737dc0445f02f512f814ba140227e1a049b3d215d79e22ead412c9befe830292c48a559a8ad1514a474ae8f0c4c43954dfbe294b93a0279d8747d08f7b7924 + languageName: node + linkType: hard + "@radix-ui/react-presence@npm:1.1.0": version: 1.1.0 resolution: "@radix-ui/react-presence@npm:1.1.0" @@ -5392,6 +5455,26 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-presence@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-presence@npm:1.1.1" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.0" + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/1ae074efae47ab52a63239a5936fddb334b2f66ed91e74bfe8b1ae591e5db01fa7e9ddb1412002cc043066d40478ba05187a27eb2684dcd68dea545993f9ee20 + languageName: node + linkType: hard + "@radix-ui/react-primitive@npm:2.0.0": version: 2.0.0 resolution: "@radix-ui/react-primitive@npm:2.0.0" @@ -5504,7 +5587,7 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-slot@npm:1.1.0": +"@radix-ui/react-slot@npm:1.1.0, @radix-ui/react-slot@npm:^1.1.0": version: 1.1.0 resolution: "@radix-ui/react-slot@npm:1.1.0" dependencies: @@ -5575,6 +5658,36 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-tooltip@npm:^1.1.3": + version: 1.1.3 + resolution: "@radix-ui/react-tooltip@npm:1.1.3" + dependencies: + "@radix-ui/primitive": "npm:1.1.0" + "@radix-ui/react-compose-refs": "npm:1.1.0" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-dismissable-layer": "npm:1.1.1" + "@radix-ui/react-id": "npm:1.1.0" + "@radix-ui/react-popper": "npm:1.2.0" + "@radix-ui/react-portal": "npm:1.1.2" + "@radix-ui/react-presence": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.0.0" + "@radix-ui/react-slot": "npm:1.1.0" + "@radix-ui/react-use-controllable-state": "npm:1.1.0" + "@radix-ui/react-visually-hidden": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/6a0eeabee30173b3d885c12c666614d673352037c0018a57e4cf220d4da73b6ebefa8610fe26a99d83fc00672a2b7417d8dc194096dd106865de1326d8cd9166 + languageName: node + linkType: hard + "@radix-ui/react-use-callback-ref@npm:1.1.0": version: 1.1.0 resolution: "@radix-ui/react-use-callback-ref@npm:1.1.0" @@ -10790,6 +10903,15 @@ __metadata: languageName: node linkType: hard +"class-variance-authority@npm:^0.7.0": + version: 0.7.0 + resolution: "class-variance-authority@npm:0.7.0" + dependencies: + clsx: "npm:2.0.0" + checksum: 10/06646e82953e577fb8834100d763f1e5ecb808b8a1fba6244e94b20603865b134ff2296e30432449793baaeb02282cce617afba6981afe18b6846f1f8e9485ca + languageName: node + linkType: hard + "clean-deep@npm:3.4.0": version: 3.4.0 resolution: "clean-deep@npm:3.4.0" @@ -10998,6 +11120,13 @@ __metadata: languageName: node linkType: hard +"clsx@npm:2.0.0": + version: 2.0.0 + resolution: "clsx@npm:2.0.0" + checksum: 10/943766d1b02fee3538c871e56638d87f973fbc2d6291ce221215ea436fdecb9be97ad323f411839c2d52c45640c449b1a53fbfe7e8b3d529b4e263308b630c9a + languageName: node + linkType: hard + "clsx@npm:^1.2.1": version: 1.2.1 resolution: "clsx@npm:1.2.1" @@ -18084,6 +18213,15 @@ __metadata: languageName: node linkType: hard +"lucide-react@npm:^0.454.0": + version: 0.454.0 + resolution: "lucide-react@npm:0.454.0" + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc + checksum: 10/90b40271182e15fefc9cbc6aca4645a49691f73b1887daffb0c9d048f61c89a1c1d7eac1096a37ba627bdce91e8aa49fcf43a5cf0ebd255117ce848d71a56dd1 + languageName: node + linkType: hard + "luxon@npm:^3.2.1": version: 3.5.0 resolution: "luxon@npm:3.5.0" @@ -23916,6 +24054,13 @@ __metadata: languageName: node linkType: hard +"tailwind-merge@npm:^2.5.4": + version: 2.5.4 + resolution: "tailwind-merge@npm:2.5.4" + checksum: 10/2bf6585a30c0ab2e4e8c4bfe0d0a14edbf8e1d88bb8ce68c79f7185e8a7e410893903a98f5819cf8843f1afbe87639e1989af28456cbb0240ddec3468f303727 + languageName: node + linkType: hard + "tailwind-scrollbar-hide@npm:^1.1.7": version: 1.1.7 resolution: "tailwind-scrollbar-hide@npm:1.1.7" @@ -23923,6 +24068,15 @@ __metadata: languageName: node linkType: hard +"tailwindcss-animate@npm:^1.0.7": + version: 1.0.7 + resolution: "tailwindcss-animate@npm:1.0.7" + peerDependencies: + tailwindcss: "*" + checksum: 10/ef176fbb0bf9dca84178b35b6a9615cd756358ea80be9c575456d12ecd7f3c431e9e571915c7df72959dc798a730959e9a4739d59eab55d8cc6db390870ff0d2 + languageName: node + linkType: hard + "tailwindcss@npm:^3.4.4": version: 3.4.10 resolution: "tailwindcss@npm:3.4.10"