Skip to content

fix(desktop): welcome banner overlap and missing dismiss control - #5330

Merged
wpfleger96 merged 3 commits into
mainfrom
hayt/welcome-banner-fix
Aug 8, 2026
Merged

fix(desktop): welcome banner overlap and missing dismiss control#5330
wpfleger96 merged 3 commits into
mainfrom
hayt/welcome-banner-fix

Conversation

@wpfleger96

Copy link
Copy Markdown
Member

Problem

The WelcomeComposerGuidanceLayer in the #Welcome channel was positioned with absolute inset-x-0 bottom-full z-[-1] — outside the composerWrapperRef measurement boundary. useComposerHeightPadding observes composerWrapperRef's block size to set paddingBottom on the timeline scroll container, but the absolutely-positioned layer didn't contribute to that size. The banner sat directly on top of the newest message, blocking the thread affordance on that message, and had no manual dismiss control.

Fix

Overlap: Changed WelcomeComposerGuidanceLayer from absolute inset-x-0 bottom-full z-[-1] to relative (in normal flow). As a normal-flow child of composer-dock, the layer's full height is now measured by the ResizeObserver and fed into the timeline's paddingBottom, so the newest message is always fully visible and its thread affordance is always clickable while the banner shows.

Dismiss: Added an X close button (data-testid="welcome-composer-dismiss-button") on the prompt state. Clicking fires onDismiss, which drives dismissing → hidden immediately (same slide-down animation as the auto-dismiss path) and marks the channel ID as completed in the session ref so the banner does not reappear on channel re-entry within the session.

Refactor: Extracted the banner state machine (refs, timers, useEffects, and callbacks) from ChannelPane.tsx into useWelcomeComposerBanner.ts. This keeps ChannelPane.tsx well under the 1000-line file-size ratchet and makes the state machine independently testable.

Changed files

  • desktop/src/features/channels/ui/WelcomeComposerBanner.tsxWelcomeComposerGuidanceLayer positioning fix; onDismiss prop; dismiss button; overflow-hidden / mb-0 / flex-1 cleanup
  • desktop/src/features/channels/ui/ChannelPane.tsx — remove inline banner state machine, use useWelcomeComposerBanner hook, pass onDismiss
  • desktop/src/features/channels/ui/useWelcomeComposerBanner.ts — new hook owning all banner state

The WelcomeComposerGuidanceLayer was positioned absolute/bottom-full
outside the composerWrapperRef measurement boundary, so its height was
invisible to useComposerHeightPadding. The banner sat on top of the
newest message and blocked thread affordances on that message.

There was also no way to dismiss the banner without sending a message
that mentions an agent.

Fix overlap: Change WelcomeComposerGuidanceLayer from
`absolute inset-x-0 bottom-full z-[-1]` to `relative` (in-flow).
Being a normal-flow child of composer-dock, its full height is now
measured by the ResizeObserver and fed into the timeline's
paddingBottom, so the newest message is always fully visible and its
thread affordance is always clickable while the banner shows.

Fix dismiss: Add an X close button on the prompt state that fires
`onDismiss`. The dismiss callback drives `dismissing → hidden`
immediately (same slide-down animation as the auto-dismiss path) and
marks the channel as completed so the banner does not reappear on
channel re-entry within the session.

Extract the banner state machine (refs, timers, effects, callbacks)
into useWelcomeComposerBanner.ts to keep ChannelPane.tsx under the
1000-line file-size ratchet.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96
wpfleger96 requested a review from a team as a code owner August 8, 2026 16:09
…sitioning

expectWelcomeComposerBannerLayout tested geometry from the old
absolute/bottom-full design where the banner's bottom extended past the
composer's top edge. With the guidance layer now in normal flow, the
banner sits entirely above the composer (no overlap) and the guidance
backdrop bottom is strictly less than composerBox.y rather than
approximately equal to it. Remove the z-index comparison — no longer
meaningful once the guidance layer dropped its z-[-1] stacking context.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96 pushed a commit that referenced this pull request Aug 8, 2026

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed on Wes's behalf. One user-visible state mismatch needs fixing before merge: manual dismissal can hide the banner while leaving the kickoff characters floating above the composer. Please couple those states (or suppress dismissal during setup) and cover the manual-dismiss path in E2E.

