improve ux overflow with sidebar (#79)

This commit is contained in:
Will Chen
2025-05-02 16:29:51 -07:00
committed by GitHub
parent 30662118d7
commit 0108ff1a82
3 changed files with 19 additions and 5 deletions

4
src/atoms/uiAtoms.ts Normal file
View File

@@ -0,0 +1,4 @@
import { atom } from "jotai";
// Atom to track if any dropdown is currently open in the UI
export const dropdownOpenAtom = atom<boolean>(false);

View File

@@ -6,6 +6,7 @@ import { PlusCircle, MoreVertical, Trash2 } from "lucide-react";
import { useAtom } from "jotai"; import { useAtom } from "jotai";
import { selectedChatIdAtom } from "@/atoms/chatAtoms"; import { selectedChatIdAtom } from "@/atoms/chatAtoms";
import { selectedAppIdAtom } from "@/atoms/appAtoms"; import { selectedAppIdAtom } from "@/atoms/appAtoms";
import { dropdownOpenAtom } from "@/atoms/uiAtoms";
import { IpcClient } from "@/ipc/ipc_client"; import { IpcClient } from "@/ipc/ipc_client";
import { showError, showSuccess } from "@/lib/toast"; import { showError, showSuccess } from "@/lib/toast";
import { import {
@@ -28,6 +29,7 @@ export function ChatList({ show }: { show?: boolean }) {
const navigate = useNavigate(); const navigate = useNavigate();
const [selectedChatId, setSelectedChatId] = useAtom(selectedChatIdAtom); const [selectedChatId, setSelectedChatId] = useAtom(selectedChatIdAtom);
const [selectedAppId, setSelectedAppId] = useAtom(selectedAppIdAtom); const [selectedAppId, setSelectedAppId] = useAtom(selectedAppIdAtom);
const [isDropdownOpen, setIsDropdownOpen] = useAtom(dropdownOpenAtom);
const { chats, loading, refreshChats } = useChats(selectedAppId); const { chats, loading, refreshChats } = useChats(selectedAppId);
const routerState = useRouterState(); const routerState = useRouterState();
const isChatRoute = routerState.location.pathname === "/chat"; const isChatRoute = routerState.location.pathname === "/chat";
@@ -136,7 +138,7 @@ export function ChatList({ show }: { show?: boolean }) {
<SidebarMenu className="space-y-1"> <SidebarMenu className="space-y-1">
{chats.map((chat) => ( {chats.map((chat) => (
<SidebarMenuItem key={chat.id} className="mb-1"> <SidebarMenuItem key={chat.id} className="mb-1">
<div className="flex w-[185px] items-center"> <div className="flex w-[175px] items-center">
<Button <Button
variant="ghost" variant="ghost"
onClick={() => onClick={() =>
@@ -161,7 +163,9 @@ export function ChatList({ show }: { show?: boolean }) {
</Button> </Button>
{selectedChatId === chat.id && ( {selectedChatId === chat.id && (
<DropdownMenu> <DropdownMenu
onOpenChange={(open) => setIsDropdownOpen(open)}
>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button <Button
variant="ghost" variant="ghost"

View File

@@ -2,6 +2,8 @@ import { Home, Inbox, Settings, HelpCircle } from "lucide-react";
import { Link, useRouterState } from "@tanstack/react-router"; import { Link, useRouterState } from "@tanstack/react-router";
import { useSidebar } from "@/components/ui/sidebar"; // import useSidebar hook import { useSidebar } from "@/components/ui/sidebar"; // import useSidebar hook
import { useEffect, useState, useRef } from "react"; import { useEffect, useState, useRef } from "react";
import { useAtom } from "jotai";
import { dropdownOpenAtom } from "@/atoms/uiAtoms";
import { import {
Sidebar, Sidebar,
@@ -50,6 +52,7 @@ export function AppSidebar() {
const [hoverState, setHoverState] = useState<HoverState>("no-hover"); const [hoverState, setHoverState] = useState<HoverState>("no-hover");
const expandedByHover = useRef(false); const expandedByHover = useRef(false);
const [isHelpDialogOpen, setIsHelpDialogOpen] = useState(false); // State for dialog const [isHelpDialogOpen, setIsHelpDialogOpen] = useState(false); // State for dialog
const [isDropdownOpen] = useAtom(dropdownOpenAtom);
useEffect(() => { useEffect(() => {
if ( if (
@@ -62,13 +65,14 @@ export function AppSidebar() {
if ( if (
hoverState === "clear-hover" && hoverState === "clear-hover" &&
state === "expanded" && state === "expanded" &&
expandedByHover.current expandedByHover.current &&
!isDropdownOpen
) { ) {
toggleSidebar(); toggleSidebar();
expandedByHover.current = false; expandedByHover.current = false;
setHoverState("no-hover"); setHoverState("no-hover");
} }
}, [hoverState, toggleSidebar, state, setHoverState]); }, [hoverState, toggleSidebar, state, setHoverState, isDropdownOpen]);
const routerState = useRouterState(); const routerState = useRouterState();
const isAppRoute = const isAppRoute =
@@ -93,7 +97,9 @@ export function AppSidebar() {
<Sidebar <Sidebar
collapsible="icon" collapsible="icon"
onMouseLeave={() => { onMouseLeave={() => {
if (!isDropdownOpen) {
setHoverState("clear-hover"); setHoverState("clear-hover");
}
}} }}
> >
<SidebarContent className="overflow-hidden"> <SidebarContent className="overflow-hidden">