diff --git a/app/admin/stats/page.tsx b/app/admin/stats/page.tsx
index aedad56c..55adaef4 100644
--- a/app/admin/stats/page.tsx
+++ b/app/admin/stats/page.tsx
@@ -2,10 +2,16 @@
import { useState, useEffect } from 'react';
import { Button } from '@/components/ui/button';
-import { Dropdown, DropdownTrigger, DropdownMenu, DropdownItem } from '@heroui/react';
import Image from 'next/image';
import ButtonGroup from '@/components/ui/button-group';
import { Spinner } from '@/components/ui/spinner';
+import {
+ DropdownMenu,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuCheckboxItem,
+} from '@/components/ui/dropdown-menu';
import { TokenIcon } from '@/components/shared/token-icon';
import { useMarkets } from '@/contexts/MarketsContext';
import { fetchAllStatistics } from '@/services/statsService';
@@ -179,8 +185,8 @@ export default function StatsPage() {
Platform Statistics
{/* Network selector */}
-
-
+
+
+
+// With icons
+}>Supply
+}>Explorer
+
+// Sections
+
+
+// Multi-select
+
+ Item
+
+
+// Prevent auto-close (for switches)
+ e.preventDefault()}>
+ {/* custom content */}
+
+```
+
+Alignment: `align="start"` | `"center"` | `"end"`
+
## Background, Border
- Use `bg-surface` first layer components
@@ -461,7 +508,6 @@ import { TablePagination } from '@/components/common/TablePagination';
- Jump-to-page search icon (appears when >10 pages)
- Optional entry count display ("Showing X-Y of Z entries")
- Loading states with disabled buttons
-- Rounded-md styling with bg-surface
- Tighter spacing (gap-2) when used in layouts
**Props:**
diff --git a/package.json b/package.json
index 464f1aec..e639077f 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,6 @@
},
"dependencies": {
"@heroicons/react": "^2.2.0",
- "@heroui/accordion": "^2.0.35",
"@heroui/input": "^2.2.2",
"@heroui/react": "^2.4.2",
"@heroui/system": "^2.2.2",
@@ -30,7 +29,7 @@
"@merkl/api": "^1.7.0",
"@morpho-org/blue-sdk": "^5.3.0",
"@radix-ui/react-checkbox": "^1.3.3",
- "@radix-ui/react-dropdown-menu": "^2.0.6",
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-slot": "^1.2.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8f2606ab..071684a1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,9 +11,6 @@ importers:
'@heroicons/react':
specifier: ^2.2.0
version: 2.2.0(react@18.3.1)
- '@heroui/accordion':
- specifier: ^2.0.35
- version: 2.2.21(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.17))(framer-motion@11.18.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@heroui/theme@2.4.20(tailwindcss@4.1.17))(framer-motion@11.18.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@heroui/input':
specifier: ^2.2.2
version: 2.4.25(@heroui/system@2.4.20(@heroui/theme@2.4.20(tailwindcss@4.1.17))(framer-motion@11.18.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@heroui/theme@2.4.20(tailwindcss@4.1.17))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -42,7 +39,7 @@ importers:
specifier: ^1.3.3
version: 1.3.3(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-dropdown-menu':
- specifier: ^2.0.6
+ specifier: ^2.1.16
version: 2.1.16(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-icons':
specifier: ^1.3.0
diff --git a/src/components/layout/header/AccountDropdown.tsx b/src/components/layout/header/AccountDropdown.tsx
index 29ec3d02..3e0854dd 100644
--- a/src/components/layout/header/AccountDropdown.tsx
+++ b/src/components/layout/header/AccountDropdown.tsx
@@ -1,13 +1,13 @@
'use client';
import { useCallback } from 'react';
-import { Dropdown, DropdownTrigger, DropdownMenu, DropdownItem } from '@heroui/react';
import { ExitIcon, ExternalLinkIcon, CopyIcon } from '@radix-ui/react-icons';
import { clsx } from 'clsx';
import { useConnection, useDisconnect } from 'wagmi';
import { useAppKit } from '@reown/appkit/react';
import { Avatar } from '@/components/Avatar/Avatar';
import { AccountIdentity } from '@/components/shared/account-identity';
+import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from '@/components/ui/dropdown-menu';
import { useStyledToast } from '@/hooks/useStyledToast';
import { getExplorerURL } from '@/utils/external';
@@ -36,8 +36,8 @@ export function AccountDropdown() {
if (!address) return null;
return (
-
-
+
+
-
-
-
+
+
-
+
- }
>
Copy Address
-
+
- }
onClick={() => window.open(getExplorerURL(address, chainId ?? 1), '_blank')}
>
View on Explorer
-
+
- }
- className="text-red-500 data-[hover=true]:text-red-500"
+ className="text-red-500 hover:text-red-500 focus:text-red-500"
>
Log out
-
-
-
+
+
+
);
}
diff --git a/src/components/layout/header/Navbar.tsx b/src/components/layout/header/Navbar.tsx
index 5e77c8f5..7a3b182d 100644
--- a/src/components/layout/header/Navbar.tsx
+++ b/src/components/layout/header/Navbar.tsx
@@ -1,7 +1,6 @@
'use client';
import { useEffect, useState } from 'react';
-import { Dropdown, DropdownTrigger, DropdownMenu, DropdownItem } from '@heroui/react';
import { ChevronDownIcon } from '@radix-ui/react-icons';
import { clsx } from 'clsx';
import Image from 'next/image';
@@ -13,6 +12,7 @@ import { FiSettings } from 'react-icons/fi';
import { LuSunMedium } from 'react-icons/lu';
import { RiBookLine, RiDiscordFill, RiGithubFill } from 'react-icons/ri';
import { useConnection } from 'wagmi';
+import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from '@/components/ui/dropdown-menu';
import { EXTERNAL_LINKS } from '@/utils/external';
import logo from '../../imgs/logo.png';
import AccountConnect from './AccountConnect';
@@ -117,12 +117,8 @@ export function Navbar() {
>
)}
-
-
+
+
-
-
+
- }
onClick={() => window.open(EXTERNAL_LINKS.docs, '_blank')}
>
Docs
-
-
+ }
onClick={() => window.open(EXTERNAL_LINKS.discord, '_blank')}
>
Discord
-
-
+ }
onClick={() => window.open(EXTERNAL_LINKS.github, '_blank')}
>
GitHub
-
-
+ : )}
onClick={toggleTheme}
>
{theme === 'dark' ? 'Light Theme' : 'Dark Theme'}
-
-
+ }
onClick={() => router.push('/settings')}
>
Settings
-
-
-
+
+
+
diff --git a/src/components/layout/header/NavbarMobile.tsx b/src/components/layout/header/NavbarMobile.tsx
index 95fb2e31..a0742acd 100644
--- a/src/components/layout/header/NavbarMobile.tsx
+++ b/src/components/layout/header/NavbarMobile.tsx
@@ -1,7 +1,6 @@
'use client';
import { useEffect, useState } from 'react';
-import { Dropdown, DropdownTrigger, DropdownMenu, DropdownItem, DropdownSection } from '@heroui/react';
import { HamburgerMenuIcon } from '@radix-ui/react-icons';
import { clsx } from 'clsx';
import Image from 'next/image';
@@ -13,6 +12,13 @@ import { FiSettings } from 'react-icons/fi';
import { LuSunMedium } from 'react-icons/lu';
import { RiBookLine, RiDiscordFill, RiGithubFill, RiLineChartLine, RiBriefcaseLine, RiGiftLine } from 'react-icons/ri';
import { useConnection } from 'wagmi';
+import {
+ DropdownMenu,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuSeparator,
+} from '@/components/ui/dropdown-menu';
import { EXTERNAL_LINKS } from '@/utils/external';
import logo from '../../imgs/logo.png';
import AccountConnect from './AccountConnect';
@@ -57,13 +63,11 @@ export default function NavbarMobile() {
/>
-
-
+
-
-
+
-
- }
- onClick={() => handleNavigation('/markets')}
- className="py-3"
- >
- Markets
-
- }
- onClick={() => handleNavigation(address ? `/positions/${address}` : '/positions')}
- className="py-3"
- >
- Portfolio
-
- }
- onClick={() => handleNavigation(address ? `/rewards/${address}` : '/rewards')}
- className="py-3"
- >
- Rewards
-
-
-
- }
- onClick={() => handleExternalLink(EXTERNAL_LINKS.docs)}
- >
- Docs
-
- }
- onClick={() => handleExternalLink(EXTERNAL_LINKS.discord)}
- >
- Discord
-
- }
- onClick={() => handleExternalLink(EXTERNAL_LINKS.github)}
- >
- GitHub
-
- : )}
- onClick={toggleTheme}
- >
- {mounted && (theme === 'dark' ? 'Light Theme' : 'Dark Theme')}
-
- }
- onClick={() => handleNavigation('/settings')}
- >
- Settings
-
-
-
-
+ }
+ onClick={() => handleNavigation('/markets')}
+ className="py-3"
+ >
+ Markets
+
+ }
+ onClick={() => handleNavigation(address ? `/positions/${address}` : '/positions')}
+ className="py-3"
+ >
+ Portfolio
+
+ }
+ onClick={() => handleNavigation(address ? `/rewards/${address}` : '/rewards')}
+ className="py-3"
+ >
+ Rewards
+
+
+
+
+ }
+ onClick={() => handleExternalLink(EXTERNAL_LINKS.docs)}
+ >
+ Docs
+
+ }
+ onClick={() => handleExternalLink(EXTERNAL_LINKS.discord)}
+ >
+ Discord
+
+ }
+ onClick={() => handleExternalLink(EXTERNAL_LINKS.github)}
+ >
+ GitHub
+
+ : )}
+ onClick={toggleTheme}
+ >
+ {mounted && (theme === 'dark' ? 'Light Theme' : 'Dark Theme')}
+
+ }
+ onClick={() => handleNavigation('/settings')}
+ >
+ Settings
+
+
+
diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx
new file mode 100644
index 00000000..466432cc
--- /dev/null
+++ b/src/components/ui/dropdown-menu.tsx
@@ -0,0 +1,235 @@
+import * as React from "react"
+import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
+import { FaCheck } from "react-icons/fa6";
+import { GoChevronRight, GoCircle } from "react-icons/go";
+
+import { cn } from "@/utils/components"
+
+// Wrapper to set modal={false} by default to prevent page shifts from scrollbar
+const DropdownMenu = ({ modal = false, ...props }: React.ComponentProps
) => (
+
+)
+
+const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
+
+const DropdownMenuGroup = DropdownMenuPrimitive.Group
+
+const DropdownMenuPortal = DropdownMenuPrimitive.Portal
+
+const DropdownMenuSub = DropdownMenuPrimitive.Sub
+
+const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
+
+const DropdownMenuSubTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, children, ...props }, ref) => (
+
+ {children}
+
+
+))
+DropdownMenuSubTrigger.displayName =
+ DropdownMenuPrimitive.SubTrigger.displayName
+
+const DropdownMenuSubContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DropdownMenuSubContent.displayName =
+ DropdownMenuPrimitive.SubContent.displayName
+
+const DropdownMenuContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, sideOffset = 4, ...props }, ref) => (
+
+
+
+))
+DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
+
+const DropdownMenuItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ startContent?: React.ReactNode
+ endContent?: React.ReactNode
+ }
+>(({ className, inset, startContent, endContent, children, ...props }, ref) => (
+ svg]:size-4 [&>svg]:shrink-0",
+ inset && "pl-8",
+ className
+ )}
+ {...props}
+ >
+ {startContent && {startContent}}
+ {children}
+ {endContent && {endContent}}
+
+))
+DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
+
+const DropdownMenuCheckboxItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ startContent?: React.ReactNode
+ endContent?: React.ReactNode
+ }
+>(({ className, children, checked, startContent, endContent, ...props }, ref) => (
+
+ {!startContent && (
+
+
+
+
+
+ )}
+ {startContent && {startContent}}
+ {children}
+ {endContent && {endContent}}
+
+))
+DropdownMenuCheckboxItem.displayName =
+ DropdownMenuPrimitive.CheckboxItem.displayName
+
+const DropdownMenuRadioItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ startContent?: React.ReactNode
+ endContent?: React.ReactNode
+ }
+>(({ className, children, startContent, endContent, ...props }, ref) => (
+
+ {!startContent && (
+
+
+
+
+
+ )}
+ {startContent && {startContent}}
+ {children}
+ {endContent && {endContent}}
+
+))
+DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
+
+const DropdownMenuLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+
+))
+DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
+
+const DropdownMenuSeparator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
+
+const DropdownMenuShortcut = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => {
+ return (
+
+ )
+}
+DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
+
+export {
+ DropdownMenu,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuCheckboxItem,
+ DropdownMenuRadioItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuShortcut,
+ DropdownMenuGroup,
+ DropdownMenuPortal,
+ DropdownMenuSub,
+ DropdownMenuSubContent,
+ DropdownMenuSubTrigger,
+ DropdownMenuRadioGroup,
+}
diff --git a/src/features/markets/components/market-actions-dropdown.tsx b/src/features/markets/components/market-actions-dropdown.tsx
index b5f1273f..5298b970 100644
--- a/src/features/markets/components/market-actions-dropdown.tsx
+++ b/src/features/markets/components/market-actions-dropdown.tsx
@@ -2,12 +2,12 @@
import type React from 'react';
import { useState } from 'react';
-import { Dropdown, DropdownTrigger, DropdownMenu, DropdownItem } from '@heroui/react';
import { AiOutlineStop } from 'react-icons/ai';
import { GoStarFill, GoStar, GoGraph } from 'react-icons/go';
import { IoEllipsisVertical } from 'react-icons/io5';
import { TbArrowUp } from 'react-icons/tb';
import { Button } from '@/components/ui/button';
+import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from '@/components/ui/dropdown-menu';
import type { Market } from '@/utils/types';
import { BlacklistConfirmationModal } from './blacklist-confirmation-modal';
@@ -64,8 +64,8 @@ export function MarketActionsDropdown({
role="button"
tabIndex={-1}
>
-
-
+
+
-
-
-
+
+ {
setSelectedMarket(market);
setShowSupplyModal(true);
@@ -91,20 +83,18 @@ export function MarketActionsDropdown({
startContent={}
>
Supply
-
+
- {
onMarketClick(market);
}}
startContent={}
>
View Market
-
+
- {
if (isStared) {
unstarMarket(market.uniqueKey);
@@ -115,19 +105,18 @@ export function MarketActionsDropdown({
startContent={isStared ? : }
>
{isStared ? 'Unstar' : 'Star'}
-
+
- }
className={isBlacklisted?.(market.uniqueKey) || !addBlacklistedMarket ? 'opacity-50 cursor-not-allowed' : ''}
- isDisabled={isBlacklisted?.(market.uniqueKey) || !addBlacklistedMarket}
+ disabled={isBlacklisted?.(market.uniqueKey) || !addBlacklistedMarket}
>
{isBlacklisted?.(market.uniqueKey) ? 'Blacklisted' : 'Blacklist'}
-
-
-
+
+
+
-
-
+
+
{periodLabels[earningsPeriod]}
-
- setEarningsPeriod(key as EarningsPeriod)}
- >
+
+
{Object.entries(periodLabels).map(([period, label]) => (
- {label}
+ setEarningsPeriod(period as EarningsPeriod)}
+ >
+ {label}
+
))}
-
-
+
+
-
-
+
+
-
-
-
+
+ e.preventDefault()}
>
Show Empty Positions
@@ -263,10 +261,10 @@ export function PositionsSummaryTable({
}}
/>
-
-
+ e.preventDefault()}
>
Show Collateral Exposure
@@ -281,9 +279,9 @@ export function PositionsSummaryTable({
}}
/>
-
-
-
+
+
+