+ {/* Search bar */}
+ {showSearch && (
+
+
+ setSearchQuery(e.target.value)}
+ placeholder="Search in document..."
+ className="flex-1 h-8"
+ autoFocus
+ />
+ {matches.length > 0 ? (
+ <>
+
+
+ {currentMatchIndex + 1} of {matches.length}
+
+
+ >
+ ) : searchQuery.trim() ? (
+ No matches
+ ) : null}
+
+
+ )}
+
+ {/* Scrollable PDF pages */}
+
+ {loading && (
+
+
+
+ )}
+
+ {error && (
+
+
Failed to load PDF: {error}
+
+ )}
+
+
+
+ {Array.from({ length: numPages }, (_, i) => (
+
{
+ if (el) pageRefs.current.set(i + 1, el)
+ }}
+ data-page={i + 1}
+ className="shadow-lg"
+ >
+
+
+
+ }
+ />
+
+ ))}
+
+
+
+
+ {/* Bottom toolbar */}
+ {numPages > 0 && (
+
+ {/* Search button */}
+
+
+
+
+ {/* Page navigation */}
+
+
+
+ Page
+
+ of {numPages}
+
+
+
+
+
+
+ {/* Zoom controls */}
+
+
{Math.round(scale * 100)}%
+
+
+ {/* Fit to width */}
+
+
+
+
+ {/* Fullscreen toggle */}
+
+
+ )}
+
+ )
+}
diff --git a/lightrag_webui/src/components/ui/Resizable.tsx b/lightrag_webui/src/components/ui/Resizable.tsx
new file mode 100644
index 00000000..97463fa9
--- /dev/null
+++ b/lightrag_webui/src/components/ui/Resizable.tsx
@@ -0,0 +1,40 @@
+import { GripVertical } from 'lucide-react'
+import * as ResizablePrimitive from 'react-resizable-panels'
+
+import { cn } from '@/lib/utils'
+
+const ResizablePanelGroup = ({
+ className,
+ ...props
+}: React.ComponentProps