diff --git a/src/components/layout/ModernLayout.tsx b/src/components/layout/ModernLayout.tsx
index 5281493..ee17243 100644
--- a/src/components/layout/ModernLayout.tsx
+++ b/src/components/layout/ModernLayout.tsx
@@ -1,8 +1,9 @@
import React, { useState } from 'react';
-import { Link } from 'react-router-dom';
+import { Link, useLocation } from 'react-router-dom';
import { useIsMobile } from '@/hooks/use-mobile';
-import { ModernSidebar, SidebarBody, SidebarLink } from '@/components/ui/modern-sidebar';
+import { ModernSidebar, SidebarBody } from '@/components/ui/modern-sidebar';
+import { VerticalLimelightNav } from '@/components/ui/limelight-nav';
import OnboardingTour from '@/components/onboarding/OnboardingTour';
import HelpIcon from '@/components/help/HelpIcon';
import { useOnboardingTour } from '@/hooks/useOnboardingTour';
@@ -63,6 +64,7 @@ const LogoIcon = () => {
export default function ModernLayout({ children }: ModernLayoutProps) {
const [open, setOpen] = useState(false);
+ const location = useLocation();
const isMobile = useIsMobile();
const {
@@ -73,65 +75,82 @@ export default function ModernLayout({ children }: ModernLayoutProps) {
closeTour
} = useOnboardingTour();
- const links = [
+ const mainLinks = [
{
+ id: "dashboard",
label: "Dashboard",
href: "/",
- icon: ,
+ icon: ,
},
{
+ id: "transacoes",
label: "Transações",
href: "/transacoes",
- icon: ,
+ icon: ,
},
{
+ id: "cartoes",
label: "Cartões de Crédito",
href: "/cartoes",
- icon: ,
+ icon: ,
},
{
+ id: "categorias",
label: "Categorias",
href: "/categorias",
- icon: ,
+ icon: ,
},
{
+ id: "metas",
label: "Metas",
href: "/metas",
- icon: ,
+ icon: ,
},
{
+ id: "calendario",
label: "Calendário",
href: "/calendario",
- icon: ,
+ icon: ,
},
{
+ id: "assinatura",
label: "Assinatura",
href: "/assinatura",
- icon: ,
+ icon: ,
}
];
const whatsappLinks = [
{
+ id: "whatsapp",
label: "Conectar WhatsApp",
href: "/whatsapp",
- icon: ,
+ icon: ,
},
{
+ id: "grupos",
label: "Grupos",
href: "/grupos-whatsapp",
- icon: ,
+ icon: ,
}
];
const configLinks = [
{
+ id: "configuracoes",
label: "Configurações",
href: "/configuracoes",
- icon: ,
+ icon: ,
}
];
+ // Determine active index based on current route
+ const getActiveIndex = () => {
+ const allLinks = [...mainLinks, ...whatsappLinks, ...configLinks];
+ const activeIndex = allLinks.findIndex(link => link.href === location.pathname);
+ return activeIndex >= 0 ? activeIndex : 0;
+ };
+
return (
@@ -139,43 +158,53 @@ export default function ModernLayout({ children }: ModernLayoutProps) {
{open ?
:
}
-
- {links.map((link, idx) => (
-
- ))}
-
-
-
- {open && (
-
- WhatsApp
-
- )}
-
- {whatsappLinks.map((link, idx) => (
-
- ))}
+
+ {/* Main Navigation */}
+
+
-
-
- {open && (
-
- Configurações
-
- )}
-
- {configLinks.map((link, idx) => (
-
- ))}
+ {/* WhatsApp Section */}
+
+ {open && (
+
+ WhatsApp
+
+ )}
+ = mainLinks.length && getActiveIndex() < mainLinks.length + whatsappLinks.length ? getActiveIndex() - mainLinks.length : -1}
+ showLabels={open}
+ className="space-y-1"
+ />
+
+
+ {/* Config Section */}
+
+ {open && (
+
+ Configurações
+
+ )}
+ = mainLinks.length + whatsappLinks.length ? getActiveIndex() - mainLinks.length - whatsappLinks.length : -1}
+ showLabels={open}
+ className="space-y-1"
+ />
diff --git a/src/components/ui/limelight-nav.tsx b/src/components/ui/limelight-nav.tsx
new file mode 100644
index 0000000..b7c8dcd
--- /dev/null
+++ b/src/components/ui/limelight-nav.tsx
@@ -0,0 +1,145 @@
+
+import React, { useState, useRef, useLayoutEffect, cloneElement } from 'react';
+
+// --- Internal Types and Defaults ---
+
+const DefaultHomeIcon = (props: React.SVGProps
) => ;
+const DefaultCompassIcon = (props: React.SVGProps) => ;
+const DefaultBellIcon = (props: React.SVGProps) => ;
+
+export type NavItem = {
+ id: string | number;
+ icon: React.ReactElement;
+ label?: string;
+ onClick?: () => void;
+ href?: string;
+};
+
+const defaultNavItems: NavItem[] = [
+ { id: 'default-home', icon: , label: 'Home' },
+ { id: 'default-explore', icon: , label: 'Explore' },
+ { id: 'default-notifications', icon: , label: 'Notifications' },
+];
+
+type VerticalLimelightNavProps = {
+ items?: NavItem[];
+ defaultActiveIndex?: number;
+ onTabChange?: (index: number) => void;
+ className?: string;
+ limelightClassName?: string;
+ iconContainerClassName?: string;
+ iconClassName?: string;
+ showLabels?: boolean;
+};
+
+/**
+ * A vertical navigation bar with a "limelight" effect that highlights the active item.
+ */
+export const VerticalLimelightNav = ({
+ items = defaultNavItems,
+ defaultActiveIndex = 0,
+ onTabChange,
+ className,
+ limelightClassName,
+ iconContainerClassName,
+ iconClassName,
+ showLabels = true,
+}: VerticalLimelightNavProps) => {
+ const [activeIndex, setActiveIndex] = useState(defaultActiveIndex);
+ const [isReady, setIsReady] = useState(false);
+ const navItemRefs = useRef<(HTMLAnchorElement | null)[]>([]);
+ const limelightRef = useRef(null);
+
+ useLayoutEffect(() => {
+ if (items.length === 0) return;
+
+ const limelight = limelightRef.current;
+ const activeItem = navItemRefs.current[activeIndex];
+
+ if (limelight && activeItem) {
+ const newTop = activeItem.offsetTop + activeItem.offsetHeight / 2 - limelight.offsetHeight / 2;
+ limelight.style.top = `${newTop}px`;
+
+ if (!isReady) {
+ setTimeout(() => setIsReady(true), 50);
+ }
+ }
+ }, [activeIndex, isReady, items]);
+
+ if (items.length === 0) {
+ return null;
+ }
+
+ const handleItemClick = (index: number, item: NavItem) => {
+ setActiveIndex(index);
+ onTabChange?.(index);
+ item.onClick?.();
+ };
+
+ return (
+
+ );
+};
+
+export { VerticalLimelightNav as LimelightNav };