fix(nav): replace NavigationMenu submenus with DropdownMenu
The Radix NavigationMenu uses a single shared viewport centered under the full nav list. Opening a right-side submenu (Analyzer, Admin) positioned the dropdown panel far to the left, so moving the mouse to reach it crossed other triggers and closed it mid-way. Switch all items-with-children to DropdownMenu, which positions each panel directly under its own trigger. Keeps the same visual style (navigationMenuTriggerStyle, ChevronDown, item layout with icon + description) and active-state highlighting. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
370125d249
commit
2d4a546a8f
1 changed files with 56 additions and 51 deletions
|
|
@ -17,16 +17,21 @@ import {
|
|||
Brain,
|
||||
Search,
|
||||
AlertTriangle,
|
||||
ChevronDown,
|
||||
} from 'lucide-react';
|
||||
import {
|
||||
NavigationMenu,
|
||||
NavigationMenuContent,
|
||||
NavigationMenuItem,
|
||||
NavigationMenuLink,
|
||||
NavigationMenuList,
|
||||
NavigationMenuTrigger,
|
||||
navigationMenuTriggerStyle,
|
||||
} from '@/components/ui/navigation-menu';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ThemeToggle } from '@/components/theme-toggle';
|
||||
import { StatusIndicator } from '@/components/navigation/status-indicator';
|
||||
|
|
@ -242,57 +247,57 @@ export function AppNavigation() {
|
|||
return (
|
||||
<NavigationMenuItem key={item.title}>
|
||||
{item.children ? (
|
||||
<>
|
||||
<NavigationMenuTrigger
|
||||
className={cn(
|
||||
'h-9 px-4 py-2',
|
||||
childActive && cn(activeRule, 'text-foreground'),
|
||||
)}
|
||||
>
|
||||
{item.icon && <item.icon className="w-4 h-4 mr-2" />}
|
||||
{item.title}
|
||||
</NavigationMenuTrigger>
|
||||
<NavigationMenuContent>
|
||||
<ul className="grid gap-1 p-2 min-w-[320px] max-w-[440px]">
|
||||
{item.children.map((child) => {
|
||||
const active = isActive(child.href);
|
||||
return (
|
||||
<li key={child.title}>
|
||||
<NavigationMenuLink asChild>
|
||||
<Link
|
||||
href={child.href || '#'}
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button
|
||||
className={cn(
|
||||
navigationMenuTriggerStyle(),
|
||||
'h-9 px-4 py-2 group',
|
||||
childActive && cn(activeRule, 'text-foreground'),
|
||||
)}
|
||||
>
|
||||
{item.icon && <item.icon className="w-4 h-4 mr-2" />}
|
||||
{item.title}
|
||||
<ChevronDown className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180" aria-hidden="true" />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start" className="p-2 min-w-[320px] max-w-[440px]">
|
||||
{item.children.map((child) => {
|
||||
const active = isActive(child.href);
|
||||
return (
|
||||
<DropdownMenuItem key={child.title} asChild className="p-0 focus:bg-transparent">
|
||||
<Link
|
||||
href={child.href || '#'}
|
||||
className={cn(
|
||||
'flex w-full items-start gap-3 rounded-sm px-3 py-2 text-sm leading-none no-underline outline-none transition-colors cursor-pointer',
|
||||
'hover:bg-accent/40 focus:bg-accent/40',
|
||||
active && 'bg-primary/10 text-primary',
|
||||
)}
|
||||
>
|
||||
{child.icon && (
|
||||
<child.icon
|
||||
className={cn(
|
||||
'flex items-start gap-3 rounded-sm px-3 py-2 leading-none no-underline outline-none transition-colors',
|
||||
'hover:bg-accent/40 focus:bg-accent/40',
|
||||
active && 'bg-primary/10 text-primary',
|
||||
'w-4 h-4 mt-0.5 shrink-0',
|
||||
active ? 'text-primary' : 'text-muted-foreground',
|
||||
)}
|
||||
>
|
||||
{child.icon && (
|
||||
<child.icon
|
||||
className={cn(
|
||||
'w-4 h-4 mt-0.5 shrink-0',
|
||||
active ? 'text-primary' : 'text-muted-foreground',
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className={cn('text-sm font-medium leading-none', active && 'text-primary')}>
|
||||
{child.title}
|
||||
</div>
|
||||
{child.description && (
|
||||
<p className="mt-1 line-clamp-2 text-xs leading-snug text-muted-foreground">
|
||||
{child.description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</Link>
|
||||
</NavigationMenuLink>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</NavigationMenuContent>
|
||||
</>
|
||||
/>
|
||||
)}
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className={cn('font-medium leading-none', active && 'text-primary')}>
|
||||
{child.title}
|
||||
</div>
|
||||
{child.description && (
|
||||
<p className="mt-1 line-clamp-2 text-xs leading-snug text-muted-foreground">
|
||||
{child.description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
);
|
||||
})}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
) : (
|
||||
<Link href={item.href || '#'} legacyBehavior passHref>
|
||||
<NavigationMenuLink
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue