refactor(layout): streamline layout components by removing DocumentsSidebar references

- Eliminated DocumentsSidebar and related state management from FreeLayoutDataProvider and LayoutDataProvider for a cleaner architecture.
- Updated Sidebar and MobileSidebar components to remove unused props and improve layout consistency.
- Adjusted navigation item handling to simplify sidebar interactions and enhance user experience.
This commit is contained in:
Anish Sarkar 2026-07-06 15:35:09 +05:30
parent e133f6f8e8
commit 556f02c5be
6 changed files with 12 additions and 115 deletions

View file

@ -1,13 +1,12 @@
"use client";
import { Inbox, LibraryBig } from "lucide-react";
import { Inbox } from "lucide-react";
import { useRouter } from "next/navigation";
import type { ReactNode } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useAnonymousMode } from "@/contexts/anonymous-mode";
import { useLoginGate } from "@/contexts/login-gate";
import { useAnnouncements } from "@/hooks/use-announcements";
import { useIsMobile } from "@/hooks/use-mobile";
import { anonymousChatApiService } from "@/lib/apis/anonymous-chat-api.service";
import type { ChatItem, NavItem, PageUsage, Workspace } from "../types/layout.types";
import { LayoutShell } from "../ui/shell";
@ -28,15 +27,8 @@ export function FreeLayoutDataProvider({ children }: FreeLayoutDataProviderProps
const router = useRouter();
const { gate } = useLoginGate();
const anonMode = useAnonymousMode();
const isMobile = useIsMobile();
const { unreadCount: announcementUnreadCount } = useAnnouncements();
const [quota, setQuota] = useState<{ used: number; limit: number } | null>(null);
const [isDocsSidebarOpen, setIsDocsSidebarOpen] = useState(false);
// Keep docs sidebar closed on mobile; auto-open only on desktop after hydration
useEffect(() => {
setIsDocsSidebarOpen(!isMobile);
}, [isMobile]);
useEffect(() => {
anonymousChatApiService
@ -65,17 +57,9 @@ export function FreeLayoutDataProvider({ children }: FreeLayoutDataProviderProps
icon: Inbox,
isActive: false,
},
isMobile
? {
title: "Documents",
url: "#documents",
icon: LibraryBig,
isActive: false,
}
: null,
] as (NavItem | null)[]
).filter((item): item is NavItem => item !== null),
[isMobile]
[]
);
const pageUsage: PageUsage | undefined = quota
@ -87,7 +71,6 @@ export function FreeLayoutDataProvider({ children }: FreeLayoutDataProviderProps
const handleNavItemClick = useCallback(
(item: NavItem) => {
if (item.title === "Inbox") gate("use the inbox");
else if (item.title === "Documents") setIsDocsSidebarOpen((v) => !v);
},
[gate]
);
@ -127,10 +110,6 @@ export function FreeLayoutDataProvider({ children }: FreeLayoutDataProviderProps
pageUsage={pageUsage}
isChatPage
isLoadingChats={false}
documentsPanel={{
open: isDocsSidebarOpen,
onOpenChange: setIsDocsSidebarOpen,
}}
>
{children}
</LayoutShell>

View file

@ -1,18 +1,16 @@
"use client";
import { useQuery } from "@tanstack/react-query";
import { useAtom, useAtomValue, useSetAtom } from "jotai";
import { AlarmClock, AlertTriangle, Boxes, Inbox, LibraryBig } from "lucide-react";
import { useAtomValue, useSetAtom } from "jotai";
import { AlarmClock, AlertTriangle, Boxes, Inbox } from "lucide-react";
import { useParams, usePathname, useRouter } from "next/navigation";
import { useTranslations } from "next-intl";
import { useTheme } from "next-themes";
import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { toast } from "sonner";
import { currentThreadAtom, resetCurrentThreadAtom } from "@/atoms/chat/current-thread.atom";
import { documentsSidebarOpenAtom } from "@/atoms/documents/ui.atoms";
import { statusInboxItemsAtom } from "@/atoms/inbox/status-inbox.atom";
import { announcementsDialogAtom } from "@/atoms/layout/dialogs.atom";
import { rightPanelCollapsedAtom } from "@/atoms/layout/right-panel.atom";
import { removeChatTabAtom, syncChatTabAtom, type Tab } from "@/atoms/tabs/tabs.atom";
import { currentUserAtom } from "@/atoms/user/user-query.atoms";
import { deleteWorkspaceMutationAtom } from "@/atoms/workspaces/workspace-mutation.atoms";
@ -44,7 +42,6 @@ import { Spinner } from "@/components/ui/spinner";
import { useActivateChatThread } from "@/hooks/use-activate-chat-thread";
import { useAnnouncements } from "@/hooks/use-announcements";
import { useInbox } from "@/hooks/use-inbox";
import { useIsMobile } from "@/hooks/use-mobile";
import { useArchiveThread, useDeleteThread, useRenameThread } from "@/hooks/use-thread-mutations";
import { notificationsApiService } from "@/lib/apis/notifications-api.service";
import { workspacesApiService } from "@/lib/apis/workspaces-api.service";
@ -80,7 +77,6 @@ export function LayoutDataProvider({ workspaceId, children }: LayoutDataProvider
const params = useParams();
const pathname = usePathname();
const { theme, setTheme } = useTheme();
const isMobile = useIsMobile();
// Announcements
const { unreadCount: announcementUnreadCount } = useAnnouncements();
@ -131,21 +127,6 @@ export function LayoutDataProvider({ workspaceId, children }: LayoutDataProvider
const isInboxSidebarOpen = activeSlideoutPanel === "inbox";
// Documents sidebar state (shared atom so Composer can toggle it)
const [isDocumentsSidebarOpen, setIsDocumentsSidebarOpen] = useAtom(documentsSidebarOpenAtom);
// Open documents sidebar by default on desktop (docked mode)
const documentsInitialized = useRef(false);
useEffect(() => {
if (!documentsInitialized.current) {
documentsInitialized.current = true;
const isDesktop = typeof window !== "undefined" && window.innerWidth >= 768;
if (isDesktop) {
setIsDocumentsSidebarOpen(true);
}
}
}, [setIsDocumentsSidebarOpen]);
// Search space dialog state
const [isCreateWorkspaceDialogOpen, setIsCreateWorkspaceDialogOpen] = useState(false);
@ -361,20 +342,10 @@ export function LayoutDataProvider({ workspaceId, children }: LayoutDataProvider
icon: Boxes,
isActive: isArtifactsActive,
},
isMobile
? {
title: "Documents",
url: "#documents",
icon: LibraryBig,
isActive: isDocumentsSidebarOpen,
}
: null,
] as (NavItem | null)[]
).filter((item): item is NavItem => item !== null),
[
isMobile,
isInboxSidebarOpen,
isDocumentsSidebarOpen,
totalUnreadCount,
workspaceId,
isAutomationsActive,
@ -520,18 +491,9 @@ export function LayoutDataProvider({ workspaceId, children }: LayoutDataProvider
setActiveSlideoutPanel((prev) => (prev === "inbox" ? null : "inbox"));
return;
}
if (item.url === "#documents") {
setIsDocumentsSidebarOpen((prev) => {
if (!prev) {
setActiveSlideoutPanel(null);
}
return !prev;
});
return;
}
router.push(item.url);
},
[router, setIsDocumentsSidebarOpen]
[router]
);
const handleNewChat = useCallback(() => {
@ -799,10 +761,6 @@ export function LayoutDataProvider({ workspaceId, children }: LayoutDataProvider
markAllAsRead: statusInbox.markAllAsRead,
},
}}
documentsPanel={{
open: isDocumentsSidebarOpen,
onOpenChange: setIsDocumentsSidebarOpen,
}}
onTabSwitch={handleTabSwitch}
onTabPrefetch={handleTabPrefetch}
>

View file

@ -144,10 +144,6 @@ interface LayoutShellProps {
// Inbox props
inbox?: InboxProps;
isLoadingChats?: boolean;
documentsPanel?: {
open: boolean;
onOpenChange: (open: boolean) => void;
};
onTabSwitch?: (tab: Tab) => void;
onTabPrefetch?: (tab: Tab) => void;
}
@ -250,7 +246,6 @@ export function LayoutShell({
onSlideoutPanelChange,
inbox,
isLoadingChats = false,
documentsPanel,
onTabSwitch,
onTabPrefetch,
}: LayoutShellProps) {
@ -312,7 +307,6 @@ export function LayoutShell({
onChatArchive={onChatArchive}
onViewAllChats={onViewAllChats}
isAllChatsActive={isAllChatsPage}
documentsPanel={documentsPanel}
user={user}
onSettings={onSettings}
onManageMembers={onManageMembers}
@ -432,7 +426,6 @@ export function LayoutShell({
onChatArchive={onChatArchive}
onViewAllChats={onViewAllChats}
isAllChatsActive={isAllChatsPage}
documentsPanel={documentsPanel}
user={user}
onSettings={onSettings}
onManageMembers={onManageMembers}

View file

@ -28,10 +28,6 @@ interface MobileSidebarProps {
onChatArchive?: (chat: ChatItem) => void;
onViewAllChats?: () => void;
isAllChatsActive?: boolean;
documentsPanel?: {
open: boolean;
onOpenChange: (open: boolean) => void;
};
user: User;
onSettings?: () => void;
onManageMembers?: () => void;
@ -80,7 +76,6 @@ export function MobileSidebar({
onChatArchive,
onViewAllChats,
isAllChatsActive = false,
documentsPanel,
user,
onSettings,
onManageMembers,
@ -99,9 +94,6 @@ export function MobileSidebar({
const handleNavItemClick = (item: NavItem) => {
onNavItemClick?.(item);
if (item.url === "#documents") {
return;
}
onOpenChange(false);
};
@ -175,7 +167,6 @@ export function MobileSidebar({
: undefined
}
isAllChatsActive={isAllChatsActive}
documentsPanel={documentsPanel}
user={user}
onSettings={
onSettings

View file

@ -77,10 +77,6 @@ interface SidebarProps {
onChatArchive?: (chat: ChatItem) => void;
onViewAllChats?: () => void;
isAllChatsActive?: boolean;
documentsPanel?: {
open: boolean;
onOpenChange: (open: boolean) => void;
};
user: User;
onSettings?: () => void;
onManageMembers?: () => void;
@ -118,7 +114,6 @@ export function Sidebar({
onChatArchive,
onViewAllChats,
isAllChatsActive = false,
documentsPanel,
user,
onSettings,
onManageMembers,
@ -155,16 +150,11 @@ export function Sidebar({
() => navItems.find((item) => item.url.endsWith("/artifacts")),
[navItems]
);
const documentsItem = useMemo(
() => navItems.find((item) => item.url === "#documents"),
[navItems]
);
const footerNavItems = useMemo(
() =>
navItems.filter(
(item) =>
item.url !== "#inbox" &&
item.url !== "#documents" &&
!item.url.endsWith("/automations") &&
!item.url.endsWith("/artifacts")
),
@ -277,16 +267,6 @@ export function Sidebar({
tooltipContent={isCollapsed ? artifactsItem.title : undefined}
/>
)}
{documentsItem && (
<SidebarButton
icon={documentsItem.icon}
label={documentsItem.title}
onClick={() => onNavItemClick?.(documentsItem)}
isCollapsed={isCollapsed}
isActive={documentsItem.isActive}
tooltipContent={isCollapsed ? documentsItem.title : undefined}
/>
)}
</div>
{/* Chat sections - fills available space */}
@ -344,11 +324,9 @@ export function Sidebar({
<p className="px-2 py-1 text-sm text-muted-foreground/60">{t("no_chats")}</p>
)}
</SidebarSection>
{documentsPanel?.open ? (
<div className="min-h-0 flex flex-1 flex-col">
<DocumentsSidebar embedded />
</div>
) : null}
<div className="min-h-0 flex flex-1 flex-col">
<DocumentsSidebar embedded />
</div>
</div>
)}
</div>

View file

@ -1,7 +1,7 @@
"use client";
import { useAtom, useAtomValue } from "jotai";
import { Check, ChevronDown, ImagePlus, Search, SlidersHorizontal } from "lucide-react";
import { Check, ChevronDown, Search, SlidersHorizontal } from "lucide-react";
import { useRouter } from "next/navigation";
import type { UIEvent } from "react";
import { useCallback, useMemo, useState } from "react";
@ -268,11 +268,9 @@ export function ImageModelSelector({
showIconOnlyTrigger && "h-9 w-auto shrink-0 justify-center gap-1 px-2"
)}
>
{selected ? (
getProviderIcon(selected.provider, { className: "size-4 shrink-0" })
) : (
<ImagePlus className="size-4 shrink-0" />
)}
{selected
? getProviderIcon(selected.provider, { className: "size-4 shrink-0" })
: getProviderIcon(AUTO_PROVIDER_ICON_KEY, { className: "size-4 shrink-0" })}
{showIconOnlyTrigger ? null : (
<span className="min-w-0 flex-1 truncate text-sm">
{selected ? modelName(selected) : "Auto"}