"use client"; import { AnimatePresence, motion } from "motion/react"; import { useEffect } from "react"; import { useMediaQuery } from "@/hooks/use-media-query"; import { cn } from "@/lib/utils"; import { useSidebarContextSafe } from "../../hooks"; export const SLIDEOUT_PANEL_OPENED_EVENT = "slideout-panel-opened"; const SIDEBAR_COLLAPSED_WIDTH = 60; interface SidebarSlideOutPanelProps { open: boolean; onOpenChange: (open: boolean) => void; ariaLabel: string; width?: number; children: React.ReactNode; } /** * Reusable slide-out panel that appears from the right edge of the sidebar. * Used by InboxSidebar (floating mode), AllSharedChatsSidebar, and AllPrivateChatsSidebar. * * Must be rendered inside a positioned container (the LayoutShell's relative flex container) * and within the SidebarProvider context. */ export function SidebarSlideOutPanel({ open, onOpenChange, ariaLabel, width = 360, children, }: SidebarSlideOutPanelProps) { const isMobile = !useMediaQuery("(min-width: 640px)"); const sidebarContext = useSidebarContextSafe(); const isCollapsed = sidebarContext?.isCollapsed ?? false; const sidebarWidth = isCollapsed ? SIDEBAR_COLLAPSED_WIDTH : (sidebarContext?.sidebarWidth ?? 240); useEffect(() => { if (open) { window.dispatchEvent(new Event(SLIDEOUT_PANEL_OPENED_EVENT)); } }, [open]); return ( {open && ( <> {/* Backdrop overlay with blur — only covers the main content area (right of sidebar) */} onOpenChange(false)} aria-hidden="true" /> {/* Clip container - positioned at sidebar edge with overflow hidden */}
{children}
)}
); }