mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 00:36:31 +02:00
feat: implement docked mode for DocumentsSidebar with toggle functionality; enhance LayoutDataProvider and LayoutShell to support new state management
This commit is contained in:
parent
74c95ee61f
commit
2608870ae6
4 changed files with 79 additions and 5 deletions
|
|
@ -119,6 +119,19 @@ export function LayoutDataProvider({ searchSpaceId, children }: LayoutDataProvid
|
|||
|
||||
// Documents sidebar state (shared atom so Composer can toggle it)
|
||||
const [isDocumentsSidebarOpen, setIsDocumentsSidebarOpen] = useAtom(documentsSidebarOpenAtom);
|
||||
const [isDocumentsDocked, setIsDocumentsDocked] = useState(true);
|
||||
|
||||
// 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]);
|
||||
|
||||
// Announcements sidebar state
|
||||
const [isAnnouncementsSidebarOpen, setIsAnnouncementsSidebarOpen] = useState(false);
|
||||
|
|
@ -678,6 +691,8 @@ export function LayoutDataProvider({ searchSpaceId, children }: LayoutDataProvid
|
|||
documentsPanel={{
|
||||
open: isDocumentsSidebarOpen,
|
||||
onOpenChange: setIsDocumentsSidebarOpen,
|
||||
isDocked: isDocumentsDocked,
|
||||
onDockedChange: setIsDocumentsDocked,
|
||||
}}
|
||||
>
|
||||
<Fragment key={chatResetKey}>{children}</Fragment>
|
||||
|
|
|
|||
|
|
@ -97,6 +97,8 @@ interface LayoutShellProps {
|
|||
documentsPanel?: {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
isDocked?: boolean;
|
||||
onDockedChange?: (docked: boolean) => void;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -319,6 +321,16 @@ export function LayoutShell({
|
|||
/>
|
||||
)}
|
||||
|
||||
{/* Docked Documents Sidebar - renders as flex sibling between sidebar and content */}
|
||||
{documentsPanel?.isDocked && (
|
||||
<DocumentsSidebar
|
||||
open={documentsPanel.open}
|
||||
onOpenChange={documentsPanel.onOpenChange}
|
||||
isDocked={documentsPanel.isDocked}
|
||||
onDockedChange={documentsPanel.onDockedChange}
|
||||
/>
|
||||
)}
|
||||
|
||||
<main className="flex-1 flex flex-col min-w-0">
|
||||
<Header />
|
||||
|
||||
|
|
@ -340,11 +352,13 @@ export function LayoutShell({
|
|||
/>
|
||||
)}
|
||||
|
||||
{/* Documents Sidebar - slide-out panel */}
|
||||
{documentsPanel && (
|
||||
{/* Documents Sidebar - floating slide-out panel (non-docked mode) */}
|
||||
{documentsPanel && !documentsPanel.isDocked && (
|
||||
<DocumentsSidebar
|
||||
open={documentsPanel.open}
|
||||
onOpenChange={documentsPanel.onOpenChange}
|
||||
isDocked={false}
|
||||
onDockedChange={documentsPanel.onDockedChange}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { useAtom, useAtomValue } from "jotai";
|
||||
import { ChevronLeft } from "lucide-react";
|
||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||
import { useParams } from "next/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
|
|
@ -14,6 +14,7 @@ import {
|
|||
import { sidebarSelectedDocumentsAtom } from "@/atoms/chat/mentioned-documents.atom";
|
||||
import { deleteDocumentMutationAtom } from "@/atoms/documents/document-mutation.atoms";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import type { DocumentTypeEnum } from "@/contracts/types/document.types";
|
||||
import { useDebouncedValue } from "@/hooks/use-debounced-value";
|
||||
import { useDocumentSearch } from "@/hooks/use-document-search";
|
||||
|
|
@ -24,9 +25,11 @@ import { SidebarSlideOutPanel } from "./SidebarSlideOutPanel";
|
|||
interface DocumentsSidebarProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
isDocked?: boolean;
|
||||
onDockedChange?: (docked: boolean) => void;
|
||||
}
|
||||
|
||||
export function DocumentsSidebar({ open, onOpenChange }: DocumentsSidebarProps) {
|
||||
export function DocumentsSidebar({ open, onOpenChange, isDocked = false, onDockedChange }: DocumentsSidebarProps) {
|
||||
const t = useTranslations("documents");
|
||||
const tSidebar = useTranslations("sidebar");
|
||||
const params = useParams();
|
||||
|
|
@ -164,6 +167,37 @@ export function DocumentsSidebar({ open, onOpenChange }: DocumentsSidebarProps)
|
|||
)}
|
||||
<h2 className="text-lg font-semibold">{t("title") || "Documents"}</h2>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
{!isMobile && onDockedChange && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-8 w-8 rounded-full"
|
||||
onClick={() => {
|
||||
if (isDocked) {
|
||||
onDockedChange(false);
|
||||
onOpenChange(false);
|
||||
} else {
|
||||
onDockedChange(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isDocked ? (
|
||||
<ChevronLeft className="h-4 w-4 text-muted-foreground" />
|
||||
) : (
|
||||
<ChevronRight className="h-4 w-4 text-muted-foreground" />
|
||||
)}
|
||||
<span className="sr-only">{isDocked ? "Collapse panel" : "Expand panel"}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="z-80">
|
||||
{isDocked ? "Collapse panel" : "Expand panel"}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -199,6 +233,17 @@ export function DocumentsSidebar({ open, onOpenChange }: DocumentsSidebarProps)
|
|||
</>
|
||||
);
|
||||
|
||||
if (isDocked && open && !isMobile) {
|
||||
return (
|
||||
<aside
|
||||
className="h-full w-[480px] shrink-0 bg-sidebar text-sidebar-foreground flex flex-col border-r"
|
||||
aria-label={t("title") || "Documents"}
|
||||
>
|
||||
{documentsContent}
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SidebarSlideOutPanel
|
||||
open={open}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ function DropdownMenuSeparator({
|
|||
return (
|
||||
<DropdownMenuPrimitive.Separator
|
||||
data-slot="dropdown-menu-separator"
|
||||
className={cn("bg-border dark:bg-neutral-700 -mx-1 my-1 h-px", className)}
|
||||
className={cn("bg-border mx-2 my-1 h-px", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue