Refactor sidebar component

This commit is contained in:
gpt-engineer-app[bot]
2025-10-29 12:52:59 +00:00
parent 64c53ee1ec
commit bdb8443a51
3 changed files with 152 additions and 92 deletions
+6 -9
View File
@@ -1,16 +1,13 @@
import { SidebarProvider } from "@/components/ui/sidebar";
import { AppSidebar } from "./AppSidebar"; import { AppSidebar } from "./AppSidebar";
import { Outlet } from "react-router-dom"; import { Outlet } from "react-router-dom";
export function AppLayout() { export function AppLayout() {
return ( return (
<SidebarProvider> <div className="flex h-screen w-full bg-background overflow-hidden">
<div className="min-h-screen flex w-full bg-background"> <AppSidebar />
<AppSidebar /> <main className="flex-1 p-6 lg:p-8 overflow-y-auto">
<main className="flex-1 p-6 lg:p-8"> <Outlet />
<Outlet /> </main>
</main> </div>
</div>
</SidebarProvider>
); );
} }
+123 -83
View File
@@ -1,26 +1,18 @@
import { useState } from "react";
import { NavLink } from "react-router-dom"; import { NavLink } from "react-router-dom";
import { useTheme } from "next-themes";
import { import {
Bot, Bot,
FileText, FileText,
TestTube, TestTube,
History, History,
Link, Link,
Sun,
Moon,
ArrowLeft, ArrowLeft,
ChevronLeft,
ChevronRight,
} from "lucide-react"; } from "lucide-react";
import { import { Button } from "@/components/ui/button";
Sidebar, import { Separator } from "@/components/ui/separator";
SidebarContent, import { ThemeToggle } from "./ThemeToggle";
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarHeader,
} from "@/components/ui/sidebar";
const menuItems = [ const menuItems = [
{ title: "Agentes", url: "/", icon: Bot }, { title: "Agentes", url: "/", icon: Bot },
@@ -31,81 +23,129 @@ const menuItems = [
]; ];
export function AppSidebar() { export function AppSidebar() {
const { theme, setTheme } = useTheme(); const [isCollapsed, setIsCollapsed] = useState(false);
const toggleTheme = () => { if (isCollapsed) {
setTheme(theme === "dark" ? "light" : "dark"); return (
}; <aside className="hidden md:flex md:w-16 bg-sidebar border-r border-sidebar-border flex-col">
{/* Collapsed Header with Expand Button */}
return ( <div className="p-3 border-b border-sidebar-border space-y-2">
<Sidebar className="border-r border-border flex flex-col"> <Button
<SidebarHeader className="border-b border-border px-6 py-4"> variant="ghost"
<div className="flex items-center gap-2"> size="icon"
<div className="h-8 w-8 rounded-lg bg-primary flex items-center justify-center"> onClick={() => setIsCollapsed(false)}
<Bot className="h-5 w-5 text-primary-foreground" /> className="w-full text-muted-foreground hover:text-foreground"
</div> title="Expandir"
<div> >
<h1 className="text-lg font-semibold text-foreground">HGTX</h1> <ChevronRight className="w-4 h-4" />
<p className="text-xs text-muted-foreground">PromptLab</p> </Button>
<div className="w-full flex justify-center">
<div className="w-8 h-8 rounded-lg bg-gradient-to-br from-primary to-secondary flex items-center justify-center">
<span className="text-xs font-bold text-white">HX</span>
</div>
</div> </div>
</div> </div>
</SidebarHeader>
<SidebarContent className="flex-1"> {/* Navigation Icons */}
<SidebarGroup> <nav className="flex-1 px-2 py-2 space-y-1">
<SidebarGroupLabel className="text-xs font-medium text-muted-foreground px-3"> {menuItems.map((item) => {
Navegação const Icon = item.icon;
</SidebarGroupLabel> return (
<SidebarGroupContent> <NavLink
<SidebarMenu> key={item.title}
{menuItems.map((item) => ( to={item.url}
<SidebarMenuItem key={item.title}> end
<SidebarMenuButton asChild> className={({ isActive }) =>
<NavLink `w-full p-3 rounded-lg transition-all flex items-center justify-center ${
to={item.url} isActive
end ? "bg-sidebar-accent text-sidebar-accent-foreground cyber-border"
className={({ isActive }) => : "text-sidebar-foreground hover:bg-sidebar-accent/50"
`flex items-center gap-3 px-3 py-2 rounded-md transition-colors ${ }`
isActive }
? "bg-primary text-primary-foreground font-medium" title={item.title}
: "text-foreground hover:bg-muted" >
}` <Icon className="w-5 h-5" />
} </NavLink>
> );
<item.icon className="h-4 w-4" /> })}
<span>{item.title}</span> </nav>
</NavLink>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<div className="border-t border-border p-4 space-y-2"> <Separator className="bg-sidebar-border" />
<button
onClick={toggleTheme} {/* Theme & Settings Icons */}
className="w-full flex items-center gap-3 px-3 py-2 rounded-md text-foreground hover:bg-muted transition-colors" <div className="p-3 border-t border-sidebar-border space-y-2">
<ThemeToggle />
<Button
variant="ghost"
size="icon"
className="w-full text-sidebar-foreground"
title="Voltar"
>
<ArrowLeft className="w-4 h-4" />
</Button>
</div>
</aside>
);
}
return (
<aside className="hidden md:flex md:w-72 bg-sidebar border-r border-sidebar-border flex-col">
{/* Logo */}
<div className="p-6 border-b border-sidebar-border flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold gradient-text">HGTX Codex</h1>
<p className="text-xs text-muted-foreground mt-1">AI Interface System</p>
</div>
<Button
variant="ghost"
size="icon"
onClick={() => setIsCollapsed(true)}
className="h-8 w-8 text-muted-foreground hover:text-foreground"
> >
{theme === "dark" ? ( <ChevronLeft className="w-4 h-4" />
<> </Button>
<Sun className="h-4 w-4" />
<span>Tema Claro</span>
</>
) : (
<>
<Moon className="h-4 w-4" />
<span>Tema Escuro</span>
</>
)}
</button>
<button className="w-full flex items-center gap-3 px-3 py-2 rounded-md text-foreground hover:bg-muted transition-colors">
<ArrowLeft className="h-4 w-4" />
<span>Voltar</span>
</button>
</div> </div>
</Sidebar>
{/* Navigation Tabs */}
<nav className="flex-1 px-3 py-2 space-y-1">
{menuItems.map((item) => {
const Icon = item.icon;
return (
<NavLink
key={item.title}
to={item.url}
end
className={({ isActive }) =>
`w-full flex items-center gap-3 px-4 py-3 rounded-lg transition-all ${
isActive
? "bg-sidebar-accent text-sidebar-accent-foreground cyber-border"
: "text-sidebar-foreground hover:bg-sidebar-accent/50"
}`
}
>
<Icon className="w-5 h-5" />
<span className="font-medium">{item.title}</span>
</NavLink>
);
})}
</nav>
<Separator className="bg-sidebar-border" />
{/* Settings & Theme */}
<div className="p-4 border-t border-sidebar-border space-y-2">
<div className="flex items-center justify-between px-3">
<span className="text-sm font-medium text-sidebar-foreground">Tema</span>
<ThemeToggle />
</div>
<Button
variant="ghost"
className="w-full justify-start gap-2 text-sidebar-foreground"
>
<ArrowLeft className="w-4 h-4" />
Voltar
</Button>
</div>
</aside>
); );
} }
+23
View File
@@ -0,0 +1,23 @@
import { useTheme } from "next-themes";
import { Moon, Sun } from "lucide-react";
import { Button } from "@/components/ui/button";
export function ThemeToggle() {
const { theme, setTheme } = useTheme();
return (
<Button
variant="ghost"
size="icon"
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
className="w-full text-sidebar-foreground hover:bg-sidebar-accent/50"
title={theme === "dark" ? "Tema Claro" : "Tema Escuro"}
>
{theme === "dark" ? (
<Sun className="w-4 h-4" />
) : (
<Moon className="w-4 h-4" />
)}
</Button>
);
}