Comment thread desktop/src/features/channels/ui/WelcomeComposerBanner.tsx Outdated
…fix CI layout assertion

Three fixes folded into one push per review feedback:

1. Wes P1: suppress the dismiss X while settingUp is true. The kickoff
   stage characters are absolutely positioned above the composer; allowing
   dismiss while they are present would hide the banner but leave the
   stage floating with nothing under it until the 90s timeout. The setup
   window is transient so suppressing the X there is the minimal correct
   fix; no teardown coupling needed.

2. E2E coverage (Wes): two new onboarding.spec.ts tests exercise the
   dismiss path that was previously untested:
   - clicking X removes the guidance surface (banner + guidance layer gone)
   - dismiss persists on channel re-entry (completedChannelIdsRef holds)

3. CI fix: expectWelcomeComposerBannerLayout asserted dockBackdropBox.y ≈
   composerBox.y, which was correct when the guidance layer was absolute
   bottom-full (dock only contained the composer). Now that the guidance
   layer is in-flow inside composer-dock, the backdrop's absolute inset-y-0
   spans guidance-layer-top → bottom, so the correct assertion is
   dockBackdropBox.y ≈ guidanceLayerBox.y. Added guidanceLayerBox
   measurement to the helper and updated the assertion accordingly.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96

Copy link
Copy Markdown
Member Author

Screenshots

Before — newest message (bob, 12:21 PM) occluded by the banner; no dismiss

The banner renders absolute bottom-full outside the measured composer area. useComposerHeightPadding only measures composerWrapperRef (the composer overlay div), which doesn't include the absolutely-positioned banner. The banner therefore sits on top of the newest message — its text is hidden and its thread affordance is unreachable.

before

After — all messages visible; × dismiss button shown

The guidance layer now renders in normal document flow inside the composer overlay, so its height is included in the composerWrapperRef measurement. The timeline receives correct bottom clearance. The × button (top-right of the banner) dismisses via the existing dismissing → hidden path and marks the channel complete in completedChannelIdsRef (no reappearance on re-entry).

after

wpfleger96 pushed a commit that referenced this pull request Aug 8, 2026

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at b9fe344 on Wes's behalf. The prior blocker is resolved: the dismiss control is now suppressed while settingUp, so the kickoff stage cannot be orphaned, and the added E2E cases cover manual dismissal plus channel re-entry persistence. I found no new actionable issues in the follow-up delta.

I am leaving this as a comment rather than an approval because Wes did not explicitly delegate approval authority for this PR.

@wpfleger96
wpfleger96 merged commit f029dea into main Aug 8, 2026
22 checks passed
@wpfleger96
wpfleger96 deleted the hayt/welcome-banner-fix branch August 8, 2026 17:00
wpfleger96 added a commit that referenced this pull request Aug 8, 2026
* origin/main:
  fix(desktop): welcome banner overlap and missing dismiss control (#5330)
  fix(desktop): prevent horizontal clipping in Prompt Context modal (#5324)
  chore(release): release Buzz Relay version 0.2.1 (#2856)
  chore(release): release Buzz Desktop version 0.5.8 (#5326)
  fix(buzz-agent): recover from 400-shaped image rejections; unbound benchmark agent rounds (#5318)
  Revert "fix(acp): reject unattended permission requests" (#5323)
  feat(desktop): unify add agent flows (#5015)
  fix(buzz-agent): budget summarizer reasoning separately so it cannot starve the handoff summary (#5248)
  infra: bind development services to loopback (#4871)
  chore(release): release Buzz Desktop version 0.5.7 (#5252)
  fix(desktop): isolate relay admission tests (#5221)
  fix(desktop): externalize boot <style> to prevent Tauri CSP nonce override (#5242)
  fix(desktop): let imported and recovered identities finish onboarding (#5228)

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants