Skip to content

Commit fbe4b05

Browse files
committed
feat(chat): setting to keep the agent plan overlay collapsed
1 parent 8427470 commit fbe4b05

16 files changed

Lines changed: 219 additions & 2 deletions

src/components/chat/agent-plan-overlay.test.tsx

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { fireEvent, render, screen } from "@testing-library/react"
22
import { NextIntlClientProvider } from "next-intl"
3-
import { describe, expect, it } from "vitest"
3+
import { afterEach, describe, expect, it } from "vitest"
44

55
import { AgentPlanOverlay } from "./agent-plan-overlay"
66
import enMessages from "@/i18n/messages/en.json"
@@ -22,6 +22,10 @@ const sampleEntries: PlanEntryInfo[] = [
2222
]
2323

2424
describe("AgentPlanOverlay", () => {
25+
afterEach(() => {
26+
window.localStorage.removeItem("codeg-plan-overlay-auto-expand")
27+
})
28+
2529
it("renders nothing when entries are empty", () => {
2630
const { container } = renderWithIntl(
2731
<AgentPlanOverlay entries={[]} planKey="p-empty" />
@@ -117,6 +121,37 @@ describe("AgentPlanOverlay", () => {
117121
expect(screen.getByText("Done A")).toBeInTheDocument()
118122
})
119123

124+
it("stays collapsed when auto-expand is turned off", () => {
125+
window.localStorage.setItem("codeg-plan-overlay-auto-expand", "0")
126+
const noPlan = {
127+
id: "live-off",
128+
content: [{ type: "text", text: "working" }],
129+
} as unknown as LiveMessage
130+
const withPlan = {
131+
id: "live-off",
132+
content: [
133+
{ type: "text", text: "working" },
134+
{
135+
type: "plan",
136+
entries: [
137+
{ content: "Build step", priority: "high", status: "in_progress" },
138+
],
139+
},
140+
],
141+
} as unknown as LiveMessage
142+
143+
const { rerender } = renderWithIntl(
144+
<AgentPlanOverlay message={noPlan} isStreaming />
145+
)
146+
rerender(
147+
<NextIntlClientProvider locale="en" messages={enMessages}>
148+
<AgentPlanOverlay message={withPlan} isStreaming />
149+
</NextIntlClientProvider>
150+
)
151+
expect(screen.getByText("Plan 0/1")).toBeInTheDocument()
152+
expect(screen.queryByText("Build step")).not.toBeInTheDocument()
153+
})
154+
120155
it("auto-expands once when a plan is created live while streaming", () => {
121156
// Streaming starts with no plan, then a plan_update lands. The overlay
122157
// should pop open by itself the first time the plan appears.

src/components/chat/agent-plan-overlay.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { Button } from "@/components/ui/button"
1313
import type { LiveMessage } from "@/contexts/acp-connections-context"
1414
import type { PlanEntryInfo } from "@/lib/types"
1515
import { cn } from "@/lib/utils"
16+
import { usePlanOverlayAutoExpand } from "@/hooks/use-plan-overlay-auto-expand"
1617
import {
1718
CheckCircle2Icon,
1819
ChevronDownIcon,
@@ -70,6 +71,7 @@ export const AgentPlanOverlay = memo(function AgentPlanOverlay({
7071
isStreaming = false,
7172
}: AgentPlanOverlayProps) {
7273
const t = useTranslations("Folder.chat.agentPlanOverlay")
74+
const { autoExpand } = usePlanOverlayAutoExpand()
7375
const liveEntries = useMemo(
7476
() => getLatestPlanEntries(message ?? null),
7577
[message]
@@ -114,6 +116,7 @@ export const AgentPlanOverlay = memo(function AgentPlanOverlay({
114116
const [autoExpanded, setAutoExpanded] = useState(false)
115117
if (prevLiveHadPlan !== liveHasPlan) {
116118
const planCreatedLive =
119+
autoExpand &&
117120
prevLiveHadPlan === false &&
118121
liveHasPlan &&
119122
isStreaming &&

src/components/settings/appearance-settings.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client"
22

3-
import { LayoutGrid, Monitor, Moon, Sun, Type } from "lucide-react"
3+
import { LayoutGrid, ListTodo, Monitor, Moon, Sun, Type } from "lucide-react"
44
import { useTranslations } from "next-intl"
55
import { useTheme } from "next-themes"
66
import { ScrollArea } from "@/components/ui/scroll-area"
@@ -30,6 +30,7 @@ import { PetManagerSection } from "./pet-manager-section"
3030
import { FontSettingsSection } from "./font-settings-section"
3131
import { WorkspaceBackgroundSection } from "./workspace-background-section"
3232
import { CustomStyleSection } from "./custom-style-section"
33+
import { usePlanOverlayAutoExpand } from "@/hooks/use-plan-overlay-auto-expand"
3334

3435
type ThemeMode = "system" | "light" | "dark"
3536

@@ -40,6 +41,8 @@ export function AppearanceSettings() {
4041
const { zoomLevel, setZoomLevel } = useZoomLevel()
4142
const { showWelcomeQuickActions, setShowWelcomeQuickActions } =
4243
useWelcomeQuickActions()
44+
const { autoExpand: autoExpandPlan, setAutoExpand: setAutoExpandPlan } =
45+
usePlanOverlayAutoExpand()
4346

4447
const resolvedThemeLabel =
4548
resolvedTheme === "dark"
@@ -238,6 +241,30 @@ export function AppearanceSettings() {
238241
</label>
239242
</section>
240243

244+
{/* ===== Conversation overlays ===== */}
245+
<section className="rounded-xl border bg-card p-4 space-y-4">
246+
<div className="flex items-center gap-2">
247+
<ListTodo className="h-4 w-4 text-muted-foreground" />
248+
<h2 className="text-sm font-semibold">
249+
{t("planOverlay.sectionTitle")}
250+
</h2>
251+
</div>
252+
253+
<p className="text-xs text-muted-foreground leading-5">
254+
{t("planOverlay.sectionDescription")}
255+
</p>
256+
257+
<label className="flex items-center gap-2">
258+
<Switch
259+
checked={autoExpandPlan}
260+
onCheckedChange={setAutoExpandPlan}
261+
/>
262+
<span className="text-xs text-muted-foreground">
263+
{t("planOverlay.autoExpand")}
264+
</span>
265+
</label>
266+
</section>
267+
241268
{/* ===== Desktop Pet ===== */}
242269
<PetManagerSection />
243270
</div>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"use client"
2+
3+
import { useCallback, useEffect, useState } from "react"
4+
5+
import {
6+
PLAN_OVERLAY_AUTO_EXPAND_EVENT,
7+
STORAGE_KEY_PLAN_OVERLAY_AUTO_EXPAND,
8+
readPlanOverlayAutoExpand,
9+
writePlanOverlayAutoExpand,
10+
} from "@/lib/plan-overlay-prefs"
11+
12+
export function usePlanOverlayAutoExpand(): {
13+
autoExpand: boolean
14+
setAutoExpand: (on: boolean) => void
15+
} {
16+
const [autoExpand, setAutoExpandState] = useState(readPlanOverlayAutoExpand)
17+
18+
useEffect(() => {
19+
const sync = () => setAutoExpandState(readPlanOverlayAutoExpand())
20+
const onStorage = (event: StorageEvent) => {
21+
if (event.key && event.key !== STORAGE_KEY_PLAN_OVERLAY_AUTO_EXPAND) return
22+
sync()
23+
}
24+
window.addEventListener("storage", onStorage)
25+
window.addEventListener(PLAN_OVERLAY_AUTO_EXPAND_EVENT, sync)
26+
return () => {
27+
window.removeEventListener("storage", onStorage)
28+
window.removeEventListener(PLAN_OVERLAY_AUTO_EXPAND_EVENT, sync)
29+
}
30+
}, [])
31+
32+
const setAutoExpand = useCallback((on: boolean) => {
33+
setAutoExpandState(on)
34+
writePlanOverlayAutoExpand(on)
35+
}, [])
36+
37+
return { autoExpand, setAutoExpand }
38+
}

src/i18n/messages/ar.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@
173173
"sectionDescription": "بطاقات الاختصار «تطوير الكود / الأعمال المكتبية» التي تظهر أعلى مربع الإدخال في صفحة المحادثة الجديدة.",
174174
"showQuickActions": "العرض في صفحة المحادثة الجديدة"
175175
},
176+
"planOverlay": {
177+
"sectionTitle": "Agent plan",
178+
"sectionDescription": "The floating plan card that appears on the left of a conversation when an agent writes a to-do list. You can always open it from the small chip.",
179+
"autoExpand": "Open the plan card when an agent starts a plan"
180+
},
176181
"workspaceBackground": {
177182
"sectionTitle": "خلفية مساحة العمل",
178183
"sectionDescription": "عرض صورة خلف مساحة العمل بالكامل. يصبح الشريط الجانبي واللوحات شبه شفافة ومصنفرة لتظهر الصورة من خلالها، ويحافظ القناع على وضوح النص.",

src/i18n/messages/de.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@
173173
"sectionDescription": "Die Shortcut-Karten „Code-Entwicklung / Büroarbeit“ über dem Eingabefeld auf der Seite für eine neue Konversation.",
174174
"showQuickActions": "Auf der Seite für neue Konversationen anzeigen"
175175
},
176+
"planOverlay": {
177+
"sectionTitle": "Agent plan",
178+
"sectionDescription": "The floating plan card that appears on the left of a conversation when an agent writes a to-do list. You can always open it from the small chip.",
179+
"autoExpand": "Open the plan card when an agent starts a plan"
180+
},
176181
"workspaceBackground": {
177182
"sectionTitle": "Arbeitsbereich-Hintergrund",
178183
"sectionDescription": "Zeigt ein Bild hinter dem gesamten Arbeitsbereich. Seitenleiste und Panels werden durchscheinend und mattiert, sodass das Bild durchscheint, und eine Maske sorgt für lesbaren Text.",

src/i18n/messages/en.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@
173173
"sectionDescription": "The Code Development / Office Work shortcut cards shown above the composer on the new conversation page.",
174174
"showQuickActions": "Show on the new conversation page"
175175
},
176+
"planOverlay": {
177+
"sectionTitle": "Agent plan",
178+
"sectionDescription": "The floating plan card that appears on the left of a conversation when an agent writes a to-do list. You can always open it from the small chip.",
179+
"autoExpand": "Open the plan card when an agent starts a plan"
180+
},
176181
"workspaceBackground": {
177182
"sectionTitle": "Workspace background",
178183
"sectionDescription": "Show a picture behind the whole workspace. Sidebar and panels turn translucent and frosted so the image shows through, and a mask keeps text readable.",

src/i18n/messages/es.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@
173173
"sectionDescription": "Las tarjetas de acceso rápido «Desarrollo de código / Ofimática» que se muestran sobre el editor en la página de nueva conversación.",
174174
"showQuickActions": "Mostrar en la página de nueva conversación"
175175
},
176+
"planOverlay": {
177+
"sectionTitle": "Agent plan",
178+
"sectionDescription": "The floating plan card that appears on the left of a conversation when an agent writes a to-do list. You can always open it from the small chip.",
179+
"autoExpand": "Open the plan card when an agent starts a plan"
180+
},
176181
"workspaceBackground": {
177182
"sectionTitle": "Fondo del espacio de trabajo",
178183
"sectionDescription": "Muestra una imagen detrás de todo el espacio de trabajo. La barra lateral y los paneles se vuelven translúcidos y esmerilados para dejar ver la imagen, y una máscara mantiene el texto legible.",

src/i18n/messages/fr.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@
173173
"sectionDescription": "Les cartes de raccourci « Développement / Bureautique » affichées au-dessus du champ de saisie sur la page de nouvelle conversation.",
174174
"showQuickActions": "Afficher sur la page de nouvelle conversation"
175175
},
176+
"planOverlay": {
177+
"sectionTitle": "Agent plan",
178+
"sectionDescription": "The floating plan card that appears on the left of a conversation when an agent writes a to-do list. You can always open it from the small chip.",
179+
"autoExpand": "Open the plan card when an agent starts a plan"
180+
},
176181
"workspaceBackground": {
177182
"sectionTitle": "Arrière-plan de l'espace de travail",
178183
"sectionDescription": "Affiche une image derrière tout l'espace de travail. La barre latérale et les panneaux deviennent translucides et dépolis pour laisser transparaître l'image, et un masque préserve la lisibilité du texte.",

src/i18n/messages/ja.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@
173173
"sectionDescription": "新しい会話ページで入力欄の上に表示される「コード開発 / 日常業務」のショートカットカードです。",
174174
"showQuickActions": "新しい会話ページに表示する"
175175
},
176+
"planOverlay": {
177+
"sectionTitle": "Agent plan",
178+
"sectionDescription": "The floating plan card that appears on the left of a conversation when an agent writes a to-do list. You can always open it from the small chip.",
179+
"autoExpand": "Open the plan card when an agent starts a plan"
180+
},
176181
"workspaceBackground": {
177182
"sectionTitle": "ワークスペースの背景",
178183
"sectionDescription": "ワークスペース全体の背後に画像を表示します。サイドバーやパネルは半透明のすりガラスになり画像が透けて見えます。マスクで文字の可読性を保ちます。",

0 commit comments

Comments
 (0)