Skip to content

Commit 2a9da70

Browse files
committed
fix: complete the flows merge — fullscreen + hero reconciled with the watch surfaces
1 parent 1ca17ed commit 2a9da70

5 files changed

Lines changed: 41 additions & 129 deletions

File tree

apps/webapp/app/components/dashboard-agent/DashboardAgent.tsx

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ import { DashboardAgentPanel } from "./DashboardAgentPanel";
1313
import { DashboardAgentProvider, TOGGLE_PANEL_SHORTCUT } from "./dashboardAgentLauncher";
1414
import { useDashboardAgentOpenRequests } from "./dashboardAgentOpenRequest";
1515
import {
16-
<<<<<<< HEAD
16+
agentHiddenContentClassName,
17+
agentTakeoverClassName,
18+
readAgentFullscreen,
19+
writeAgentFullscreen,
20+
} from "./panel-layout";
21+
import {
1722
showWatchWakesSummaryToast,
1823
showWatchWakeToast,
1924
WAKE_TOAST_MAX_INDIVIDUAL,
@@ -23,13 +28,6 @@ import {
2328
// How often the closed panel asks whether a watch woke a chat. A wake is worth
2429
// noticing within a minute, and the count is one indexed query.
2530
const UNREAD_POLL_INTERVAL_MS = 60_000;
26-
=======
27-
agentHiddenContentClassName,
28-
agentTakeoverClassName,
29-
readAgentFullscreen,
30-
writeAgentFullscreen,
31-
} from "./panel-layout";
32-
>>>>>>> origin/feat/dashboard-agent-flows
3331

3432
/**
3533
* Mounts the dashboard agent in the env layout. Renders the page content
@@ -59,14 +57,12 @@ export function DashboardAgent({
5957
const actionPath = `/resources/orgs/${organization.slug}/projects/${project.slug}/env/${environment.slug}/dashboard-agent`;
6058

6159
const [open, setOpen] = useState(false);
62-
<<<<<<< HEAD
6360
const [unreadWakes, setUnreadWakes] = useState(0);
6461
// Wakes already toasted this session. Session-scoped on purpose: a wake that
6562
// arrived overnight deserves the toast on the first poll after a reload, but a
6663
// wake the user has already been shown (and maybe dismissed) must not come
6764
// back every 60s while the chat stays unread.
6865
const toastedWakes = useRef(new Set<string>());
69-
=======
7066
// The side panel is the default; someone who last worked fullscreen gets
7167
// fullscreen back. Read lazily so SSR always renders the side panel.
7268
const [fullscreen, setFullscreen] = useState(readAgentFullscreen);
@@ -77,7 +73,6 @@ export function DashboardAgent({
7773
return !current;
7874
});
7975
}, []);
80-
>>>>>>> origin/feat/dashboard-agent-flows
8176
// A request from `openWith`, handed to the panel. `seq` makes repeat requests
8277
// with the same text distinct, so the panel can tell them apart.
8378
const [requestedMessage, setRequestedMessage] = useState<
@@ -218,25 +213,6 @@ export function DashboardAgent({
218213
return (
219214
<DashboardAgentProvider value={context}>
220215
{open ? (
221-
<<<<<<< HEAD
222-
<ResizablePanelGroup
223-
orientation="horizontal"
224-
autosaveId="dashboard-agent-split"
225-
className="h-full min-h-0"
226-
>
227-
<ResizablePanel id="dashboard-content" min="320px">
228-
<div className="h-full overflow-hidden">{children}</div>
229-
</ResizablePanel>
230-
<ResizableHandle id="dashboard-agent-handle" />
231-
<ResizablePanel id="dashboard-agent-panel" default="380px" min="320px" max="720px">
232-
<DashboardAgentPanel
233-
onClose={() => setPanelOpen(false)}
234-
requestedMessage={requestedMessage}
235-
openChatRequest={openChatRequest}
236-
watchRequest={watchRequest}
237-
promotedPrompt={promotedPrompt}
238-
onChatRead={markChatRead}
239-
=======
240216
// `relative` is the takeover's containing block: in fullscreen the panel
241217
// is pinned over this box — everything right of the side nav — while the
242218
// split, the page content and the panel itself all stay mounted. Toggling
@@ -254,14 +230,16 @@ export function DashboardAgent({
254230
<ResizableHandle
255231
id="dashboard-agent-handle"
256232
className={fullscreen ? "invisible" : undefined}
257-
>>>>>>> origin/feat/dashboard-agent-flows
258233
/>
259234
<ResizablePanel id="dashboard-agent-panel" default="380px" min="320px" max="720px">
260235
<div className={agentTakeoverClassName(fullscreen)}>
261236
<DashboardAgentPanel
262237
onClose={() => setPanelOpen(false)}
263238
requestedMessage={requestedMessage}
239+
openChatRequest={openChatRequest}
240+
watchRequest={watchRequest}
264241
promotedPrompt={promotedPrompt}
242+
onChatRead={markChatRead}
265243
isFullscreen={fullscreen}
266244
onToggleFullscreen={toggleFullscreen}
267245
/>

apps/webapp/app/components/dashboard-agent/DashboardAgentDraft.tsx

Lines changed: 21 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -49,52 +49,33 @@ export function DashboardAgentDraft({
4949
);
5050

5151
return (
52-
<<<<<<< HEAD
53-
<>
54-
<DashboardAgentSuggestedPrompts
55-
onSelect={submit}
56-
pageContext={pageContext}
57-
promoted={promotedPrompt}
58-
/>
59-
{watchCard}
60-
<DashboardAgentComposer
61-
value={input}
62-
onChange={setInput}
63-
onSubmit={() => submit(input)}
64-
onStop={() => {}}
65-
isStreaming={false}
66-
context={
67-
<DashboardAgentContextBanner
68-
projectSlug={projectSlug}
69-
environmentSlug={environmentSlug}
70-
currentPage={currentPage}
71-
/>
72-
}
73-
/>
74-
</>
75-
=======
7652
<DashboardAgentHero
7753
onSelect={submit}
7854
pageContext={pageContext}
7955
promoted={promotedPrompt}
8056
composer={
81-
<DashboardAgentComposer
82-
layout="hero"
83-
value={input}
84-
onChange={setInput}
85-
onSubmit={() => submit(input)}
86-
onStop={() => {}}
87-
isStreaming={false}
88-
context={
89-
<DashboardAgentContextBanner
90-
projectSlug={projectSlug}
91-
environmentSlug={environmentSlug}
92-
currentPage={currentPage}
93-
/>
94-
}
95-
/>
57+
// The card rides in the composer slot, directly above the field — the
58+
// same place a chat puts it, so an ephemeral card reads the same in the
59+
// blank state as it does mid-conversation.
60+
<div className="flex w-full flex-col gap-3">
61+
{watchCard}
62+
<DashboardAgentComposer
63+
layout="hero"
64+
value={input}
65+
onChange={setInput}
66+
onSubmit={() => submit(input)}
67+
onStop={() => {}}
68+
isStreaming={false}
69+
context={
70+
<DashboardAgentContextBanner
71+
projectSlug={projectSlug}
72+
environmentSlug={environmentSlug}
73+
currentPage={currentPage}
74+
/>
75+
}
76+
/>
77+
</div>
9678
}
9779
/>
98-
>>>>>>> origin/feat/dashboard-agent-flows
9980
);
10081
}

apps/webapp/app/components/dashboard-agent/DashboardAgentPanel.tsx

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,10 @@ export function DashboardAgentPanel({
8585
requestedMessage,
8686
openChatRequest,
8787
promotedPrompt,
88-
<<<<<<< HEAD
8988
watchRequest,
9089
onChatRead,
91-
=======
9290
isFullscreen = false,
9391
onToggleFullscreen,
94-
>>>>>>> origin/feat/dashboard-agent-flows
9592
}: {
9693
onClose: () => void;
9794
// Fullscreen is owned by `DashboardAgent` (it also has to hide the page
@@ -607,48 +604,6 @@ export function DashboardAgentPanel({
607604
onClose={onClose}
608605
/>
609606

610-
<<<<<<< HEAD
611-
{loading ? (
612-
<div className="flex flex-1 items-center justify-center">
613-
<Spinner className="size-5" />
614-
</div>
615-
) : active ? (
616-
<DashboardAgentChat
617-
key={active.chatId}
618-
chatId={active.chatId}
619-
initialMessages={active.messages}
620-
session={active.session}
621-
pendingFirstMessage={active.pendingFirstMessage}
622-
streaming={active.streaming}
623-
prefill={prefill && prefill.chatId === active.chatId ? prefill : undefined}
624-
clientData={clientData}
625-
apiOrigin={apiOrigin}
626-
actionPath={actionPath}
627-
projectSlug={project.slug}
628-
environmentSlug={environment.slug}
629-
currentPage={currentPage}
630-
promotedPrompt={promotedPrompt}
631-
watches={chatWatches}
632-
pagePaths={pagePaths}
633-
watchCard={watchCard}
634-
appendedMessage={appendedMessage}
635-
onWatchIntent={openWatchCard}
636-
onCancelWatch={cancelWatch}
637-
onTurnSettled={loadHistory}
638-
onActivityChange={handleActivityChange}
639-
/>
640-
) : (
641-
<DashboardAgentDraft
642-
onSubmit={createChat}
643-
projectSlug={project.slug}
644-
environmentSlug={environment.slug}
645-
currentPage={currentPage}
646-
pageContext={pageContext}
647-
promotedPrompt={promotedPrompt}
648-
watchCard={watchCard}
649-
/>
650-
)}
651-
=======
652607
{/* Always mounted, so switching to fullscreen only re-styles this column —
653608
the chat below it keeps its transport, session and transcript. */}
654609
<AgentPanelColumn fullscreen={isFullscreen}>
@@ -672,7 +627,12 @@ export function DashboardAgentPanel({
672627
environmentSlug={environment.slug}
673628
currentPage={currentPage}
674629
promotedPrompt={promotedPrompt}
630+
watches={chatWatches}
675631
pagePaths={pagePaths}
632+
watchCard={watchCard}
633+
appendedMessage={appendedMessage}
634+
onWatchIntent={openWatchCard}
635+
onCancelWatch={cancelWatch}
676636
onTurnSettled={loadHistory}
677637
onActivityChange={handleActivityChange}
678638
/>
@@ -684,10 +644,10 @@ export function DashboardAgentPanel({
684644
currentPage={currentPage}
685645
pageContext={pageContext}
686646
promotedPrompt={promotedPrompt}
647+
watchCard={watchCard}
687648
/>
688649
)}
689650
</AgentPanelColumn>
690-
>>>>>>> origin/feat/dashboard-agent-flows
691651
</div>
692652
);
693653
}

