fix(frontend): address onboarding copy review + hide Board header on welcome
Per review on #2432: welcome body now names the kanban board explicitly, step copy tightened to the reviewer's wording, the project empty state says "No worker sessions yet" (an orchestrator session may already exist), and the "Board" subhead is hidden on the first-launch welcome since it described a board that isn't rendered there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
699469bee4
commit
acb959c059
|
|
@ -118,6 +118,8 @@ describe("global board first launch", () => {
|
|||
expect(screen.getByText("Describe a task")).toBeInTheDocument();
|
||||
expect(screen.getByText("Ready to merge")).toBeInTheDocument();
|
||||
expect(columnCount()).toBe(0);
|
||||
// The welcome carries its own orientation — no dangling "Board" header.
|
||||
expect(screen.queryByText("Board")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("opens the native folder picker from the welcome CTA", async () => {
|
||||
|
|
@ -154,7 +156,7 @@ describe("project board with no sessions", () => {
|
|||
respondWith([project], []);
|
||||
renderBoard(<SessionsBoard projectId="proj-1" />);
|
||||
|
||||
expect(await screen.findByText("No sessions yet")).toBeInTheDocument();
|
||||
expect(await screen.findByText("No worker sessions yet")).toBeInTheDocument();
|
||||
// Board header + empty state each offer the pair; the orchestrator is primary in both.
|
||||
expect(screen.getAllByRole("button", { name: "Spawn Orchestrator" }).length).toBeGreaterThan(0);
|
||||
expect(screen.getAllByRole("button", { name: "New task" }).length).toBeGreaterThan(0);
|
||||
|
|
@ -167,7 +169,7 @@ describe("project board with no sessions", () => {
|
|||
spawnOrchestratorMock.mockRejectedValue(new Error("branch is already checked out in another worktree"));
|
||||
renderBoard(<SessionsBoard projectId="proj-1" />);
|
||||
|
||||
await screen.findByText("No sessions yet");
|
||||
await screen.findByText("No worker sessions yet");
|
||||
const [spawnButton] = screen.getAllByRole("button", { name: "Spawn Orchestrator" });
|
||||
await userEvent.click(spawnButton);
|
||||
|
||||
|
|
@ -229,7 +231,7 @@ describe("project board with no sessions", () => {
|
|||
</QueryClientProvider>,
|
||||
);
|
||||
|
||||
await screen.findByText("No sessions yet");
|
||||
await screen.findByText("No worker sessions yet");
|
||||
await waitFor(() => expect(useUiStore.getState().orchestratorStartupErrors["proj-1"]).toBeUndefined());
|
||||
expect(screen.queryByText(/Project added, but orchestrator did not start/)).not.toBeInTheDocument();
|
||||
});
|
||||
|
|
@ -244,7 +246,7 @@ describe("project board with no sessions", () => {
|
|||
);
|
||||
renderBoard(<SessionsBoard projectId="proj-1" />);
|
||||
|
||||
await screen.findByText("No sessions yet");
|
||||
await screen.findByText("No worker sessions yet");
|
||||
await waitFor(() => expect(useUiStore.getState().orchestratorStartupErrors["proj-1"]).toBeUndefined());
|
||||
expect(screen.queryByText(/Project added, but orchestrator did not start/)).not.toBeInTheDocument();
|
||||
});
|
||||
|
|
@ -255,7 +257,7 @@ describe("project board with no sessions", () => {
|
|||
spawnOrchestratorMock.mockRejectedValue(new Error("branch is already checked out in another worktree"));
|
||||
const { rerender } = renderBoard(<SessionsBoard projectId="proj-1" />);
|
||||
|
||||
await screen.findByText("No sessions yet");
|
||||
await screen.findByText("No worker sessions yet");
|
||||
const [spawnButton] = screen.getAllByRole("button", { name: "Spawn Orchestrator" });
|
||||
await userEvent.click(spawnButton);
|
||||
await screen.findByText(/branch is already checked out/);
|
||||
|
|
@ -267,7 +269,7 @@ describe("project board with no sessions", () => {
|
|||
</ShellProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
await screen.findByText("No sessions yet");
|
||||
await screen.findByText("No worker sessions yet");
|
||||
expect(screen.queryByText(/branch is already checked out/)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
|
@ -276,7 +278,7 @@ describe("project board with no sessions", () => {
|
|||
renderBoard(<SessionsBoard projectId="proj-1" />);
|
||||
|
||||
expect(await screen.findByText("fix the bug")).toBeInTheDocument();
|
||||
expect(screen.queryByText("No sessions yet")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("No worker sessions yet")).not.toBeInTheDocument();
|
||||
expect(columnCount()).toBe(4);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -29,19 +29,19 @@ export function BoardWelcome() {
|
|||
Welcome to Agent Orchestrator
|
||||
</h2>
|
||||
<p className="mt-2 max-w-[400px] text-[12.5px] leading-[1.6] text-muted-foreground">
|
||||
Point it at a git repository and delegate. Agents do the work on isolated branches; you review and merge the
|
||||
PRs from this board.
|
||||
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.
|
||||
</p>
|
||||
|
||||
<ol className="mt-7 w-full divide-y divide-border rounded-[13px] border border-border bg-surface text-left">
|
||||
<WelcomeStep n="01" title="Add a project">
|
||||
Pick a local git repository and choose which agents run it.
|
||||
Choose a local git repository and select the agents AO should use.
|
||||
</WelcomeStep>
|
||||
<WelcomeStep n="02" title="Describe a task">
|
||||
The orchestrator plans the work and spawns worker sessions, each on its own branch.
|
||||
Tell the orchestrator what you want done; it creates worker sessions on isolated branches.
|
||||
</WelcomeStep>
|
||||
<WelcomeStep n="03" title="Review and merge">
|
||||
Sessions move across this board as they progress:
|
||||
Follow each session from work to review to merge readiness:
|
||||
<span className="mt-2 flex flex-wrap items-center gap-x-1.5 gap-y-1.5">
|
||||
{FLOW_LEGEND.map((zone, index) => (
|
||||
<Fragment key={zone.label}>
|
||||
|
|
@ -123,7 +123,7 @@ export function ProjectBoardEmpty({
|
|||
return (
|
||||
<div className="flex h-full min-h-0 items-center justify-center overflow-y-auto">
|
||||
<div className="flex w-full max-w-[400px] flex-col items-center pb-[5vh] text-center">
|
||||
<h2 className="text-[15px] font-semibold tracking-[-0.01em] text-foreground">No sessions yet</h2>
|
||||
<h2 className="text-[15px] font-semibold tracking-[-0.01em] text-foreground">No worker sessions yet</h2>
|
||||
<p className="mt-2 text-[12.5px] leading-[1.6] text-muted-foreground">
|
||||
Describe a task and the orchestrator plans it, spawns worker sessions, and tracks them here from work to
|
||||
merge.
|
||||
|
|
|
|||
|
|
@ -225,11 +225,16 @@ export function SessionsBoard({ projectId }: SessionsBoardProps) {
|
|||
|
||||
return (
|
||||
<div className="flex h-full min-h-0 flex-col bg-background text-foreground">
|
||||
{/* The first-launch welcome carries its own orientation; a "Board"
|
||||
header above it would describe a board that isn't rendered
|
||||
(review feedback on #2432). */}
|
||||
{!showWelcome && (
|
||||
<DashboardSubhead
|
||||
title="Board"
|
||||
subtitle="Live agent sessions flowing from work → review → merge."
|
||||
actions={actions}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="min-h-0 flex-1 overflow-hidden p-[18px]">
|
||||
{projectId && health.state !== "ok" ? (
|
||||
|
|
|
|||
Loading…
Reference in New Issue