hide sidebar component

This commit is contained in:
Harivansh Rathi 2024-12-11 17:45:56 -05:00
parent 979fc85242
commit 3fb10c4172
3 changed files with 96 additions and 27 deletions

View file

@ -1,33 +1,65 @@
import React from 'react'; import React, { createContext, useContext, useState } from 'react';
import { Outlet } from 'react-router-dom'; import { Outlet } from 'react-router-dom';
import { PanelLeft } from 'lucide-react';
import { Header } from '../Header/index'; import { Header } from '../Header/index';
import { Sidebar } from '../Sidebar/index'; import { Sidebar } from '../Sidebar/index';
import { cn } from '../../../lib/utils';
type SidebarContextType = {
isHidden: boolean;
setIsHidden: (hidden: boolean) => void;
};
export const SidebarContext = createContext<SidebarContextType>({
isHidden: false,
setIsHidden: () => {},
});
export const useSidebar = () => useContext(SidebarContext);
const DashboardLayout = () => { const DashboardLayout = () => {
const [isHidden, setIsHidden] = useState(false);
return ( return (
<div className="flex h-screen bg-secondary/20"> <SidebarContext.Provider value={{ isHidden, setIsHidden }}>
{/* Fixed header */} <div className="flex h-screen bg-secondary/20">
<div className="fixed top-0 left-0 right-0 z-50"> {/* Fixed header */}
<Header /> <div className="fixed top-0 left-0 right-0 z-50">
</div> <Header />
{/* Sidebar and main content */}
<div className="flex w-full pt-16">
{/* Fixed sidebar */}
<div className="fixed left-0 top-16 bottom-0 w-[280px] p-4 overflow-y-auto">
<Sidebar />
</div> </div>
{/* Main content area */} {/* Sidebar and main content */}
<div className="flex-1 ml-[280px]"> <div className="flex w-full pt-16">
<main className="h-[calc(100vh-4rem)] relative"> {/* Fixed sidebar */}
<div className="h-full"> <div className="fixed left-0 top-16 bottom-0 w-[280px] p-4 overflow-y-auto">
<Outlet /> <Sidebar />
</div> </div>
</main>
{/* Main content area */}
<div className={cn(
"flex-1 transition-all duration-300",
isHidden ? "ml-0" : "ml-[280px]"
)}>
<main className="h-[calc(100vh-4rem)] relative">
<div className="h-full">
<Outlet />
</div>
</main>
</div>
</div> </div>
{/* Fixed Show Sidebar Button - Only visible when sidebar is hidden */}
{isHidden && (
<button
onClick={() => setIsHidden(false)}
className="fixed left-4 bottom-4 z-50 flex items-center gap-2 px-4 py-2 bg-background border rounded-xl shadow-lg transition-all duration-200 text-sm font-medium text-muted-foreground hover:bg-accent"
>
<PanelLeft className="h-5 w-5" />
<span>Show Sidebar</span>
</button>
)}
</div> </div>
</div> </SidebarContext.Provider>
); );
}; };

View file

@ -4,10 +4,13 @@ import {
Settings, Settings,
MessageSquare, MessageSquare,
Upload, Upload,
History History,
PanelLeftClose,
PanelLeft
} from 'lucide-react'; } from 'lucide-react';
import { cn } from '../../../lib/utils'; import { cn } from '../../../lib/utils';
import { useLatestChat } from '../../../hooks/useLatestChat'; import { useLatestChat } from '../../../hooks/useLatestChat';
import { useSidebar } from '../../../hooks/useSidebar';
const sidebarItems = [ const sidebarItems = [
{ {
@ -35,6 +38,7 @@ const sidebarItems = [
const Sidebar = () => { const Sidebar = () => {
const location = useLocation(); const location = useLocation();
const { navigateToChat } = useLatestChat(); const { navigateToChat } = useLatestChat();
const { isHidden, setIsHidden } = useSidebar();
const isActive = (path: string) => { const isActive = (path: string) => {
if (path.startsWith('/dashboard/ask')) { if (path.startsWith('/dashboard/ask')) {
@ -44,8 +48,13 @@ const Sidebar = () => {
}; };
return ( return (
<div className="h-full"> <div
<div className="flex flex-col h-full space-y-4"> className={cn(
"fixed left-0 top-16 bottom-0 w-[280px] bg-background border-r transition-all duration-300 z-50",
isHidden ? "-translate-x-[280px]" : "translate-x-0"
)}
>
<div className="flex flex-col h-full p-4">
{/* Navigation Links */} {/* Navigation Links */}
<nav className="flex-1 space-y-1"> <nav className="flex-1 space-y-1">
{sidebarItems.map((item, index) => { {sidebarItems.map((item, index) => {
@ -62,14 +71,14 @@ const Sidebar = () => {
'w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200', 'w-full flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200',
active active
? 'bg-purple-50/50 text-purple-500' ? 'bg-purple-50/50 text-purple-500'
: 'text-muted-foreground hover:bg-purple-50/30 hover:text-purple-500' : 'text-muted-foreground'
)} )}
> >
<Icon className={cn( <Icon className={cn(
'h-5 w-5', 'h-5 w-5',
active active
? 'text-purple-500' ? 'text-purple-500'
: 'text-muted-foreground group-hover:text-purple-500' : 'text-muted-foreground'
)} /> )} />
{item.label} {item.label}
</button> </button>
@ -84,20 +93,38 @@ const Sidebar = () => {
'flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200', 'flex items-center gap-3 px-4 py-3 text-sm font-medium rounded-xl transition-all duration-200',
active active
? 'bg-purple-50/50 text-purple-500' ? 'bg-purple-50/50 text-purple-500'
: 'text-muted-foreground hover:bg-purple-50/30 hover:text-purple-500' : 'text-muted-foreground'
)} )}
> >
<Icon className={cn( <Icon className={cn(
'h-5 w-5', 'h-5 w-5',
active active
? 'text-purple-500' ? 'text-purple-500'
: 'text-muted-foreground group-hover:text-purple-500' : 'text-muted-foreground'
)} /> )} />
{item.label} {item.label}
</Link> </Link>
); );
})} })}
</nav> </nav>
{/* Toggle Button */}
<button
onClick={() => setIsHidden(!isHidden)}
className="flex items-center gap-2 px-4 py-2 mt-4 text-sm font-medium rounded-xl transition-all duration-200 text-muted-foreground"
>
{isHidden ? (
<>
<PanelLeft className="h-5 w-5" />
Show Sidebar
</>
) : (
<>
<PanelLeftClose className="h-5 w-5" />
Hide Sidebar
</>
)}
</button>
</div> </div>
</div> </div>
); );

10
src/hooks/useSidebar.ts Normal file
View file

@ -0,0 +1,10 @@
import { useContext } from 'react';
import { SidebarContext } from '../components/layout/DashboardLayout';
export const useSidebar = () => {
const context = useContext(SidebarContext);
if (!context) {
throw new Error('useSidebar must be used within a SidebarProvider');
}
return context;
};