2026-01-08 19:10:40 +02:00
"use client" ;
2026-03-27 01:39:15 -07:00
import { useAtomValue } from "jotai" ;
2026-03-22 00:01:31 +05:30
import { AnimatePresence , motion } from "motion/react" ;
2026-04-19 14:50:55 +02:00
import dynamic from "next/dynamic" ;
2026-03-22 00:01:31 +05:30
import { useCallback , useMemo , useState } from "react" ;
2026-03-27 01:39:15 -07:00
import { activeTabAtom , type Tab } from "@/atoms/tabs/tabs.atom" ;
2026-04-19 14:50:55 +02:00
import { Spinner } from "@/components/ui/spinner" ;
2026-01-08 19:10:40 +02:00
import { TooltipProvider } from "@/components/ui/tooltip" ;
2026-01-27 19:46:43 +05:30
import type { InboxItem } from "@/hooks/use-inbox" ;
2026-01-08 19:10:40 +02:00
import { useIsMobile } from "@/hooks/use-mobile" ;
import { cn } from "@/lib/utils" ;
2026-01-27 19:46:43 +05:30
import { SidebarProvider , useSidebarState } from "../../hooks" ;
2026-05-04 01:47:17 +05:30
import {
SIDEBAR_MAX_WIDTH ,
SIDEBAR_MIN_WIDTH ,
useSidebarResize ,
} from "../../hooks/useSidebarResize" ;
2026-01-13 00:17:12 -08:00
import type { ChatItem , NavItem , PageUsage , SearchSpace , User } from "../../types/layout.types" ;
2026-01-08 19:10:40 +02:00
import { Header } from "../header" ;
import { IconRail } from "../icon-rail" ;
2026-03-29 21:27:10 +05:30
import { RightPanel , RightPanelExpandButton } from "../right-panel/RightPanel" ;
2026-02-09 11:41:55 -05:00
import {
2026-03-22 00:01:31 +05:30
AllPrivateChatsSidebarContent ,
AllSharedChatsSidebarContent ,
2026-03-05 20:34:02 +05:30
DocumentsSidebar ,
2026-03-22 00:01:31 +05:30
InboxSidebarContent ,
2026-02-09 11:41:55 -05:00
MobileSidebar ,
MobileSidebarTrigger ,
Sidebar ,
} from "../sidebar" ;
2026-03-22 00:01:31 +05:30
import { SidebarSlideOutPanel } from "../sidebar/SidebarSlideOutPanel" ;
2026-03-27 01:39:15 -07:00
import { TabBar } from "../tabs/TabBar" ;
2026-05-17 03:17:12 +05:30
import { WorkspacePanel } from "./WorkspacePanel" ;
2026-01-27 19:46:43 +05:30
2026-04-19 14:50:55 +02:00
const DocumentTabContent = dynamic (
( ) = > import ( "../tabs/DocumentTabContent" ) . then ( ( m ) = > ( { default : m . DocumentTabContent } ) ) ,
{
ssr : false ,
loading : ( ) = > (
< div className = "flex-1 flex items-center justify-center h-full" >
< Spinner size = "lg" / >
< / div >
) ,
}
) ;
2026-03-06 19:35:35 +05:30
// Per-tab data source
interface TabDataSource {
2026-01-27 19:46:43 +05:30
items : InboxItem [ ] ;
2026-03-06 19:35:35 +05:30
unreadCount : number ;
2026-01-27 19:46:43 +05:30
loading : boolean ;
2026-03-06 19:35:35 +05:30
loadingMore : boolean ;
hasMore : boolean ;
loadMore : ( ) = > void ;
2026-01-27 19:46:43 +05:30
markAsRead : ( id : number ) = > Promise < boolean > ;
markAllAsRead : ( ) = > Promise < boolean > ;
2026-03-06 19:35:35 +05:30
}
2026-05-03 18:42:29 +05:30
export type ActiveSlideoutPanel = "inbox" | "shared" | "private" | null ;
2026-03-22 00:01:31 +05:30
2026-03-06 19:35:35 +05:30
// Inbox-related props — per-tab data sources with independent loading/pagination
interface InboxProps {
isOpen : boolean ;
totalUnreadCount : number ;
comments : TabDataSource ;
status : TabDataSource ;
2026-01-27 19:46:43 +05:30
}
2026-01-08 19:10:40 +02:00
interface LayoutShellProps {
2026-01-12 15:47:56 +02:00
searchSpaces : SearchSpace [ ] ;
activeSearchSpaceId : number | null ;
onSearchSpaceSelect : ( id : number ) = > void ;
2026-01-13 01:45:58 -08:00
onSearchSpaceDelete ? : ( searchSpace : SearchSpace ) = > void ;
onSearchSpaceSettings ? : ( searchSpace : SearchSpace ) = > void ;
2026-01-12 15:47:56 +02:00
onAddSearchSpace : ( ) = > void ;
searchSpace : SearchSpace | null ;
2026-01-08 19:10:40 +02:00
navItems : NavItem [ ] ;
onNavItemClick ? : ( item : NavItem ) = > void ;
chats : ChatItem [ ] ;
2026-01-13 00:17:12 -08:00
sharedChats? : ChatItem [ ] ;
2026-01-08 19:10:40 +02:00
activeChatId? : number | null ;
onNewChat : ( ) = > void ;
onChatSelect : ( chat : ChatItem ) = > void ;
2026-02-03 20:47:18 -05:00
onChatRename ? : ( chat : ChatItem ) = > void ;
2026-01-08 19:10:40 +02:00
onChatDelete ? : ( chat : ChatItem ) = > void ;
2026-01-24 15:17:35 +05:30
onChatArchive ? : ( chat : ChatItem ) = > void ;
2026-01-13 00:17:12 -08:00
onViewAllSharedChats ? : ( ) = > void ;
onViewAllPrivateChats ? : ( ) = > void ;
2026-01-08 19:10:40 +02:00
user : User ;
onSettings ? : ( ) = > void ;
2026-01-12 15:47:56 +02:00
onManageMembers ? : ( ) = > void ;
2026-01-12 17:06:05 +02:00
onUserSettings ? : ( ) = > void ;
2026-05-03 18:42:29 +05:30
onAnnouncements ? : ( ) = > void ;
announcementUnreadCount? : number ;
2026-01-08 19:10:40 +02:00
onLogout ? : ( ) = > void ;
pageUsage? : PageUsage ;
theme? : string ;
2026-01-20 16:04:56 +05:30
setTheme ? : ( theme : "light" | "dark" | "system" ) = > void ;
2026-01-08 19:10:40 +02:00
defaultCollapsed? : boolean ;
isChatPage? : boolean ;
2026-05-17 03:17:12 +05:30
useWorkspacePanel? : boolean ;
2026-05-18 01:51:31 +05:30
workspacePanelViewportClassName? : string ;
workspacePanelContentClassName? : string ;
2026-01-08 19:10:40 +02:00
children : React.ReactNode ;
className? : string ;
2026-03-22 00:01:31 +05:30
// Unified slide-out panel state
activeSlideoutPanel? : ActiveSlideoutPanel ;
onSlideoutPanelChange ? : ( panel : ActiveSlideoutPanel ) = > void ;
2026-01-27 19:46:43 +05:30
// Inbox props
inbox? : InboxProps ;
2026-02-04 20:13:33 +05:30
isLoadingChats? : boolean ;
2026-02-09 11:41:55 -05:00
// All chats panel props
2026-02-09 16:49:11 -08:00
allSharedChatsPanel ? : {
searchSpaceId : string ;
} ;
allPrivateChatsPanel ? : {
searchSpaceId : string ;
} ;
2026-03-05 20:34:02 +05:30
documentsPanel ? : {
open : boolean ;
onOpenChange : ( open : boolean ) = > void ;
2026-03-10 12:26:45 +05:30
isDocked? : boolean ;
onDockedChange ? : ( docked : boolean ) = > void ;
2026-03-05 20:34:02 +05:30
} ;
2026-03-27 01:39:15 -07:00
onTabSwitch ? : ( tab : Tab ) = > void ;
}
function MainContentPanel ( {
isChatPage ,
onTabSwitch ,
onNewChat ,
children ,
} : {
isChatPage : boolean ;
onTabSwitch ? : ( tab : Tab ) = > void ;
onNewChat ? : ( ) = > void ;
children : React.ReactNode ;
} ) {
const activeTab = useAtomValue ( activeTabAtom ) ;
const isDocumentTab = activeTab ? . type === "document" ;
return (
2026-05-01 18:43:45 +05:30
< div className = "relative isolate flex flex-1 flex-col min-w-0" >
2026-03-29 21:27:10 +05:30
< TabBar
onTabSwitch = { onTabSwitch }
onNewChat = { onNewChat }
2026-03-31 16:35:29 +05:30
rightActions = { < RightPanelExpandButton / > }
className = "min-w-0"
2026-03-29 21:27:10 +05:30
/ >
2026-05-04 02:05:20 +05:30
< div className = "relative flex flex-1 flex-col bg-panel overflow-hidden min-w-0" >
2026-03-31 16:35:29 +05:30
< Header / >
2026-03-27 01:39:15 -07:00
2026-03-31 16:35:29 +05:30
{ isDocumentTab && activeTab . documentId && activeTab . searchSpaceId ? (
< div className = "flex-1 overflow-hidden" >
< DocumentTabContent
key = { activeTab . documentId }
documentId = { activeTab . documentId }
searchSpaceId = { activeTab . searchSpaceId }
title = { activeTab . title }
/ >
< / div >
) : (
< div className = { cn ( "flex-1" , isChatPage ? "overflow-hidden" : "overflow-auto" ) } >
{ children }
< / div >
) }
< / div >
2026-03-27 01:39:15 -07:00
< / div >
) ;
2026-01-08 19:10:40 +02:00
}
2026-05-17 03:17:12 +05:30
function DesktopWorkspaceRegion ( { children } : { children : React.ReactNode } ) {
return < div className = "flex h-full min-w-0 flex-1 -mr-2" > { children } < / div > ;
}
2026-01-08 19:10:40 +02:00
export function LayoutShell ( {
2026-01-12 15:47:56 +02:00
searchSpaces ,
activeSearchSpaceId ,
onSearchSpaceSelect ,
2026-01-13 01:45:58 -08:00
onSearchSpaceDelete ,
onSearchSpaceSettings ,
2026-01-12 15:47:56 +02:00
onAddSearchSpace ,
searchSpace ,
2026-01-08 19:10:40 +02:00
navItems ,
onNavItemClick ,
chats ,
2026-01-13 00:17:12 -08:00
sharedChats ,
2026-01-08 19:10:40 +02:00
activeChatId ,
onNewChat ,
onChatSelect ,
2026-02-03 20:47:18 -05:00
onChatRename ,
2026-01-08 19:10:40 +02:00
onChatDelete ,
2026-01-24 15:17:35 +05:30
onChatArchive ,
2026-01-13 00:17:12 -08:00
onViewAllSharedChats ,
onViewAllPrivateChats ,
2026-01-08 19:10:40 +02:00
user ,
onSettings ,
2026-01-12 15:47:56 +02:00
onManageMembers ,
2026-01-12 17:06:05 +02:00
onUserSettings ,
2026-05-03 18:42:29 +05:30
onAnnouncements ,
announcementUnreadCount = 0 ,
2026-01-08 19:10:40 +02:00
onLogout ,
pageUsage ,
theme ,
2026-01-20 16:04:56 +05:30
setTheme ,
2026-01-08 19:10:40 +02:00
defaultCollapsed = false ,
isChatPage = false ,
2026-05-17 03:17:12 +05:30
useWorkspacePanel = false ,
2026-05-18 01:51:31 +05:30
workspacePanelViewportClassName ,
workspacePanelContentClassName ,
2026-01-08 19:10:40 +02:00
children ,
className ,
2026-03-22 00:01:31 +05:30
activeSlideoutPanel = null ,
onSlideoutPanelChange ,
2026-01-27 19:46:43 +05:30
inbox ,
2026-02-04 20:13:33 +05:30
isLoadingChats = false ,
2026-02-09 11:41:55 -05:00
allSharedChatsPanel ,
allPrivateChatsPanel ,
2026-03-05 20:34:02 +05:30
documentsPanel ,
2026-03-27 01:39:15 -07:00
onTabSwitch ,
2026-01-08 19:10:40 +02:00
} : LayoutShellProps ) {
const isMobile = useIsMobile ( ) ;
const [ mobileMenuOpen , setMobileMenuOpen ] = useState ( false ) ;
2026-01-27 19:46:43 +05:30
const { isCollapsed , setIsCollapsed , toggleCollapsed } = useSidebarState ( defaultCollapsed ) ;
2026-02-09 16:49:11 -08:00
const {
sidebarWidth ,
2026-05-04 01:47:17 +05:30
handlePointerDown : onResizePointerDown ,
2026-02-09 16:49:11 -08:00
isDragging : isResizing ,
} = useSidebarResize ( ) ;
2026-01-27 19:46:43 +05:30
// Memoize context value to prevent unnecessary re-renders
const sidebarContextValue = useMemo (
2026-05-02 14:01:33 +05:30
( ) = > ( { isCollapsed , setIsCollapsed , toggleCollapsed } ) ,
[ isCollapsed , setIsCollapsed , toggleCollapsed ]
2026-01-27 19:46:43 +05:30
) ;
2026-01-08 19:10:40 +02:00
2026-03-22 00:01:31 +05:30
const closeSlideout = useCallback (
( open : boolean ) = > {
if ( ! open ) onSlideoutPanelChange ? . ( null ) ;
} ,
[ onSlideoutPanelChange ]
) ;
const anySlideOutOpen = activeSlideoutPanel !== null ;
const panelAriaLabel =
activeSlideoutPanel === "inbox"
? "Inbox"
: activeSlideoutPanel === "shared"
? "Shared Chats"
: activeSlideoutPanel === "private"
? "Private Chats"
2026-05-03 18:42:29 +05:30
: "Panel" ;
2026-03-22 00:01:31 +05:30
2026-01-08 19:10:40 +02:00
// Mobile layout
if ( isMobile ) {
return (
2026-01-27 19:46:43 +05:30
< SidebarProvider value = { sidebarContextValue } >
< TooltipProvider delayDuration = { 0 } >
2026-05-03 20:38:21 +05:30
< div className = { cn ( "flex h-screen w-full flex-col bg-panel" , className ) } >
2026-03-07 04:46:48 +05:30
< Header
mobileMenuTrigger = { < MobileSidebarTrigger onClick = { ( ) = > setMobileMenuOpen ( true ) } / > }
/ >
2026-01-08 19:10:40 +02:00
2026-01-27 19:46:43 +05:30
< MobileSidebar
isOpen = { mobileMenuOpen }
onOpenChange = { setMobileMenuOpen }
searchSpaces = { searchSpaces }
activeSearchSpaceId = { activeSearchSpaceId }
onSearchSpaceSelect = { onSearchSpaceSelect }
onAddSearchSpace = { onAddSearchSpace }
searchSpace = { searchSpace }
navItems = { navItems }
onNavItemClick = { onNavItemClick }
chats = { chats }
sharedChats = { sharedChats }
activeChatId = { activeChatId }
onNewChat = { onNewChat }
onChatSelect = { onChatSelect }
2026-02-03 20:47:18 -05:00
onChatRename = { onChatRename }
2026-01-27 19:46:43 +05:30
onChatDelete = { onChatDelete }
onChatArchive = { onChatArchive }
onViewAllSharedChats = { onViewAllSharedChats }
onViewAllPrivateChats = { onViewAllPrivateChats }
2026-03-22 00:43:53 +05:30
isSharedChatsPanelOpen = { activeSlideoutPanel === "shared" }
isPrivateChatsPanelOpen = { activeSlideoutPanel === "private" }
2026-01-27 19:46:43 +05:30
user = { user }
onSettings = { onSettings }
onManageMembers = { onManageMembers }
onUserSettings = { onUserSettings }
2026-05-03 18:42:29 +05:30
onAnnouncements = { onAnnouncements }
announcementUnreadCount = { announcementUnreadCount }
2026-01-27 19:46:43 +05:30
onLogout = { onLogout }
pageUsage = { pageUsage }
theme = { theme }
setTheme = { setTheme }
2026-02-04 20:13:33 +05:30
isLoadingChats = { isLoadingChats }
2026-01-27 19:46:43 +05:30
/ >
2026-01-08 19:10:40 +02:00
2026-05-17 03:17:12 +05:30
{ useWorkspacePanel ? (
2026-05-18 01:51:31 +05:30
< WorkspacePanel
viewportClassName = { workspacePanelViewportClassName }
contentClassName = { workspacePanelContentClassName }
>
{ children }
< / WorkspacePanel >
2026-05-17 03:17:12 +05:30
) : (
< main className = { cn ( "flex-1" , isChatPage ? "overflow-hidden" : "overflow-auto" ) } >
{ children }
< / main >
) }
2026-03-03 13:09:29 -05:00
2026-03-22 00:43:53 +05:30
{ /* Mobile unified slide-out panel */ }
< SidebarSlideOutPanel
open = { anySlideOutOpen }
onOpenChange = { closeSlideout }
ariaLabel = { panelAriaLabel }
>
< AnimatePresence mode = "popLayout" initial = { false } >
{ activeSlideoutPanel === "inbox" && inbox && (
< motion.div
key = "inbox"
className = "h-full flex flex-col"
initial = { { opacity : 0 } }
animate = { { opacity : 1 } }
exit = { { opacity : 0 } }
transition = { { duration : 0.15 } }
>
< InboxSidebarContent
onOpenChange = { ( open ) = > closeSlideout ( open ) }
comments = { inbox . comments }
status = { inbox . status }
totalUnreadCount = { inbox . totalUnreadCount }
onCloseMobileSidebar = { ( ) = > setMobileMenuOpen ( false ) }
/ >
< / motion.div >
) }
{ activeSlideoutPanel === "shared" && allSharedChatsPanel && (
< motion.div
key = "shared"
className = "h-full flex flex-col"
initial = { { opacity : 0 } }
animate = { { opacity : 1 } }
exit = { { opacity : 0 } }
transition = { { duration : 0.15 } }
>
< AllSharedChatsSidebarContent
onOpenChange = { ( open ) = > closeSlideout ( open ) }
searchSpaceId = { allSharedChatsPanel . searchSpaceId }
onCloseMobileSidebar = { ( ) = > setMobileMenuOpen ( false ) }
/ >
< / motion.div >
) }
{ activeSlideoutPanel === "private" && allPrivateChatsPanel && (
< motion.div
key = "private"
className = "h-full flex flex-col"
initial = { { opacity : 0 } }
animate = { { opacity : 1 } }
exit = { { opacity : 0 } }
transition = { { duration : 0.15 } }
>
< AllPrivateChatsSidebarContent
onOpenChange = { ( open ) = > closeSlideout ( open ) }
searchSpaceId = { allPrivateChatsPanel . searchSpaceId }
onCloseMobileSidebar = { ( ) = > setMobileMenuOpen ( false ) }
/ >
< / motion.div >
) }
< / AnimatePresence >
< / SidebarSlideOutPanel >
2026-02-22 00:24:49 +05:30
2026-03-22 00:43:53 +05:30
{ /* Mobile Documents Sidebar - separate (not part of slide-out group) */ }
{ documentsPanel && (
< DocumentsSidebar
open = { documentsPanel . open }
onOpenChange = { documentsPanel . onOpenChange }
/ >
) }
2026-01-27 19:46:43 +05:30
< / div >
< / TooltipProvider >
< / SidebarProvider >
2026-01-08 19:10:40 +02:00
) ;
}
// Desktop layout
return (
2026-01-27 19:46:43 +05:30
< SidebarProvider value = { sidebarContextValue } >
< TooltipProvider delayDuration = { 0 } >
2026-01-28 02:14:36 +05:30
< div
2026-05-03 20:38:21 +05:30
className = { cn (
"flex h-screen w-full gap-2 px-2 py-0 overflow-hidden bg-rail" ,
className
) }
2026-01-28 02:14:36 +05:30
>
2026-05-03 20:38:21 +05:30
< div className = "hidden md:flex overflow-hidden border-r -mr-2 pr-2 bg-rail" >
2026-01-27 19:46:43 +05:30
< IconRail
searchSpaces = { searchSpaces }
activeSearchSpaceId = { activeSearchSpaceId }
onSearchSpaceSelect = { onSearchSpaceSelect }
onSearchSpaceDelete = { onSearchSpaceDelete }
onSearchSpaceSettings = { onSearchSpaceSettings }
onAddSearchSpace = { onAddSearchSpace }
2026-05-04 01:47:17 +05:30
isSingleRailMode = { false }
2026-04-28 19:29:14 +05:30
user = { user }
onUserSettings = { onUserSettings }
2026-05-03 18:42:29 +05:30
onAnnouncements = { onAnnouncements }
announcementUnreadCount = { announcementUnreadCount }
2026-04-28 19:29:14 +05:30
onLogout = { onLogout }
theme = { theme }
setTheme = { setTheme }
2026-01-27 19:46:43 +05:30
/ >
< / div >
2026-01-08 19:10:40 +02:00
2026-05-02 14:01:33 +05:30
{ /* Sidebar + slide-out panels share one container; overflow visible so panels can overlay main content. Negative right margin closes the flex gap so the sidebar sits flush against the main panel, separated only by a border. */ }
2026-05-04 01:47:17 +05:30
< div className = "relative hidden md:flex shrink-0 z-20 -mr-2 border-r bg-panel" >
< Sidebar
searchSpace = { searchSpace }
isCollapsed = { isCollapsed }
onToggleCollapse = { toggleCollapsed }
navItems = { navItems }
onNavItemClick = { onNavItemClick }
chats = { chats }
sharedChats = { sharedChats }
activeChatId = { activeChatId }
onNewChat = { onNewChat }
onChatSelect = { onChatSelect }
onChatRename = { onChatRename }
onChatDelete = { onChatDelete }
onChatArchive = { onChatArchive }
onViewAllSharedChats = { onViewAllSharedChats }
onViewAllPrivateChats = { onViewAllPrivateChats }
isSharedChatsPanelOpen = { activeSlideoutPanel === "shared" }
isPrivateChatsPanelOpen = { activeSlideoutPanel === "private" }
user = { user }
onSettings = { onSettings }
onManageMembers = { onManageMembers }
onUserSettings = { onUserSettings }
onAnnouncements = { onAnnouncements }
announcementUnreadCount = { announcementUnreadCount }
onLogout = { onLogout }
pageUsage = { pageUsage }
theme = { theme }
setTheme = { setTheme }
renderUserProfile = { false }
className = "flex shrink-0"
isLoadingChats = { isLoadingChats }
sidebarWidth = { sidebarWidth }
isResizing = { isResizing }
/ >
2026-03-10 12:26:45 +05:30
2026-05-02 14:01:33 +05:30
{ ! isCollapsed && (
2026-05-04 01:47:17 +05:30
< hr
aria - orientation = "vertical"
2026-05-02 14:01:33 +05:30
aria - label = "Resize sidebar"
2026-05-04 01:47:17 +05:30
aria - valuemin = { SIDEBAR_MIN_WIDTH }
aria - valuemax = { SIDEBAR_MAX_WIDTH }
aria - valuenow = { sidebarWidth }
tabIndex = { 0 }
onPointerDown = { onResizePointerDown }
style = { { touchAction : "none" } }
2026-05-03 20:38:21 +05:30
className = { cn (
2026-05-04 02:05:20 +05:30
"absolute top-0 right-0 h-full w-4 translate-x-1/2 z-50 m-0 border-0 bg-transparent p-0 select-none cursor-col-resize" ,
2026-05-03 20:38:21 +05:30
"after:content-[''] after:absolute after:inset-y-0 after:left-1/2 after:w-px after:-translate-x-1/2 after:bg-transparent hover:after:bg-border/80 after:transition-colors" ,
isResizing && "after:bg-border"
) }
2026-05-02 14:01:33 +05:30
/ >
) }
2026-03-22 00:01:31 +05:30
{ /* Unified slide-out panel — shell stays open, content cross-fades */ }
< SidebarSlideOutPanel
open = { anySlideOutOpen }
onOpenChange = { closeSlideout }
ariaLabel = { panelAriaLabel }
>
< AnimatePresence mode = "popLayout" initial = { false } >
{ activeSlideoutPanel === "inbox" && inbox && (
< motion.div
key = "inbox"
className = "h-full flex flex-col"
initial = { { opacity : 0 } }
animate = { { opacity : 1 } }
exit = { { opacity : 0 } }
transition = { { duration : 0.15 } }
>
< InboxSidebarContent
onOpenChange = { ( open ) = > closeSlideout ( open ) }
comments = { inbox . comments }
status = { inbox . status }
totalUnreadCount = { inbox . totalUnreadCount }
/ >
< / motion.div >
) }
{ activeSlideoutPanel === "shared" && allSharedChatsPanel && (
< motion.div
key = "shared"
className = "h-full flex flex-col"
initial = { { opacity : 0 } }
animate = { { opacity : 1 } }
exit = { { opacity : 0 } }
transition = { { duration : 0.15 } }
>
< AllSharedChatsSidebarContent
onOpenChange = { ( open ) = > closeSlideout ( open ) }
searchSpaceId = { allSharedChatsPanel . searchSpaceId }
/ >
< / motion.div >
) }
{ activeSlideoutPanel === "private" && allPrivateChatsPanel && (
< motion.div
key = "private"
className = "h-full flex flex-col"
initial = { { opacity : 0 } }
animate = { { opacity : 1 } }
exit = { { opacity : 0 } }
transition = { { duration : 0.15 } }
>
< AllPrivateChatsSidebarContent
onOpenChange = { ( open ) = > closeSlideout ( open ) }
searchSpaceId = { allPrivateChatsPanel . searchSpaceId }
/ >
< / motion.div >
) }
< / AnimatePresence >
< / SidebarSlideOutPanel >
2026-01-27 19:46:43 +05:30
< / div >
2026-03-17 01:09:15 +05:30
2026-05-17 03:17:12 +05:30
< DesktopWorkspaceRegion >
{ useWorkspacePanel ? (
2026-05-18 01:51:31 +05:30
< WorkspacePanel
viewportClassName = { workspacePanelViewportClassName }
contentClassName = { workspacePanelContentClassName }
>
{ children }
< / WorkspacePanel >
2026-05-17 03:17:12 +05:30
) : (
< >
{ /* Main content panel */ }
< MainContentPanel
isChatPage = { isChatPage }
onTabSwitch = { onTabSwitch }
onNewChat = { onNewChat }
>
{ children }
< / MainContentPanel >
2026-03-17 01:09:15 +05:30
2026-05-17 03:17:12 +05:30
{ /* Right panel — tabbed Sources/Report (desktop only) */ }
{ documentsPanel ? (
< RightPanel
documentsPanel = { {
open : documentsPanel.open ,
onOpenChange : documentsPanel.onOpenChange ,
} }
/ >
) : null }
< / >
) }
< / DesktopWorkspaceRegion >
2026-01-08 19:10:40 +02:00
< / div >
2026-01-27 19:46:43 +05:30
< / TooltipProvider >
< / SidebarProvider >
2026-01-08 19:10:40 +02:00
) ;
}