diff --git a/frontend/src/renderer/components/Sidebar.test.tsx b/frontend/src/renderer/components/Sidebar.test.tsx
index cd71be74..8c26c235 100644
--- a/frontend/src/renderer/components/Sidebar.test.tsx
+++ b/frontend/src/renderer/components/Sidebar.test.tsx
@@ -1,6 +1,5 @@
import { SidebarProvider } from "@/components/ui/sidebar";
-import { render, screen, waitFor } from "@testing-library/react";
-import userEvent from "@testing-library/user-event";
+import { render, screen } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { Sidebar } from "./Sidebar";
import type { WorkspaceSummary } from "../types/workspace";
@@ -25,24 +24,20 @@ const workspace: WorkspaceSummary = {
sessions: [],
};
-function renderSidebar(onRemoveProject = vi.fn().mockResolvedValue(undefined)) {
+function renderSidebar() {
render(
,
);
- return onRemoveProject;
}
beforeEach(() => {
navigateMock.mockReset();
- vi.spyOn(window, "confirm").mockReturnValue(true);
- vi.spyOn(window, "alert").mockImplementation(() => undefined);
});
afterEach(() => {
@@ -50,30 +45,6 @@ afterEach(() => {
});
describe("Sidebar", () => {
- it("confirms project removal before calling the remove handler", async () => {
- const user = userEvent.setup();
- const onRemoveProject = renderSidebar();
-
- await user.click(screen.getByLabelText("Project actions for Project One"));
- await user.click(await screen.findByRole("menuitem", { name: "Remove project" }));
-
- expect(window.confirm).toHaveBeenCalledWith(
- "Remove project Project One? This stops its live sessions and removes it from the sidebar, but keeps the repository folder and stored history on disk.",
- );
- await waitFor(() => expect(onRemoveProject).toHaveBeenCalledTimes(1));
- });
-
- it("does not remove the project when confirmation is cancelled", async () => {
- vi.mocked(window.confirm).mockReturnValue(false);
- const user = userEvent.setup();
- const onRemoveProject = renderSidebar();
-
- await user.click(screen.getByLabelText("Project actions for Project One"));
- await user.click(await screen.findByRole("menuitem", { name: "Remove project" }));
-
- expect(onRemoveProject).not.toHaveBeenCalled();
- });
-
it("hides the worker count in every state that reveals project actions", () => {
renderSidebar();
diff --git a/frontend/src/renderer/components/Sidebar.tsx b/frontend/src/renderer/components/Sidebar.tsx
index affc9e1a..0397ee67 100644
--- a/frontend/src/renderer/components/Sidebar.tsx
+++ b/frontend/src/renderer/components/Sidebar.tsx
@@ -1,16 +1,5 @@
import { useNavigate, useParams, useRouterState } from "@tanstack/react-router";
-import {
- ChevronRight,
- GitPullRequest,
- Moon,
- MoreHorizontal,
- Plus,
- Search,
- Settings,
- Sun,
- Trash2,
- Waypoints,
-} from "lucide-react";
+import { ChevronRight, GitPullRequest, Moon, Plus, Search, Settings, Sun, Waypoints } from "lucide-react";
import { useState } from "react";
import {
attentionZone,
@@ -377,25 +366,6 @@ function ProjectItem({
}
};
- const removeProject = async () => {
- setRemoveError(null);
- const confirmed = window.confirm(
- `Remove project ${workspace.name}? This stops its live sessions and removes it from the sidebar, but keeps the repository folder and stored history on disk.`,
- );
- if (!confirmed) return;
-
- setIsRemoving(true);
- try {
- await onRemoveProject();
- } catch (err) {
- const message = err instanceof Error ? err.message : "Could not remove project";
- setRemoveError(message);
- window.alert(message);
- } finally {
- setIsRemoving(false);
- }
- };
-
return (
{/* project-sidebar__proj-row */}
diff --git a/frontend/src/renderer/routes/_shell.tsx b/frontend/src/renderer/routes/_shell.tsx
index 65674f44..9c2bbbcb 100644
--- a/frontend/src/renderer/routes/_shell.tsx
+++ b/frontend/src/renderer/routes/_shell.tsx
@@ -1,6 +1,6 @@
-import { createFileRoute, Outlet, useNavigate, useParams } from "@tanstack/react-router";
+import { createFileRoute, Outlet, useNavigate } from "@tanstack/react-router";
import { useQueryClient } from "@tanstack/react-query";
-import { useCallback, useEffect, useState } from "react";
+import { type CSSProperties, useCallback, useEffect } from "react";
import { ShellTopbar } from "../components/ShellTopbar";
import { Sidebar } from "../components/Sidebar";
import { SidebarProvider } from "../components/ui/sidebar";
@@ -34,7 +34,6 @@ function errorMessage(error: unknown) {
// instead of Zustand. The daemon-status effect runs here exactly once.
function ShellLayout() {
const navigate = useNavigate();
- const params = useParams({ strict: false }) as { projectId?: string };
const queryClient = useQueryClient();
const workspaceQuery = useWorkspaceQuery();
const workspaces = workspaceQuery.data ?? [];
@@ -67,20 +66,6 @@ function ShellLayout() {
[navigate, updateWorkspaces],
);
- const removeProject = useCallback(
- async (projectId: string) => {
- const { error } = await apiClient.DELETE("/api/v1/projects/{id}", { params: { path: { id: projectId } } });
- if (error) throw new Error(apiErrorMessage(error));
-
- updateWorkspaces((current) => current.filter((item) => item.id !== projectId));
- await queryClient.invalidateQueries({ queryKey: workspaceQueryKey });
- if (params.projectId === projectId) {
- void navigate({ to: "/" });
- }
- },
- [navigate, params.projectId, queryClient, updateWorkspaces],
- );
-
useEffect(() => {
document.documentElement.dataset.theme = theme;
document.documentElement.style.colorScheme = theme;
@@ -113,7 +98,7 @@ function ShellLayout() {
}, [navigate, workspaces]);
return (
-
+
{/* The topbar spans the full window width above the sidebar row (the
macOS traffic lights + TitlebarNav cluster sit in its left inset),
and the sidebar hangs below it — so the sidebar border stops at the
@@ -130,7 +115,7 @@ function ShellLayout() {
onOpenChange={(open) => open !== isSidebarOpen && toggleSidebar()}
open={isSidebarOpen}
style={
- { "--sidebar-width": "var(--ao-sidebar-w, 240px)", "--sidebar-width-icon": "48px" } as React.CSSProperties
+ { "--sidebar-width": "var(--ao-sidebar-w, 240px)", "--sidebar-width-icon": "48px" } as CSSProperties
}
>
-
);
}