diff --git a/components/topbar/app-topbar.tsx b/components/topbar/app-topbar.tsx index 8fcdf8c..b877035 100644 --- a/components/topbar/app-topbar.tsx +++ b/components/topbar/app-topbar.tsx @@ -29,7 +29,7 @@ export function AppTopbar({ notificationsSnapshot, }: AppTopbarProps) { return ( -
+
{/* Logo */} + {items.map((item) => ( +
  • + + {item.icon} + {item.label} + {item.badge && item.badge > 0 ? ( + + {item.badge} + + ) : null} + +
  • + ))} + + ); +} diff --git a/components/topbar/mobile-nav-link.tsx b/components/topbar/mobile-nav-link.tsx new file mode 100644 index 0000000..8f2635e --- /dev/null +++ b/components/topbar/mobile-nav-link.tsx @@ -0,0 +1,56 @@ +"use client"; + +import Link from "next/link"; +import { usePathname } from "next/navigation"; +import { Badge } from "@/components/ui/badge"; +import { cn } from "@/lib/utils/ui"; + +type MobileNavLinkProps = { + href: string; + icon: React.ReactNode; + children: React.ReactNode; + onClick?: () => void; + badge?: number; +}; + +export function MobileNavLink({ + href, + icon, + children, + onClick, + badge, +}: MobileNavLinkProps) { + const pathname = usePathname(); + const isActive = + href === "/dashboard" + ? pathname === href + : pathname === href || pathname.startsWith(`${href}/`); + + return ( + + {icon} + {children} + {badge && badge > 0 ? ( + + {badge} + + ) : null} + + ); +} + +export function MobileSectionLabel({ label }: { label: string }) { + return ( +

    + {label} +

    + ); +} diff --git a/components/topbar/nav-styles.ts b/components/topbar/nav-styles.ts new file mode 100644 index 0000000..c7845f9 --- /dev/null +++ b/components/topbar/nav-styles.ts @@ -0,0 +1,20 @@ +export const linkBase = + "inline-flex h-9 items-center justify-center rounded-md px-3 py-2 text-sm font-medium transition-colors"; + +export const linkIdle = "text-foreground hover:text-foreground hover:underline"; + +export const linkActive = "text-primary"; + +export const triggerClass = [ + "text-foreground!", + "bg-transparent!", + "hover:bg-transparent!", + "hover:text-foreground!", + "hover:underline!", + "focus:bg-transparent!", + "focus:text-foreground!", + "data-[state=open]:bg-transparent!", + "data-[state=open]:text-foreground!", + "data-[state=open]:underline!", + "px-3!", +].join(" "); diff --git a/components/topbar/simple-nav-link.tsx b/components/topbar/simple-nav-link.tsx new file mode 100644 index 0000000..4f2a6a2 --- /dev/null +++ b/components/topbar/simple-nav-link.tsx @@ -0,0 +1,28 @@ +"use client"; + +import Link from "next/link"; +import { usePathname } from "next/navigation"; +import { cn } from "@/lib/utils/ui"; +import { linkActive, linkBase, linkIdle } from "./nav-styles"; + +type SimpleNavLinkProps = { + href: string; + children: React.ReactNode; +}; + +export function SimpleNavLink({ href, children }: SimpleNavLinkProps) { + const pathname = usePathname(); + const isActive = + href === "/dashboard" + ? pathname === href + : pathname === href || pathname.startsWith(`${href}/`); + + return ( + + {children} + + ); +} diff --git a/components/topbar/top-nav-menu.tsx b/components/topbar/top-nav-menu.tsx index 9420158..c61d50c 100644 --- a/components/topbar/top-nav-menu.tsx +++ b/components/topbar/top-nav-menu.tsx @@ -15,10 +15,7 @@ import { RiSparklingLine, RiTodoLine, } from "@remixicon/react"; -import Link from "next/link"; -import { usePathname } from "next/navigation"; import { useState } from "react"; -import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { NavigationMenu, @@ -34,136 +31,16 @@ import { SheetTitle, SheetTrigger, } from "@/components/ui/sheet"; -import { cn } from "@/lib/utils/ui"; +import type { DropdownLinkItem } from "./dropdown-link-list"; +import { DropdownLinkList } from "./dropdown-link-list"; +import { MobileNavLink, MobileSectionLabel } from "./mobile-nav-link"; +import { triggerClass } from "./nav-styles"; +import { SimpleNavLink } from "./simple-nav-link"; type TopNavMenuProps = { preLancamentosCount?: number; }; -const linkBase = - "inline-flex h-9 items-center justify-center rounded-md px-3 py-2 text-sm font-medium transition-colors"; -const linkIdle = "text-foreground hover:text-foreground hover:underline"; -const linkActive = "text-primary"; - -// NavigationMenuTrigger override: remove backgrounds, keep underline style -const triggerClass = [ - "text-foreground!", - "bg-transparent!", - "hover:bg-transparent!", - "hover:text-foreground!", - "hover:underline!", - "focus:bg-transparent!", - "focus:text-foreground!", - "data-[state=open]:bg-transparent!", - "data-[state=open]:text-foreground!", - "data-[state=open]:underline!", - "px-3!", -].join(" "); - -function SimpleNavLink({ - href, - children, -}: { - href: string; - children: React.ReactNode; -}) { - const pathname = usePathname(); - const isActive = - href === "/dashboard" - ? pathname === href - : pathname === href || pathname.startsWith(`${href}/`); - - return ( - - {children} - - ); -} - -type DropdownLinkItem = { - href: string; - label: string; - icon: React.ReactNode; - badge?: number; -}; - -function DropdownLinkList({ items }: { items: DropdownLinkItem[] }) { - return ( -
      - {items.map((item) => ( -
    • - - {item.icon} - {item.label} - {item.badge && item.badge > 0 ? ( - - {item.badge} - - ) : null} - -
    • - ))} -
    - ); -} - -function MobileNavLink({ - href, - icon, - children, - onClick, - badge, -}: { - href: string; - icon: React.ReactNode; - children: React.ReactNode; - onClick?: () => void; - badge?: number; -}) { - const pathname = usePathname(); - const isActive = - href === "/dashboard" - ? pathname === href - : pathname === href || pathname.startsWith(`${href}/`); - - return ( - - {icon} - {children} - {badge && badge > 0 ? ( - - {badge} - - ) : null} - - ); -} - -function MobileSectionLabel({ label }: { label: string }) { - return ( -

    - {label} -

    - ); -} - export function TopNavMenu({ preLancamentosCount = 0 }: TopNavMenuProps) { const [sheetOpen, setSheetOpen] = useState(false); const close = () => setSheetOpen(false);