diff --git a/apps/web/src/components/Sidebar.logic.test.ts b/apps/web/src/components/Sidebar.logic.test.ts index 19d6f3060..2f4f1efd6 100644 --- a/apps/web/src/components/Sidebar.logic.test.ts +++ b/apps/web/src/components/Sidebar.logic.test.ts @@ -6,6 +6,7 @@ import { resolveSidebarNewThreadEnvMode, resolveThreadRowClassName, resolveThreadStatusPill, + shouldHideSidebarAfterThreadAction, shouldClearThreadSelectionOnMouseDown, } from "./Sidebar.logic"; @@ -84,6 +85,16 @@ describe("resolveSidebarNewThreadEnvMode", () => { }); }); +describe("shouldHideSidebarAfterThreadAction", () => { + it("hides the sidebar after thread actions on mobile", () => { + expect(shouldHideSidebarAfterThreadAction(true)).toBe(true); + }); + + it("keeps the sidebar open after thread actions on desktop", () => { + expect(shouldHideSidebarAfterThreadAction(false)).toBe(false); + }); +}); + describe("resolveThreadStatusPill", () => { const baseThread = { interactionMode: "plan" as const, diff --git a/apps/web/src/components/Sidebar.logic.ts b/apps/web/src/components/Sidebar.logic.ts index ef338dab6..aaf393000 100644 --- a/apps/web/src/components/Sidebar.logic.ts +++ b/apps/web/src/components/Sidebar.logic.ts @@ -59,6 +59,10 @@ export function resolveSidebarNewThreadEnvMode(input: { return input.requestedEnvMode ?? input.defaultEnvMode; } +export function shouldHideSidebarAfterThreadAction(isMobile: boolean): boolean { + return isMobile; +} + export function resolveThreadRowClassName(input: { isActive: boolean; isSelected: boolean; diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx index 9ff741897..8ecd5a7c5 100644 --- a/apps/web/src/components/Sidebar.tsx +++ b/apps/web/src/components/Sidebar.tsx @@ -88,9 +88,11 @@ import { resolveSidebarNewThreadEnvMode, resolveThreadRowClassName, resolveThreadStatusPill, + shouldHideSidebarAfterThreadAction, shouldClearThreadSelectionOnMouseDown, } from "./Sidebar.logic"; import { useCopyToClipboard } from "~/hooks/useCopyToClipboard"; +import { useSidebar } from "~/components/ui/sidebar"; const EMPTY_KEYBINDINGS: ResolvedKeybindingsConfig = []; const THREAD_PREVIEW_LIMIT = 6; @@ -253,6 +255,7 @@ function SortableProjectItem({ } export default function Sidebar() { + const { isMobile, setOpenMobile } = useSidebar(); const projects = useStore((store) => store.projects); const threads = useStore((store) => store.threads); const markThreadUnread = useStore((store) => store.markThreadUnread); @@ -383,6 +386,13 @@ export default function Sidebar() { }); }, []); + const hideSidebarAfterThreadAction = useCallback(() => { + if (!shouldHideSidebarAfterThreadAction(isMobile)) { + return; + } + setOpenMobile(false); + }, [isMobile, setOpenMobile]); + const focusMostRecentThreadForProject = useCallback( (projectId: ProjectId) => { const latestThread = threads @@ -844,6 +854,7 @@ export default function Sidebar() { clearSelection(); } setSelectionAnchor(threadId); + hideSidebarAfterThreadAction(); void navigate({ to: "/$threadId", params: { threadId }, @@ -855,6 +866,7 @@ export default function Sidebar() { rangeSelectTo, selectedThreadIds.size, setSelectionAnchor, + hideSidebarAfterThreadAction, toggleThreadSelection, ], ); @@ -1424,6 +1436,7 @@ export default function Sidebar() { onClick={(event) => { event.preventDefault(); event.stopPropagation(); + hideSidebarAfterThreadAction(); void handleNewThread(project.id, { envMode: resolveSidebarNewThreadEnvMode({ defaultEnvMode: appSettings.defaultThreadEnvMode, @@ -1492,6 +1505,7 @@ export default function Sidebar() { clearSelection(); } setSelectionAnchor(thread.id); + hideSidebarAfterThreadAction(); void navigate({ to: "/$threadId", params: { threadId: thread.id },