revert(web): restore previous composer banners - #8733
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
| const overflowCandidates = visibleGroupedEntries.filter( | ||
| (entry) => entry.agentSpawn === undefined, | ||
| ); |
There was a problem hiding this comment.
🟡 Medium chat/MessagesTimeline.logic.ts:934
Error-toned entries can be placed in hiddenEntries and disappear behind the generic toggle, while hasFailure remains false when a later tool entry succeeds. This removes the visible and accessibility indication of the failed operation; exclude error entries from the overflow candidates so they are always rendered.
| const overflowCandidates = visibleGroupedEntries.filter( | |
| (entry) => entry.agentSpawn === undefined, | |
| ); | |
| const overflowCandidates = visibleGroupedEntries.filter( | |
| (entry) => entry.agentSpawn === undefined && entry.tone !== "error", | |
| ); |
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/components/chat/MessagesTimeline.logic.ts around lines 934-936:
Error-toned entries can be placed in `hiddenEntries` and disappear behind the generic toggle, while `hasFailure` remains `false` when a later tool entry succeeds. This removes the visible and accessibility indication of the failed operation; exclude error entries from the overflow candidates so they are always rendered.
| const offset = event.key === "ArrowDown" ? 1 : -1; | ||
| const normalizedIndex = currentIndex >= 0 ? currentIndex : offset === 1 ? -1 : 0; | ||
| const nextIndex = (normalizedIndex + offset + entries.length) % entries.length; | ||
| setHighlightedId(entries[nextIndex]?.id ?? null); |
There was a problem hiding this comment.
🟡 Medium chat/ComposerStashMenu.tsx:90
Arrow-key navigation updates highlightedId without scrolling the selected CommandItem into view, so with a max-h-64 list the item that Enter will restore can move below the viewport and remain invisible. Restore the selected-row scrollIntoView behavior (or equivalent) when highlightedId changes.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/components/chat/ComposerStashMenu.tsx around line 90:
Arrow-key navigation updates `highlightedId` without scrolling the selected `CommandItem` into view, so with a `max-h-64` list the item that `Enter` will restore can move below the viewport and remain invisible. Restore the selected-row `scrollIntoView` behavior (or equivalent) when `highlightedId` changes.
| <div className="min-h-0 overflow-hidden"> | ||
| <div | ||
| className={cn( | ||
| "invisible pointer-events-none space-y-2 pb-2 opacity-0", |
There was a problem hiding this comment.
🟠 High chat/ComposerBannerStack.tsx:152
On touch-only devices, stacked banners remain inaccessible: the expanded list is gated by group-hover/group-focus-within, while the collapsed cap has pointer-events-none and the banners are visibility: hidden. This prevents users from reaching actions such as the background-work Stop button when another banner is in front. Restore a touch-activatable expansion control or provide a non-hover path to reveal the stack.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/components/chat/ComposerBannerStack.tsx around line 152:
On touch-only devices, stacked banners remain inaccessible: the expanded list is gated by `group-hover`/`group-focus-within`, while the collapsed cap has `pointer-events-none` and the banners are `visibility: hidden`. This prevents users from reaching actions such as the background-work `Stop` button when another banner is in front. Restore a touch-activatable expansion control or provide a non-hover path to reveal the stack.
There was a problem hiding this comment.
UI Consistency — 4 findings
This revert restores the pre-primitive composer markup. Most of it is a faithful rollback, but a few keyboard/AT affordances that existed on main do not come back, and the shared attached-drawer contract is now duplicated across call sites.
ComposerBannerStack.tsx— stacked banners become hover-only; thegroup-focus-withinpath is unreachable because the region isvisibility: hidden.ComposerStashMenu.tsx— arrow navigation no longer scrolls the highlighted row into view or moves focus, and rows are no longer focusable/labelled controls.ThreadSyncStatusPill.tsx(+ 4 other call sites) — the attached-drawer surface geometry is now copy-pasted rather than owned by one component.ComposerPlanFollowUpBanner.tsx— commented-out JSX reintroduced.
None of these block the rollback itself; they are the parts of the reverted behavior worth keeping or re-adding.
Posted via Macroscope — UI Consistency
| <div className="min-h-0 overflow-hidden"> | ||
| <div | ||
| className={cn( | ||
| "invisible pointer-events-none space-y-2 pb-2 opacity-0", | ||
| "translate-y-1 transform-gpu transition-[opacity,transform] duration-150 ease-out will-change-[opacity,transform]", | ||
| "group-hover/banner-stack:visible group-hover/banner-stack:pointer-events-auto group-hover/banner-stack:translate-y-0 group-hover/banner-stack:opacity-100", | ||
| "group-focus-within/banner-stack:visible group-focus-within/banner-stack:pointer-events-auto group-focus-within/banner-stack:translate-y-0 group-focus-within/banner-stack:opacity-100", | ||
| )} |
There was a problem hiding this comment.
Stacked banners are now reachable by hover only. The collapsed cap is aria-hidden + pointer-events-none, and this region stays invisible (visibility: hidden) until group-focus-within — but a visibility-hidden subtree is removed from the tab order, so focus can never enter and group-focus-within:* can never fire. Keyboard and coarse-pointer users lose access to every stacked banner and to its actions/dismiss buttons; the version being reverted exposed a real Peek button (aria-expanded / aria-controls, Escape to collapse) for exactly this.
Smallest fix: keep a focusable trigger that toggles an explicit stackExpanded state and drive visibility from that state instead of group-hover/group-focus-within alone.
Posted via Macroscope — UI Consistency
| {/* <div className="mt-2 text-xs text-muted-foreground"> | ||
| Review the plan | ||
| </div> */} |
There was a problem hiding this comment.
Commented-out JSX is reintroduced here; it has no owner and will silently rot.
</div>
- {/* <div className="mt-2 text-xs text-muted-foreground">
- Review the plan
- </div> */}
</div>Posted via Macroscope — UI Consistency
| return ( | ||
| <div | ||
| aria-label={label} | ||
| className="chat-composer-drawer-surface chat-composer-drawer-attached chat-composer-drawer-slot pointer-events-none flex items-center gap-2 px-3 pt-2 pb-[calc(var(--chat-composer-attachment-overlap)_+_0.375rem)] text-foreground text-xs font-medium sm:px-4" | ||
| data-thread-sync-drawer="true" | ||
| role="status" |
There was a problem hiding this comment.
The attached-drawer contract (chat-composer-drawer-surface chat-composer-drawer-attached chat-composer-drawer-slot plus the pb-[calc(var(--chat-composer-attachment-overlap)_+_0.375rem)] overlap padding) is now hand-copied here and in ComposerBannerStack, ComposerStashMenu, ComposerCommandMenu, and ChatComposer's top drawer, with the overlap padding spelled as an arbitrary calc() in two of them. That is durable shared geometry with five owners, which is what drifts first.
If the rollback stands, a one-component wrapper for the surface classes (call sites keeping only layout/padding) would preserve the revert while keeping a single owner for the seam.
Posted via Macroscope — UI Consistency
| const currentIndex = entries.findIndex((entry) => entry.id === highlightedId); | ||
| const offset = event.key === "ArrowDown" ? 1 : -1; | ||
| const normalizedIndex = currentIndex >= 0 ? currentIndex : offset === 1 ? -1 : 0; | ||
| const nextIndex = (normalizedIndex + offset + entries.length) % entries.length; | ||
| setHighlightedId(entries[nextIndex]?.id ?? null); |
There was a problem hiding this comment.
ArrowUp/ArrowDown now only update highlightedId. The removed scrollIntoView({ block: "nearest" }) / focus() calls were what kept the highlighted entry inside the max-h-64 scroll region and moved real focus onto the row. Combined with rows rendering as non-focusable CommandItems (no per-row restore button, no accessible name, no aria-activedescendant), keyboard users can highlight entries that stay scrolled out of view and assistive tech is never told which entry is active.
Smallest fix: scroll the highlighted row into view when it changes (e.g. drawerRef.current?.querySelector('[data-stash-entry="…"]')?.scrollIntoView({ block: "nearest" })) and keep the restore action as a focusable, labelled control per row.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6aa5498. Configure here.
| "translate-y-1 transform-gpu transition-[opacity,transform] duration-150 ease-out will-change-[opacity,transform]", | ||
| "group-hover/banner-stack:visible group-hover/banner-stack:pointer-events-auto group-hover/banner-stack:translate-y-0 group-hover/banner-stack:opacity-100", | ||
| "group-focus-within/banner-stack:visible group-focus-within/banner-stack:pointer-events-auto group-focus-within/banner-stack:translate-y-0 group-focus-within/banner-stack:opacity-100", | ||
| )} |
There was a problem hiding this comment.
Stacked banners unreachable on touch
Medium Severity
The restored stack only reveals hidden banners via group-hover and group-focus-within. The peek cap is pointer-events-none and aria-hidden, so there is no tap target. When the front item is urgent and has no actions (for example the reconnecting notice), touch users cannot reach banners behind it, including background-liveness Stop.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 6aa5498. Configure here.
| dismissLabel: "Dismiss update notice", | ||
| onDismiss: () => { | ||
| if (updateFailed) { | ||
| dismissServerUpdateFailure(serverUpdateState); |
There was a problem hiding this comment.
Failed update banner cannot dismiss
Medium Severity
A failed server update always shows in the stack, but dismiss is omitted whenever updateFailed is true, and Retry is omitted when versionMismatch is missing. That can leave a persistent error banner with no action until update state clears on its own.
Reviewed by Cursor Bugbot for commit 6aa5498. Configure here.
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This is a large production composer and timeline refactor that changes default banner stacking, keyboard/touch access, update failure handling, and shared layout geometry. Unresolved accessibility and failure-state concerns remain in these normal user paths. Not approved because:
Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more. |
## What's Changed * revert(web): restore previous composer banners by @t3dotgg in pingdotgg/t3code#8733 **Full Changelog**: pingdotgg/t3code@v0.0.37-nightly.20260830.1225...v0.0.37-nightly.20260830.1226 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.37-nightly.20260830.1226
## What's Changed * Remove Messages Glass Lab experiment by @juliusmarminge in pingdotgg/t3code#8599 * Require human review for pull requests changing product defaults by @juliusmarminge in pingdotgg/t3code#8603 * fix(codex): avoid quadratic app-server input buffering by @juliusmarminge in pingdotgg/t3code#8605 * fix(mobile): stabilize iOS header item transitions by @juliusmarminge in pingdotgg/t3code#8607 * chore(mobile): upgrade to Expo SDK 57 by @juliusmarminge in pingdotgg/t3code#8609 * fix(mobile): harden native header toolbar items by @juliusmarminge in pingdotgg/t3code#8611 * fix(server): stop querying Claude context usage after turns by @t3dotgg in pingdotgg/t3code#8610 * chore: vouch ryanrhughes by @t3dotgg in pingdotgg/t3code#8613 * feat(web): attach PDFs, ZIPs, and other files to a turn by @t3dotgg in pingdotgg/t3code#8236 * feat(web): keybinding settings as settings rows by @StiensWout in pingdotgg/t3code#8532 * feat: let an environment publish themes as a file by @ryanrhughes in pingdotgg/t3code#8569 * fix(web): clean up provider settings list and editor by @StiensWout in pingdotgg/t3code#8504 * fix(web): keep project picker popup inside the sidebar by @SunkenInTime in pingdotgg/t3code#8627 * fix(mobile): prevent header overflow and back-button artifacts by @juliusmarminge in pingdotgg/t3code#8624 * fix(server): retry automatic thread title generation by @Bil0000 in pingdotgg/t3code#8087 * fix(client-runtime): refresh edited pull request comments by @Bil0000 in pingdotgg/t3code#8094 * fix(web): four composer spacing defects by @Bil0000 in pingdotgg/t3code#8090 * perf(desktop): skip duplicate browser updates by @Bil0000 in pingdotgg/t3code#8018 * fix(web): render nested markdown images correctly by @flamboh in pingdotgg/t3code#8501 * fix(web): unify activity logs and composer banners by @juliusmarminge in pingdotgg/t3code#8693 * fix(mobile): reduce dev-client reload and Metro startup cost by @juliusmarminge in pingdotgg/t3code#8694 * revert(web): restore previous composer banners by @t3dotgg in pingdotgg/t3code#8733 * test(web): remove tests for unreachable helpers by @t3-code[bot] in pingdotgg/t3code#8738 * feat(mobile): update tool summaries and chat transitions by @juliusmarminge in pingdotgg/t3code#8793 * feat(web): play video attachments in chat by @Bil0000 in pingdotgg/t3code#8688 * fix(web,mobile): snooze menu no longer offers the same wake time twice by @vitalyiegorov in pingdotgg/t3code#8741 * fix(grok): allow model changes in existing threads by @ahmed-besic in pingdotgg/t3code#8392 * feat(mobile): pick, share, and receive files in threads by @t3dotgg in pingdotgg/t3code#8237 * fix(web): reduce title bar scroll fade height by @maria-rcks in pingdotgg/t3code#8799 * fix(windows): strip quotes from repaired PATH by @UtkarshUsername in pingdotgg/t3code#8746 * fix(web): open agent images in expanded preview by @maria-rcks in pingdotgg/t3code#8807 * fix(git): follow repository instructions in generated source control text by @maria-rcks in pingdotgg/t3code#8804 * fix(server): stop overpricing cached Claude tokens by @SunkenInTime in pingdotgg/t3code#8806 * fix(web): keep image preview above sidebar control by @maria-rcks in pingdotgg/t3code#8811 * fix(web): keep right panel synced with agent edits by @maria-rcks in pingdotgg/t3code#8803 * fix(web,mobile): render Codex citations and artifact templates by @Yash-Singh1 in pingdotgg/t3code#8584 * chore: add Windows setup script to t3.json by @UtkarshUsername in pingdotgg/t3code#8814 * fix(web): fold interim turn responses by @maria-rcks in pingdotgg/t3code#8828 * fix(web): use circle alert for failed tool calls by @maria-rcks in pingdotgg/t3code#8840 * feat(mobile): add offline iPhone voice input by @t3dotgg in pingdotgg/t3code#8614 * fix(web): prevent pull request metadata overlap by @MatthewFeroz in pingdotgg/t3code#8790 ## New Contributors * @ryanrhughes made their first contribution in pingdotgg/t3code#8569 * @ahmed-besic made their first contribution in pingdotgg/t3code#8392 * @MatthewFeroz made their first contribution in pingdotgg/t3code#8790 **Full Changelog**: pingdotgg/t3code@v0.0.36...v0.0.37 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.37


#8693 moved Compact and dismiss controls into the title row and reduced the banner edge padding. The controls no longer align with the full title and description block.
This fully reverts commit
3d32797f6f4614205debf8a61f09e950f5f9a81cand restores the previous composer banners and activity logs.Tests not run, as requested.
Made with GPT-5.6 Sol in the Codex harness.
Note
Medium Risk
Large composer and banner refactor affects scroll padding, notice stacking, and in-flight turn UX, but stays in presentation-layer React/CSS with added unit tests.
Overview
Reworks the chat composer layout by removing the
ComposerSurface/ComposerBannerlayer and driving the glass shell, drawers, and shoulder tabs with shared CSS classes and simpler markup (BranchToolbarcontext strip included).System notices move out of
ChatComposer:ComposerBannerStacknow sits above the composer inChatView, built on the sharedAlertUI with hover/focus stack expansion (variant-colored peek cap). Banner ordering is assembled inChatView—urgent system items first, background liveness in the middle so Stop stays reachable, then calmer notices—using anurgentflag instead of in-stack priority sorting. Server-update banners use inline titles plusServerUpdateProgress, and failed-update dismissal is folded into version-mismatch dismiss.Activity shifts to the timeline and tabs: composer “working/sync” rows and
ComposerActivityStatusare removed; an in-timeline working row getsworkingStepLabelandactiveTurnStartedAt. Thread sync usesThreadSyncStatusPillbeside the stack. Plan/task progress for the shoulder tab comes fromactiveThreadShell.planProgress, with per-turn dismiss on the tasks tab/drawer.Scroll/layout fixes:
shoulderTabReservesubtracts shoulder-tab height from composer overlay clearance (with aMutationObserverwhen tabs mount), and stash/tasks render as attached shoulder tabs with inline fallbacks when drawers or external banners occupy the top.Reviewed by Cursor Bugbot for commit 6aa5498. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Replace
ComposerBannersystem withAlert-based stack and addWorkingTimelineRowtoMessagesTimelineComposerBanner.*component family across composer UI;ComposerBannerStacknow usesAlert/Buttonwith hover/focus CSS expansion, and drawers (ComposerStashMenu,ComposerCommandMenu) render in plaindivwrappers with glass-surface classesworkingrow variant toMessagesTimelinewith a self-tickingWorkingTimerand optionalThinkingActivityRow; work-log overflow collapses afterMAX_VISIBLE_WORK_LOG_ENTRIES = 1visible entry behind a+N previous …toggleChatComposerviadismissedTasksTurnId, hiding task progress/steps for the active turn until the thread advancesThreadSyncStatusPillas an accessible status indicator for loading/syncing phases, andshoulderTabReserveto adjust composer overlay clearance for shoulder tabsderiveWorkLogEntriesnow includesturn.plan.updatedactivities instead of filtering them outChatComposerPropsremovesbannerItems,isWorking,activeWorkStartedAt, andthreadSyncPhase, replacing them withexternalDrawerAttached;ComposerTasksBadgenow requiresonDismissandhasTrailingShoulderprops.versionSkew.tsremovesisServerUpdateFailureDismissedanddismissServerUpdateFailureexports.ComposerPendingApprovalPanelrenders adivinstead ofspan, which may change wrapping behavior in surrounding markup.📊 Macroscope summarized 6aa5498. 17 files reviewed, 3 issues evaluated, 0 issues filtered, 3 comments posted
🗂️ Filtered Issues