authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-08-30 22:21:12-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-30 22:21:12-07:00
log3f62e6fa65c2a2a91a367be4ee95da1b50007bde
tree7324e9dfd92c915133c35d1d2104c15a0d3dbfd3
parent9842518c9a0af14fb3a3e90993692a6e34032682
signature Signed by PGP key B5690EEEBB952194

fix(web): widen sync banners and simplify the working timer (#8855)


4 files changed, 6 insertions(+), 36 deletions(-)

apps/web/src/components/ChatView.tsx-16
......@@ -2435,21 +2435,6 @@ function ChatViewContent(props: ChatViewProps) {
24352435 () => deriveActivePlanState(threadActivities, activeLatestTurn?.turnId ?? undefined),
24362436 [activeLatestTurn?.turnId, threadActivities],
24372437 );
2438 // Current step for the in-chat working row: only for the running turn's own
2439 // plan (deriveActivePlanState falls back to older turns' plans, which must
2440 // not label fresh work). Falls back to the first pending step so an
2441 // all-pending freshly written plan labels the row, matching the composer and
2442 // the server's planProgress.
2443 const workingStepLabel = useMemo(() => {
2444 if (!activePlan || activePlan.turnId !== (activeLatestTurn?.turnId ?? null)) {
2445 return null;
2446 }
2447 return (
2448 activePlan.steps.find((step) => step.status === "inProgress")?.step ??
2449 activePlan.steps.find((step) => step.status === "pending")?.step ??
2450 null
2451 );
2452 }, [activeLatestTurn?.turnId, activePlan]);
24532438 const showPlanFollowUpPrompt = shouldShowPlanFollowUpPrompt({
24542439 pendingUserInputCount: pendingUserInputs.length,
24552440 interactionMode,
......@@ -7240,7 +7225,6 @@ function ChatViewContent(props: ChatViewProps) {
72407225 onOpenAgents={addAgentsSurface}
72417226 key={activeThread.id}
72427227 isWorking={isWorking}
7243 workingStepLabel={workingStepLabel}
72447228 activeTurnStartedAt={activeWorkStartedAt}
72457229 listRef={legendListRef}
72467230 timelineEntries={timelineEntries}
apps/web/src/components/chat/ChatComposer.tsx+1-8
......@@ -3439,14 +3439,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
34393439 />
34403440 {!activityStackItem && (props.threadSyncPhase || inlineTasksBadge) ? (
34413441 <ComposerBanner.Attachment>
3442 <ComposerBanner.Root
3443 width={
3444 props.threadSyncPhase && !showComposerTopDrawer && !isComposerCollapsedMobile
3445 ? "content"
3446 : "fill"
3447 }
3448 data-chat-composer-activity-strip="true"
3449 >
3442 <ComposerBanner.Root data-chat-composer-activity-strip="true">
34503443 {props.threadSyncPhase ? (
34513444 <ComposerActivityRow phase={props.threadSyncPhase} />
34523445 ) : (
apps/web/src/components/chat/MessagesTimeline.tsx+1-12
......@@ -171,8 +171,6 @@ interface TimelineRowActivityState {
171171 isWorking: boolean;
172172 isRevertingCheckpoint: boolean;
173173 latestTurnId: TurnId | null;
174 /** Current plan step label for the working row, when the turn has a plan. */
175 workingStepLabel: string | null;
176174}
177175
178176const TimelineRowCtx = createContext<TimelineRowSharedState>(null!);
......@@ -227,7 +225,6 @@ interface MessagesTimelineProps {
227225 agentPanelModel?: AgentPanelModel;
228226 onOpenAgents?: () => void;
229227 isWorking: boolean;
230 workingStepLabel?: string | null;
231228 activeTurnStartedAt: string | null;
232229 listRef: React.RefObject<LegendListRef | null>;
233230 timelineEntries: ReturnType<typeof deriveTimelineEntries>;
......@@ -273,7 +270,6 @@ interface MessagesTimelineProps {
273270
274271export const MessagesTimeline = memo(function MessagesTimeline({
275272 isWorking,
276 workingStepLabel = null,
277273 activeTurnStartedAt,
278274 agentPanelModel = EMPTY_AGENT_PANEL_MODEL,
279275 onOpenAgents = NOOP_OPEN_AGENTS,
......@@ -583,9 +579,8 @@ export const MessagesTimeline = memo(function MessagesTimeline({
583579 isWorking,
584580 isRevertingCheckpoint,
585581 latestTurnId: latestTurn?.turnId ?? null,
586 workingStepLabel,
587582 }),
588 [isRevertingCheckpoint, isWorking, latestTurn?.turnId, workingStepLabel],
583 [isRevertingCheckpoint, isWorking, latestTurn?.turnId],
589584 );
590585
591586 // Stable renderItem — no closure deps. Row components read shared state
......@@ -1323,7 +1318,6 @@ function ProposedPlanTimelineRow({
13231318}
13241319
13251320function WorkingTimelineRow({ row }: { row: Extract<TimelineRow, { kind: "working" }> }) {
1326 const { workingStepLabel } = use(TimelineRowActivityCtx);
13271321 return (
13281322 <div>
13291323 <div className="border-b border-border/60 pb-2 pt-1">
......@@ -1337,11 +1331,6 @@ function WorkingTimelineRow({ row }: { row: Extract<TimelineRow, { kind: "workin
13371331 "Working..."
13381332 )}
13391333 </span>
1340 {workingStepLabel ? (
1341 <span className="ml-2 min-w-0 truncate text-muted-foreground/55">
1342 · {workingStepLabel}
1343 </span>
1344 ) : null}
13451334 </div>
13461335 </div>
13471336 {row.showThinking ? (
docs/user/composer.md+4
......@@ -37,6 +37,10 @@ when starting a thread or changing an existing thread's model.
3737
3838## Notices above the composer
3939
40On web and desktop, loading and syncing statuses fill the available banner width beside the
41stash tab. Task progress appears above the composer, while the timeline's working timer shows
42only elapsed time.
43
4044On web and desktop, additional notices peek out above the attached banner. Hover over the peek
4145to reveal them, or focus **Show other notices** with `Tab` and press `Enter` or `Space`. Press
4246`Escape` to close the stack and return focus to that control. On a touchscreen, tap the peek to