Skip to content

improve: polish hub title bar, notifications, and chat UI - #1041

Merged
shanselman merged 17 commits into
openclaw:mainfrom
karkarl:karkarl-literate-robot
Jul 21, 2026
Merged

improve: polish hub title bar, notifications, and chat UI#1041
shanselman merged 17 commits into
openclaw:mainfrom
karkarl:karkarl-literate-robot

Conversation

@karkarl

@karkarl karkarl commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

The hub title bar and app notification banner did not match Windows 11 / GitHub Copilot app conventions ahead of the release. The pane toggle and logo were separate, the back button sat away from the search box, the right-side status and notification buttons had heavy resting fills, and the notification banner pushed the title bar and nav content down when it appeared.

Why This Change Was Made

Restyle the hub title bar into a single, familiar layout and convert the notification banner to a standard floating WinUI InfoBar so it overlays content instead of shifting it. This is UI-only polish; no behavior, capability, or data paths change.

User Impact

  • The lobster logo now doubles as the pane toggle: hovering it reveals a DockLeft panel icon (GitHub Copilot style).
  • The back button is a chevron placed directly left of a centered search box (Teams style).
  • Title-bar icon buttons have a subtle hover/pressed affordance.
  • The right-side status/error pill is transparent at rest (keeps its border for the dropdown); the notification bell is a true borderless subtle button.
  • The notification banner is a native WinUI InfoBar that floats over the top-right of the content area (right ~2/5), wraps long messages into a taller banner, and never pushes the title bar or nav content down.

Evidence

Dark-mode isolated instance at PR head. The banner is shown in its Error state (expected "device token mismatch" in isolation), floating over the Connection page content:

Title bar and floating InfoBar in dark mode
image
image

Change Type

  • Refactor
  • Bug fix
  • Feature
  • Docs or instructions
  • Tests or validation
  • Security hardening
  • Chore or infrastructure

Scope

  • Tray or WinUI UX

Validation (eb07b6c, integrated with main at 2fb1da2)

Run on Windows x64, Debug, at final integrated head:

Handler accumulation regression tests (3/3 pass)

  • EnsureThemeCallback_100Renders_SingleStoredCallback: 100 render passes, single stored callback verified
  • EnsureThemeCallback_LatestState_StoredCorrectly: latest per-render state captured correctly
  • TrackThemedBrushes_ControlBackground_ReRendersWithoutAccumulation: Button BackgroundResource modifier works through renderer

Real Behavior Proof

  • Environment tested: Windows 11 ARM64, isolated tray instance (run-app-local.ps1 -Isolated), dark theme.
  • PR head or commit tested: e005d3d (original screenshots), eb07b6c (current integrated head).
  • Exact steps or command run: ./build.ps1; launch isolated; deep-link openclaw://hub to open the hub window.
  • Evidence after fix: screenshots above (captured by PR author at e005d3d).
  • Observed result: merged lobster/pane toggle at top-left, chevron back directly left of the centered search box, transparent-at-rest right-side buttons (pill keeps its border, bell is borderless), and the native InfoBar floating over the right portion of the content without displacing the title bar or nav.
  • Screenshot or artifact links verified? Yes (raw URL returns HTTP 200 image/png).
  • Not verified or blocked: Isolated instance blocks hub behind first-run setup wizard. Connected chat timeline not exercised (isolated instance cannot pair). Computer-use proof attempt confirmed setup wizard blocks hub deep-link in fresh isolated instances.

Security Impact

  • New permissions or capabilities? No
  • Secrets or tokens handling changed? No
  • New or changed network calls? No
  • Command or tool execution surface changed? No
  • Data access scope changed? No

Compatibility and Migration

  • Backward compatible? Yes
  • Config or environment changes? No
  • Migration needed? No

Review Conversations

  • I replied to or resolved every bot review conversation addressed by this PR.
  • I left unresolved only conversations that still need maintainer judgment.

Fix: Event Handler Accumulation (b3916e9)

Problem

7 sites in the chat components subscribed ActualThemeChanged + Loaded inside .Set() lambdas that run on every render pass, causing linear handler accumulation per keystroke.