apps/webapp/app/components/dashboard-agent/DashboardAgentSuggestedPrompts.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
22
BookOpenIcon,
3-
ChartBarIcon,
3+
EyeIcon,
44
MagnifyingGlassIcon,
55
QuestionMarkCircleIcon,
66
SparklesIcon,
@@ -21,7 +21,7 @@ import {
2121
*
2222
* - `promoted` / `investigate` — something to do about a problem, so they get
2323
* the indigo primary the rest of the app uses for the main action.
24-
* - `status` — "what's going on right now", a neutral query: secondary.
24+
* - `watch` — "tell me when this changes", a standing offer: secondary.
2525
* - `explain` — the evergreen question, the quietest of the set: tertiary.
2626
* - `docs` — a documentation question, so it gets the docs variant, the same
2727
* style every "read the docs" button in the dashboard has.
@@ -32,7 +32,7 @@ export const PROMPT_SLOT_BUTTON: Record<
3232
> = {
3333
promoted: { variant: "primary/medium", icon: SparklesIcon },
3434
investigate: { variant: "primary/medium", icon: MagnifyingGlassIcon },
35-
status: { variant: "secondary/medium", icon: ChartBarIcon },
35+
watch: { variant: "secondary/medium", icon: EyeIcon },
3636
explain: { variant: "tertiary/medium", icon: QuestionMarkCircleIcon },
3737
docs: { variant: "docs/medium", icon: BookOpenIcon },
3838
};

apps/webapp/app/routes/storybook.agent-ui/manifest.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,10 @@ export type GalleryGroup =
2323
| "investigation"
2424
| "report"
2525
| "chart"
26-
<<<<<<< HEAD
2726
| "watches"
2827
| "watch-card"
2928
| "wakes"
30-
=======
3129
| "hero"
32-
>>>>>>> origin/feat/dashboard-agent-flows
3330
| "prompts"
3431
| "intents"
3532
| "messages"
@@ -56,13 +53,10 @@ export const GALLERY_GROUPS: { group: GalleryGroup; label: string }[] = [
5653
{ group: "investigation", label: "Investigation card" },
5754
{ group: "report", label: "Report card" },
5855
{ group: "chart", label: "Chart card" },
59-
<<<<<<< HEAD
6056
{ group: "watches", label: "Watch chips" },
6157
{ group: "watch-card", label: "Watch card" },
6258
{ group: "wakes", label: "Wake banners" },
63-
=======
6459
{ group: "hero", label: "Blank-state hero" },
65-
>>>>>>> origin/feat/dashboard-agent-flows
6660
{ group: "prompts", label: "Suggested prompts" },
6761
{ group: "intents", label: "Intent bubbles" },
6862
{ group: "messages", label: "Message-level states" },
@@ -236,7 +230,6 @@ export const MANIFEST: GallerySection[] = [
236230
},
237231
{ sectionId: "chart-empty", title: "Empty — no data to display", group: "chart" },
238232

239-
<<<<<<< HEAD
240233
// --- Watch chips ---------------------------------------------------------
241234
{ sectionId: "watches-active", title: "Active — cancellable", group: "watches" },
242235
{ sectionId: "watches-fired", title: "Fired", group: "watches" },
@@ -292,7 +285,8 @@ export const MANIFEST: GallerySection[] = [
292285
sectionId: "wake-unknown-watch",
293286
title: "Fired, watch not in hand — kind-agnostic",
294287
group: "wakes",
295-
=======
288+
},
289+
296290
// --- Blank-state hero -----------------------------------------------------
297291
// The new-chat state, with the composer inside the hero. Both widths it ships
298292
// at: the 380px side panel and the fullscreen takeover's centred column.
@@ -320,7 +314,6 @@ export const MANIFEST: GallerySection[] = [
320314
sectionId: "hero-in-chat",
321315
title: "Empty chat — hero without its own composer",
322316
group: "hero",
323-
>>>>>>> origin/feat/dashboard-agent-flows
324317
},
325318

326319
// --- Suggested prompts ---------------------------------------------------

0 commit comments

Comments
 (0)