diff --git a/docs/screenshots/board-welcome-ao-20260709-042252.png b/docs/screenshots/board-welcome-ao-20260709-042252.png new file mode 100644 index 0000000000..bd8aacf59d Binary files /dev/null and b/docs/screenshots/board-welcome-ao-20260709-042252.png differ diff --git a/frontend/src/renderer/__tests__/integration/board-empty-states.test.tsx b/frontend/src/renderer/__tests__/integration/board-empty-states.test.tsx index 1403a74742..5e330d679e 100644 --- a/frontend/src/renderer/__tests__/integration/board-empty-states.test.tsx +++ b/frontend/src/renderer/__tests__/integration/board-empty-states.test.tsx @@ -113,10 +113,8 @@ describe("global board first launch", () => { expect(await screen.findByText("Welcome to Agent Orchestrator")).toBeInTheDocument(); expect(screen.getByRole("button", { name: "Add your first project" })).toBeInTheDocument(); - // The three orientation steps and the column legend are present. - expect(screen.getByText("Add a project")).toBeInTheDocument(); - expect(screen.getByText("Describe a task")).toBeInTheDocument(); - expect(screen.getByText("Ready to merge")).toBeInTheDocument(); + // The CTA is present. + expect(screen.getByRole("button", { name: "Add your first project" })).toBeInTheDocument(); expect(columnCount()).toBe(0); // The welcome carries its own orientation — no dangling "Board" header. expect(screen.queryByText("Board")).not.toBeInTheDocument(); diff --git a/frontend/src/renderer/components/BoardEmptyState.tsx b/frontend/src/renderer/components/BoardEmptyState.tsx index e339844af4..9a09fbf8df 100644 --- a/frontend/src/renderer/components/BoardEmptyState.tsx +++ b/frontend/src/renderer/components/BoardEmptyState.tsx @@ -1,107 +1,45 @@ -import { Fragment, type ReactNode } from "react"; import { Plus } from "lucide-react"; + import { useShell } from "../lib/shell-context"; -import { cn } from "../lib/utils"; import aoLogo from "../assets/ao-logo.png"; import { CreateProjectFlow } from "./CreateProjectFlow"; import { OrchestratorIcon } from "./icons"; -// The four board zones, in flow order — mirrors COLUMNS in SessionsBoard.tsx -// (label + dot color + title tint) so the welcome legend pre-teaches exactly -// what the user will see once the board has sessions. -const FLOW_LEGEND = [ - { label: "Working", dot: "var(--orange)", titleClass: "text-working" }, - { label: "Needs you", dot: "var(--amber)", titleClass: "text-warning" }, - { label: "In review", dot: "var(--fg-muted)", titleClass: "text-muted-foreground" }, - { label: "Ready to merge", dot: "var(--green)", titleClass: "text-success" }, -]; - -// First-launch board state (no projects registered yet): replaces the four -// empty kanban columns with orientation — what this app does, the three steps -// to a first merge, and the same create-project flow the sidebar's + runs. export function BoardWelcome() { const { createProject } = useShell(); return (
-
- -

+
+ +

Welcome to Agent Orchestrator

-

- Add a git repository, describe the work, and AO coordinates agent sessions on isolated branches. This kanban - board tracks each session from work through review to merge. +

+ Add a repository and describe the work. AO runs agents on isolated branches, from start to merge.

-
    - - Choose a local git repository and select the agents AO should use. - - - Tell the orchestrator what you want done; it creates worker sessions on isolated branches. - - - Follow each session from work to review to merge readiness: - - {FLOW_LEGEND.map((zone, index) => ( - - {index > 0 && ( - - )} - - - {zone.label} - - - ))} - - -
- {({ choosePath, disabled, error, label }) => ( <> {error &&

{error}

} )}
-

- Adding a project starts its orchestrator — the agent you talk to. -

+

Starts an orchestrator session for the project.

); } -function WelcomeStep({ n, title, children }: { n: string; title: string; children: ReactNode }) { - return ( -
  • - {n} - - {title} - {children} - -
  • - ); -} - // Project board with a registered project but no worker sessions yet: a quiet // invitation instead of four empty columns. Actions mirror the board header // (Orchestrator stays the primary, like the topbar) so the vocabulary holds.