Solution

  • Added Theme.EnsureThemeCallback(control, action): a ConditionalWeakTable-based utility that subscribes once per control and stores/replaces the latest callback (invoked immediately and on theme/load events).
  • Extended ApplyModifiers + ReapplyThemedBrushes to handle Control.BackgroundResourceKey, so Buttons can use .BackgroundResource(...) for theme-tracked backgrounds.
  • Replaced all 7 ad-hoc subscriptions: constant-key cases use the modifier path; conditional/gradient cases use EnsureThemeCallback.
  • Removed dead RootGrid Row 1 (InfoBar relocated to overlay).

Integration with #1036 (eb07b6c)

Merged origin/main (squashed #1036 at 2fb1da2) into PR branch. Auto-merged cleanly across overlapping chat files (ChatRoot, Timeline, Composer). Verified:

Non-blocking note

#1036's new compaction rows use the legacy themeBrush() snapshot pattern (pre-existing in #1036, follow-up recommended to migrate to Ref(...)).

calebeden and others added 16 commits July 20, 2026 14:55
Handle exact /new, /reset, and /compact commands through lifecycle RPCs, preserve structured compaction boundaries, and retain safe compatibility behavior for older gateways.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c41e789a-73e3-41ae-ac62-1ff5287599c0
Match the WinUI standard of pinning Settings to the very bottom of the
navigation pane. Moves the Settings NavigationViewItem out of MenuItems
into FooterMenuItems, placed after Diagnostics. Navigation still resolves
via both collections and the high-contrast icon swap already covers footer
items, so behavior is unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Drop the default button stroke and elevation depth from the three
zero-state prompt suggestions (Say hi, What can you do?, Give me a quick
tour of OpenClaw), keeping only a light, low-opacity fill at rest via
SubtleFillColorSecondaryBrush. Rounded corners, padding, and hover
feedback are unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The composer read as light gray on a dark chat surface and its fade
gradient stayed white because FunctionalUI resolved theme brushes by
walking the app-level ThemeDictionaries, which do not surface WinUI's
XamlControlsResources framework brushes. Controls rendering dark fell
back to the light Application.Resources snapshot.

Fixes, using only built-in WinUI theme resources (no hardcoded colors,
no C# theme helper):

- App.xaml: re-declare the exact framework brush keys the chat uses in
  the Default/Light/HighContrast theme dictionaries, each aliasing its
  built-in color token via ThemeResource. Values are identical but now
  reachable by the per-theme walk, so they flip correctly.
- FunctionalUI: resolve foreground/background/border resource brushes
  against the control's ActualTheme and re-apply reactively on
  ActualThemeChanged/Loaded so brushes flip on a runtime light/dark
  switch.
- Composer: send/stop glyphs and fills, session-picker rows, and the
  welcome suggestion buttons resolve against ActualTheme instead of
  snapshotting the app theme; the fade gradient derives from the
  now-correct base-surface brush so it fades into the dock in dark.
- Timeline: timestamp/helper captions resolve TextFillColorSecondary
  for the timeline root's ActualTheme so they stay legible in dark.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve explicit session selection and failed composer sends, retain live entries during authoritative reloads, widen compaction metrics, and clarify lifecycle timeout recovery.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c41e789a-73e3-41ae-ac62-1ff5287599c0
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c41e789a-73e3-41ae-ac62-1ff5287599c0
Merge the pane toggle into the lobster logo (hover reveals a DockLeft
panel icon), move the back button to a chevron directly left of a
centered search box, and give the title-bar icon buttons a subtle
hover/pressed affordance.

Make the right-side status/error pill transparent at rest (border kept
for its dropdown) and the notification bell a true borderless subtle
button. Convert the app notification banner to a native WinUI InfoBar
with Title/Message and a standard ActionButton, and float it over the
top-right of the content area (right ~2/5) so it never pushes the title
bar or nav content down. Long messages wrap and grow the banner taller.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c41e789a-73e3-41ae-ac62-1ff5287599c0
ResolveColor threw InvalidOperationException when a raw WinUI color token was absent, which happens in minimal hosts (including the UI test surfaces) that seed only the paired '<key>Brush'. The chat timeline resolves TextFillColorSecondary during render, so the throw aborted the whole mount and the timeline rendered no ItemsRepeater, failing the chat proof tests. Fall back to the paired brush's color before throwing; both forms resolve to the same value in production. Adds a regression test covering the brush-color fallback and the still-missing-token throw.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…) lambdas

Replace 7 repeated event subscriptions inside .Set() render paths with:
- Theme.EnsureThemeCallback: ConditionalWeakTable-based single-subscription
  utility that stores and replaces the latest callback per control, invoking
  it immediately and on theme/load events (once, never accumulating).
- FunctionalUI modifier path (.BackgroundResource / .Background(Ref(...))):
  for constant resource keys on Borders and Buttons, reuse the existing
  TrackThemedBrushes mechanism which already guards first-time subscription.
- Control.Background support in ApplyModifiers + ReapplyThemedBrushes: the
  narrow renderer extension needed for Button backgrounds.

Also remove the dead RootGrid Row 1 (formerly the InfoBar, now floating
in Row 1 as an overlay).

Regression tests prove:
- 100 EnsureThemeCallback calls store exactly one callback (latest state)
- FunctionalUI renderer applies BackgroundResource to Controls correctly

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 103120e9-d856-456c-885c-1ffd529b8746
The composer scrim derived its color by reading .Color off the framework
SolidBackgroundFillColorBaseBrush out of the visual tree, so its
{ThemeResource} re-resolved against the ambient light app theme and the
fade read white (#F3F3F3) on a dark page.

Add a dedicated ChatComposerFadeBrush to App.xaml ThemeDictionaries with
literal per-theme colors (dark #202020, light #F3F3F3, high-contrast
follows SystemColorWindowColor) and resolve it as a whole brush per
ElementTheme, so it flips correctly and stays aligned with the composer
dock fill. App-defined theme dictionaries are reachable by the
FunctionalUI theme walk; framework primitives are not.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Integrate openclaw#1040 demand-loaded history (LoadHistoryCoreAsync split, generation
CTS, connection version guards) with PR openclaw#1036 authoritative reload path.

Resolve provider conflicts preserving both connection-versioned history
flights and authoritative reload pending queue.

Address review findings:
- Replace hardcoded 'New session' with localized Chat_PendingNewSessionTitle
  across all 5 locales (en-us, fr-fr, nl-nl, zh-cn, zh-tw)
- Fix authoritative reload dropping valid live entries without OpenClawSeq
  when gateway clock skews behind local time: entries with no seq are now
  preserved since history coverage cannot be determined
- Add post-timeout session list reconciliation for /new failures so user
  can see potentially-created sessions (protocol has no idempotency key;
  guidance message retained by design)
- Add behavioral composer submission policy tests (reference equality,
  identity preservation, edit-during-send)
- Add behavioral pending selection survival test for stale snapshots

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d2982ca8-bb56-4728-85bd-29542ce9d554
The _authoritativeHistoryReloadPending flag was consumed in
LoadHistoryCoreAsync's finally block without checking whether the
completing request belonged to the current connection generation.
A stale old-generation completion after disconnect/reconnect could
consume the flag and trigger an unintended authoritative reload
in the newer generation.

Fix:
- Only consume/schedule the pending authoritative reload when
  requestConnectionVersion == _historyConnectionVersion (same
  guard as _historyInFlight removal)
- Clear _authoritativeHistoryReloadPending in
  AdvanceHistoryGenerationLocked so generation advances invalidate
  stale pending flags
- Add deterministic regression test:
  StaleGenerationAuthoritativeReload_DoesNotReloadInNewGeneration

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d2982ca8-bb56-4728-85bd-29542ce9d554
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 4f0e93ff-d320-454d-b00a-865dac727d0c
@clawsweeper

clawsweeper Bot commented Jul 21, 2026

Copy link
Copy Markdown

ClawSweeper status: review started.

I am starting a fresh review of this pull request: improve: polish hub title bar, notifications, and chat UI This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

@clawsweeper

clawsweeper Bot commented Jul 21, 2026

Copy link
Copy Markdown

ClawSweeper status: review started.

I am starting a fresh review of this pull request: improve: polish hub title bar, notifications, and chat UI This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

@shanselman
shanselman merged commit 4d09797 into openclaw:main Jul 21, 2026
14 checks passed
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.

3 participants