This commit is contained in:
DESKTOP-RTLN3BA\$punk 2025-12-28 15:54:10 -08:00
commit 35904ba0c8
43 changed files with 1019 additions and 663 deletions

View file

@ -42,9 +42,15 @@ interface AllChatsSidebarProps {
open: boolean;
onOpenChange: (open: boolean) => void;
searchSpaceId: string;
onCloseMobileSidebar?: () => void;
}
export function AllChatsSidebar({ open, onOpenChange, searchSpaceId }: AllChatsSidebarProps) {
export function AllChatsSidebar({
open,
onOpenChange,
searchSpaceId,
onCloseMobileSidebar,
}: AllChatsSidebarProps) {
const t = useTranslations("sidebar");
const router = useRouter();
const params = useParams();
@ -61,6 +67,7 @@ export function AllChatsSidebar({ open, onOpenChange, searchSpaceId }: AllChatsS
const [searchQuery, setSearchQuery] = useState("");
const [showArchived, setShowArchived] = useState(false);
const [mounted, setMounted] = useState(false);
const [openDropdownId, setOpenDropdownId] = useState<number | null>(null);
const debouncedSearchQuery = useDebouncedValue(searchQuery, 300);
const isSearchMode = !!debouncedSearchQuery.trim();
@ -120,8 +127,10 @@ export function AllChatsSidebar({ open, onOpenChange, searchSpaceId }: AllChatsS
(threadId: number) => {
router.push(`/dashboard/${searchSpaceId}/new-chat/${threadId}`);
onOpenChange(false);
// Also close the main sidebar on mobile
onCloseMobileSidebar?.();
},
[router, onOpenChange, searchSpaceId]
[router, onOpenChange, searchSpaceId, onCloseMobileSidebar]
);
// Handle thread deletion
@ -209,7 +218,7 @@ export function AllChatsSidebar({ open, onOpenChange, searchSpaceId }: AllChatsS
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
className="fixed inset-0 z-50 bg-black/50"
className="fixed inset-0 z-[70] bg-black/50"
onClick={() => onOpenChange(false)}
aria-hidden="true"
/>
@ -220,7 +229,7 @@ export function AllChatsSidebar({ open, onOpenChange, searchSpaceId }: AllChatsS
animate={{ x: 0 }}
exit={{ x: "-100%" }}
transition={{ type: "spring", damping: 25, stiffness: 300 }}
className="fixed inset-y-0 left-0 z-50 w-80 bg-background shadow-xl flex flex-col"
className="fixed inset-y-0 left-0 z-[70] w-80 bg-background shadow-xl flex flex-col pointer-events-auto isolate"
role="dialog"
aria-modal="true"
aria-label={t("all_chats") || "All Chats"}
@ -345,14 +354,17 @@ export function AllChatsSidebar({ open, onOpenChange, searchSpaceId }: AllChatsS
</Tooltip>
{/* Actions dropdown */}
<DropdownMenu>
<DropdownMenu
open={openDropdownId === thread.id}
onOpenChange={(isOpen) => setOpenDropdownId(isOpen ? thread.id : null)}
>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
className={cn(
"h-6 w-6 shrink-0",
"opacity-0 group-hover:opacity-100 focus:opacity-100",
"md:opacity-0 md:group-hover:opacity-100 md:focus:opacity-100",
"transition-opacity"
)}
disabled={isBusy}
@ -365,7 +377,7 @@ export function AllChatsSidebar({ open, onOpenChange, searchSpaceId }: AllChatsS
<span className="sr-only">{t("more_options") || "More options"}</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-40">
<DropdownMenuContent align="end" className="w-40 z-[80]">
<DropdownMenuItem
onClick={() => handleToggleArchive(thread.id, thread.archived)}
disabled={isArchiving}

View file

@ -27,6 +27,7 @@ interface AllNotesSidebarProps {
onOpenChange: (open: boolean) => void;
searchSpaceId: string;
onAddNote?: () => void;
onCloseMobileSidebar?: () => void;
}
export function AllNotesSidebar({
@ -34,6 +35,7 @@ export function AllNotesSidebar({
onOpenChange,
searchSpaceId,
onAddNote,
onCloseMobileSidebar,
}: AllNotesSidebarProps) {
const t = useTranslations("sidebar");
const router = useRouter();
@ -45,6 +47,7 @@ export function AllNotesSidebar({
const [deletingNoteId, setDeletingNoteId] = useState<number | null>(null);
const [searchQuery, setSearchQuery] = useState("");
const [mounted, setMounted] = useState(false);
const [openDropdownId, setOpenDropdownId] = useState<number | null>(null);
const debouncedSearchQuery = useDebouncedValue(searchQuery, 300);
// Handle mounting for portal
@ -114,8 +117,10 @@ export function AllNotesSidebar({
(noteId: number, noteSearchSpaceId: number) => {
router.push(`/dashboard/${noteSearchSpaceId}/editor/${noteId}`);
onOpenChange(false);
// Also close the main sidebar on mobile
onCloseMobileSidebar?.();
},
[router, onOpenChange]
[router, onOpenChange, onCloseMobileSidebar]
);
// Handle note deletion
@ -195,7 +200,7 @@ export function AllNotesSidebar({
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
className="fixed inset-0 z-50 bg-black/50"
className="fixed inset-0 z-[70] bg-black/50"
onClick={() => onOpenChange(false)}
aria-hidden="true"
/>
@ -206,7 +211,7 @@ export function AllNotesSidebar({
animate={{ x: 0 }}
exit={{ x: "-100%" }}
transition={{ type: "spring", damping: 25, stiffness: 300 }}
className="fixed inset-y-0 left-0 z-50 w-80 bg-background shadow-xl flex flex-col"
className="fixed inset-y-0 left-0 z-[70] w-80 bg-background shadow-xl flex flex-col pointer-events-auto isolate"
role="dialog"
aria-modal="true"
aria-label={t("all_notes") || "All Notes"}
@ -307,14 +312,17 @@ export function AllNotesSidebar({
</Tooltip>
{/* Actions dropdown - separate from main click area */}
<DropdownMenu>
<DropdownMenu
open={openDropdownId === note.id}
onOpenChange={(isOpen) => setOpenDropdownId(isOpen ? note.id : null)}
>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
className={cn(
"h-6 w-6 shrink-0",
"opacity-0 group-hover:opacity-100 focus:opacity-100",
"md:opacity-0 md:group-hover:opacity-100 md:focus:opacity-100",
"transition-opacity"
)}
disabled={isDeleting}
@ -327,7 +335,7 @@ export function AllNotesSidebar({
<span className="sr-only">{t("more_options") || "More options"}</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-40">
<DropdownMenuContent align="end" className="w-40 z-[80]">
<DropdownMenuItem
onClick={() => handleDeleteNote(note.id, note.search_space_id)}
className="text-destructive focus:text-destructive"

View file

@ -28,6 +28,7 @@ import {
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
useSidebar,
} from "@/components/ui/sidebar";
import { useIsMobile } from "@/hooks/use-mobile";
import { cn } from "@/lib/utils";
@ -73,6 +74,7 @@ export function NavChats({
const router = useRouter();
const pathname = usePathname();
const isMobile = useIsMobile();
const { setOpenMobile } = useSidebar();
const [isDeleting, setIsDeleting] = useState<number | null>(null);
const [isOpen, setIsOpen] = useState(defaultOpen);
const [isAllChatsSidebarOpen, setIsAllChatsSidebarOpen] = useState(false);
@ -119,7 +121,7 @@ export function NavChats({
</CollapsibleTrigger>
{/* Action buttons - always visible on hover */}
<div className="flex items-center gap-0.5 opacity-0 group-hover/header:opacity-100 transition-opacity pr-1">
<div className="flex items-center gap-0.5 md:opacity-0 md:group-hover/header:opacity-100 transition-opacity pr-1">
{searchSpaceId && chats.length > 0 && (
<Button
variant="ghost"
@ -171,7 +173,7 @@ export function NavChats({
size="icon"
className={cn(
"h-6 w-6",
"opacity-0 group-hover/chat:opacity-100 focus:opacity-100",
"md:opacity-0 md:group-hover/chat:opacity-100 md:focus:opacity-100",
"data-[state=open]:opacity-100",
"transition-opacity"
)}
@ -242,6 +244,7 @@ export function NavChats({
open={isAllChatsSidebarOpen}
onOpenChange={setIsAllChatsSidebarOpen}
searchSpaceId={searchSpaceId}
onCloseMobileSidebar={() => setOpenMobile(false)}
/>
)}
</SidebarGroup>

View file

@ -28,6 +28,7 @@ import {
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
useSidebar,
} from "@/components/ui/sidebar";
import { useLogsSummary } from "@/hooks/use-logs";
import { useIsMobile } from "@/hooks/use-mobile";
@ -75,6 +76,7 @@ export function NavNotes({
const router = useRouter();
const pathname = usePathname();
const isMobile = useIsMobile();
const { setOpenMobile } = useSidebar();
const [isDeleting, setIsDeleting] = useState<number | null>(null);
const [isOpen, setIsOpen] = useState(defaultOpen);
const [isAllNotesSidebarOpen, setIsAllNotesSidebarOpen] = useState(false);
@ -138,7 +140,7 @@ export function NavNotes({
</CollapsibleTrigger>
{/* Action buttons - always visible on hover */}
<div className="flex items-center gap-0.5 opacity-0 group-hover/header:opacity-100 transition-opacity pr-1">
<div className="flex items-center gap-0.5 md:opacity-0 md:group-hover/header:opacity-100 transition-opacity pr-1">
{searchSpaceId && notes.length > 0 && (
<Button
variant="ghost"
@ -209,7 +211,7 @@ export function NavNotes({
size="icon"
className={cn(
"h-6 w-6",
"opacity-0 group-hover/note:opacity-100 focus:opacity-100",
"md:opacity-0 md:group-hover/note:opacity-100 md:focus:opacity-100",
"data-[state=open]:opacity-100",
"transition-opacity"
)}
@ -293,6 +295,7 @@ export function NavNotes({
onOpenChange={setIsAllNotesSidebarOpen}
searchSpaceId={searchSpaceId}
onAddNote={onAddNote}
onCloseMobileSidebar={() => setOpenMobile(false)}
/>
)}
</SidebarGroup>