diff --git a/e2e/docs.spec.ts b/e2e/docs.spec.ts new file mode 100644 index 00000000..7c100a85 --- /dev/null +++ b/e2e/docs.spec.ts @@ -0,0 +1,21 @@ +import { expect, test } from "@playwright/test"; +import { loadApp } from "./helpers"; + +test.describe("Docs pane", () => { + test("opens docs from the sidebar and switches sections", async ({ page }) => { + await loadApp(page); + + await page.getByTestId("docs-button").click(); + + const docsPane = page.getByTestId("docs-pane"); + await expect(docsPane).toBeVisible({ timeout: 3_000 }); + await expect(docsPane.getByRole("heading", { level: 2, name: "Agents" })).toBeVisible(); + + await page.getByRole("button", { name: "Repo Tools" }).click(); + await expect(docsPane.getByRole("heading", { level: 2, name: "Repo Tools" })).toBeVisible(); + await expect(docsPane.getByRole("heading", { level: 3, name: "Defining tools" })).toBeVisible(); + + await page.getByRole("button", { name: "Close" }).click(); + await expect(docsPane).not.toBeVisible({ timeout: 3_000 }); + }); +}); diff --git a/web/src/App.tsx b/web/src/App.tsx index 59838fea..28ef54ec 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -5,6 +5,7 @@ import { ClipboardAddon } from "@xterm/addon-clipboard"; import "@xterm/xterm/css/xterm.css"; import { AgentSidebar, AgentSidebarContent } from "@/components/app/agent-sidebar"; import { AppHeader } from "@/components/app/app-header"; +import { DocsPane } from "@/components/app/docs-pane"; import { SettingsPane } from "@/components/app/settings-pane"; import { CreateAgentDialog } from "@/components/app/create-agent-dialog"; import { DeleteAgentDialog } from "@/components/app/delete-agent-dialog"; @@ -179,6 +180,7 @@ export function App(): JSX.Element { const [statusMessage, setStatusMessage] = useState("Starting..."); const [settingsPaneOpen, setSettingsPaneOpen] = useState(false); + const [docsPaneOpen, setDocsPaneOpen] = useState(false); const [createOpen, setCreateOpen] = useState(false); const [createName, setCreateName] = useState(""); const [createCwd, setCreateCwd] = useState(() => readLastUsedCwd()); @@ -1418,7 +1420,8 @@ export function App(): JSX.Element { overflowAgentId={overflowAgentId} setLeftOpen={setLeftOpen} onOpenCreateDialog={openCreateDialog} - onOpenSettings={() => setSettingsPaneOpen(true)} + onOpenDocs={() => setDocsPaneOpen(true)} + onOpenSettings={() => setSettingsPaneOpen(true)} setOverflowAgentId={setOverflowAgentId} setDeleteTarget={setDeleteTarget} setDeleteConfirmOpen={setDeleteConfirmOpen} @@ -1516,6 +1519,7 @@ export function App(): JSX.Element { selectedAgentId={selectedAgentId} overflowAgentId={overflowAgentId} onOpenCreateDialog={() => { setMobileLeftOpen(false); openCreateDialog(); }} + onOpenDocs={() => { setMobileLeftOpen(false); setDocsPaneOpen(true); }} onOpenSettings={() => { setMobileLeftOpen(false); setSettingsPaneOpen(true); }} setOverflowAgentId={setOverflowAgentId} setDeleteTarget={setDeleteTarget} @@ -1588,6 +1592,7 @@ export function App(): JSX.Element { onDelete={deleteAgent} /> + setDocsPaneOpen(false)} /> setSettingsPaneOpen(false)} /> void; + onOpenDocs: () => void; onOpenSettings: () => void; setOverflowAgentId: (value: string | null | ((current: string | null) => string | null)) => void; setDeleteTarget: (agent: Agent | null) => void; @@ -58,6 +60,7 @@ export function AgentSidebarContent({ selectedAgentId, overflowAgentId, onOpenCreateDialog, + onOpenDocs, onOpenSettings, setOverflowAgentId, setDeleteTarget, @@ -421,10 +424,18 @@ export function AgentSidebarContent({
+ + ) : null} + + {activeSection !== null ? {active.label} : null} + Docs + + + + Close + +
+ +
+ + + {activeSection === null ? ( + + ) : null} + +
+ +
+
+

{active.title}

+
+
+ {active.content} +
+
+
+
+
+ + + + ); +}