@@ -174,21 +175,24 @@ export function ShellTopbar() {
>
) : (
+
+ )}
+ {/* Kill control sits beside the orchestrator link for active workers —
+ moved here from the inspector's Summary "Danger zone". */}
+ {!isOrchestrator && session && sessionIsActive(session) ? : null}
+ {!isOrchestrator && (
)}
- {/* Kill control sits beside the orchestrator link for active workers —
- moved here from the inspector's Summary "Danger zone". */}
- {!isOrchestrator && session && sessionIsActive(session) ? : null}
{/* Inspector collapse (worker sessions only — orchestrators have no rail). */}
{!isOrchestrator && (
+ );
+}
+
// Compact kill control for the topbar actions row. Stop a running worker and
// tear down its runtime/workspace. Kill is irreversible from the UI, so the
// button arms a one-step confirmation before firing POST /sessions/{id}/kill,
@@ -328,7 +304,8 @@ export function TopbarKillButton({ session }: { session: WorkspaceSession }) {
title="Kill session"
type="button"
>
-
+
+ Kill
);
}
diff --git a/frontend/src/renderer/components/Sidebar.tsx b/frontend/src/renderer/components/Sidebar.tsx
index a243b26a2..9dc80f83b 100644
--- a/frontend/src/renderer/components/Sidebar.tsx
+++ b/frontend/src/renderer/components/Sidebar.tsx
@@ -71,6 +71,7 @@ const HOVER_ACTION_CLASS =
type SidebarProps = {
daemonStatus: { state: string; message?: string };
+ underTopbar?: boolean;
workspaceError?: string;
workspaces: WorkspaceSummary[];
onCreateProject: (input: { path: string }) => Promise;
@@ -119,7 +120,14 @@ function SessionDot({ session }: { session: WorkspaceSession }) {
// _shell owns open state (synced to the ui-store) and `collapsible="icon"`
// replaces the old hand-rolled CollapsedRail — the same tree restyles itself
// via group-data-[collapsible=icon] into the 48px letter rail.
-export function Sidebar({ daemonStatus, workspaceError, workspaces, onCreateProject, onRemoveProject }: SidebarProps) {
+export function Sidebar({
+ daemonStatus,
+ underTopbar = true,
+ workspaceError,
+ workspaces,
+ onCreateProject,
+ onRemoveProject,
+}: SidebarProps) {
const selection = useSelection();
const eventsConnection = useEventsConnection();
const { state } = useSidebar();
@@ -151,8 +159,11 @@ export function Sidebar({ daemonStatus, workspaceError, workspaces, onCreateProj
// The container is fixed-positioned by the shadcn primitive; offset it
// below the 56px shell topbar so the bar runs edge-to-edge above it
// (same override as shadcn's header-above-sidebar block).
-
-
+
+
{/* Brand (project-sidebar__brand); in the icon rail it becomes the old
36px board button wrapping the 22px accent mark. */}
@@ -544,11 +555,10 @@ function ProjectItem({
{removeError}
)}
- {/* project-sidebar__sessions: indented under the project parent with a
- subtle guide line so worker sessions read as children, not peer
- navigation rows. */}
+ {/* project-sidebar__sessions: indented under the project parent so worker
+ sessions read as children without adding a persistent guide rail. */}
{expanded && sessions.length > 0 && (
-
+
{sessions.map((session) => {
const active = selection.activeSessionId === session.id;
return (
diff --git a/frontend/src/renderer/routes/_shell.tsx b/frontend/src/renderer/routes/_shell.tsx
index 7eb542356..ed395722f 100644
--- a/frontend/src/renderer/routes/_shell.tsx
+++ b/frontend/src/renderer/routes/_shell.tsx
@@ -1,4 +1,4 @@
-import { createFileRoute, Outlet, useNavigate } from "@tanstack/react-router";
+import { createFileRoute, Outlet, useNavigate, useRouterState } from "@tanstack/react-router";
import { useQueryClient } from "@tanstack/react-query";
import { type CSSProperties, useCallback, useEffect } from "react";
import { ShellTopbar } from "../components/ShellTopbar";
@@ -35,11 +35,13 @@ function errorMessage(error: unknown) {
// instead of Zustand. The daemon-status effect runs here exactly once.
function ShellLayout() {
const navigate = useNavigate();
+ const pathname = useRouterState({ select: (state) => state.location.pathname });
const queryClient = useQueryClient();
const workspaceQuery = useWorkspaceQuery();
const workspaces = workspaceQuery.data ?? [];
const daemonStatus = useDaemonStatus(queryClient);
const { theme, setTheme, isSidebarOpen, toggleSidebar } = useUiStore();
+ const isBoardRoute = pathname === "/" || /^\/projects\/[^/]+$/.test(pathname);
const updateWorkspaces = useCallback(
(updater: (workspaces: WorkspaceSummary[]) => WorkspaceSummary[]) => {
@@ -129,7 +131,7 @@ function ShellLayout() {
in the layout, not the screens, so the crumb and actions never shift
when the outlet content swaps. */}
-
+ {!isBoardRoute && }
{/* Controlled by the ui-store so TitlebarNav / Topbar toggles (which
call the store directly) stay in sync. --sidebar-width chains to
the drag-resizable --ao-sidebar-w set on :root by useResizable. */}
@@ -141,6 +143,7 @@ function ShellLayout() {
>