Skip to content

feat(ui): redesign dashboard chrome with tiny top bar and sidebar search#101497

Merged
steipete merged 3 commits into
mainfrom
claude/competent-bell-2e1cc2
Jul 7, 2026
Merged

feat(ui): redesign dashboard chrome with tiny top bar and sidebar search#101497
steipete merged 3 commits into
mainfrom
claude/competent-bell-2e1cc2

Conversation

@steipete

@steipete steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

The Control UI window chrome had grown noisy and scattered. The top bar spent 52px on controls that do not belong there: a search button, a terminal button styled as a heavy bordered circle, and a three-way light/dark/system toggle. Meanwhile the sidebar collapse button hid in the bottom-right corner of the sidebar footer, where nobody expects a sidebar toggle. In the macOS app, the OpenClaw mascot in the native titlebar strip rendered on a shadowed plate that looked like a misplaced card, because a box-shadow was applied to a transparent SVG.

Why This Change Was Made

The chrome now follows the layout conventions users already know from macOS apps and tools like Linear/Slack: a tiny top bar that only carries navigation (sidebar toggle + breadcrumb + quiet terminal toggle), a search field at the top of the sidebar as the command palette entry point, and personal/utility controls (color mode, settings, docs, pairing) grouped in the sidebar footer. The sidebar toggle is a macOS-style panel button at the left edge of the top bar; on drawer viewports (≤1100px) the same slot drives the slide-over drawer. The brand mark now renders bare, since any shadow/background behind a transparent SVG reads as a floating plate.

Along the way this fixes a real a11y bug: the theme buttons referenced a missing common.colorModeOption i18n key, so tooltips and aria-labels literally announced "common.colorModeOption". The dead .theme-orb legacy styles were removed. Net diff is negative (‑60 lines of non-generated code).

User Impact

  • The top bar shrinks from 52px to 44px and only contains the sidebar toggle, breadcrumb, and (when available) a quiet terminal toggle.
  • Search is more discoverable: a labeled field with a ⌘K hint at the top of the sidebar opens the command palette; the collapsed rail keeps an icon-only entry. ⌘K still works everywhere.
  • Light/dark/system switching lives in the sidebar footer on all viewports (previously desktop-only in the top bar, mobile-only in the sidebar).
  • The sidebar collapse toggle sits where users look for it — top-left, macOS style — and doubles as the drawer toggle on tablet/mobile.
  • macOS app: the mascot in the titlebar strip no longer sits on a shadowed plate.
  • Screen readers now get "Color mode: Light/Dark/System" instead of a raw i18n key.

Evidence

Full-page, light and dark (1440×880, live gateway):

Before After
before light after light
before dark after dark

Top bar detail (search + theme trio gone, panel toggle added left):

Before After
before topbar after topbar

Sidebar footer (collapse toggle out, color-mode toggle in):

Before After
before footer after footer

Collapsed rail, dark:

Before After
before rail after rail

macOS titlebar brand mark (simulated native strip; shadow plate removed):

Before After
before brand after brand

Validation:

  • Interactive proof against a live local gateway via the Vite dev UI: sidebar search opens the command palette; the top bar toggle collapses/expands the rail on desktop and opens the drawer at ≤1100px; theme switching works from the footer in expanded, rail (vertical stack), and drawer modes; terminal ghost button verified with terminalAvailable forced on; phone width (390px) checked.
  • ui/src/e2e/sidebar-customization.e2e.test.ts extended: sidebar search opens/closes the palette, the collapse toggle is asserted to live in the top bar, and the rail keeps the icon-only search entry; the existing collapse-persistence and drawer flows keep passing against the same accessible names.
  • pnpm ui:i18n:sync + pnpm ui:i18n:check clean after adding the missing common.colorModeOption key (locale bundles regenerate with tracked English fallbacks).
  • pnpm check:changed (Blacksmith Testbox): guard lanes green; the warning-only "test temp creation report" lane failed with origin/main...HEAD: no merge base because the branch was not pushed yet — infra-side, rerun after push in CI.
  • Codex autoreview (gpt-5.5, local diff): clean, no accepted/actionable findings.
  • Artifact manifest with SHA-256 for all screenshots: https://artifacts.openclaw.ai/control-ui-chrome-redesign/20260707/artifact-manifest.json

Move the sidebar toggle to the top bar as a macOS-style panel button
(collapse on desktop, drawer on tablet/mobile), move search into a
sidebar field that opens the command palette, and move the color-mode
toggle into the sidebar footer. Shrink the top bar to 44px, make the
terminal toggle a quiet ghost button, and drop the shadow plate behind
the macOS titlebar brand mark so the transparent mascot renders bare.
Adds the missing common.colorModeOption i18n key (theme buttons were
announcing the raw key) and removes the dead theme-orb styles.
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation app: web-ui App: web-ui size: L maintainer Maintainer-authored PR labels Jul 7, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1adc842986

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ui/src/app/app-host.ts
context.navigation.update({
navCollapsed: !navCollapsed,
})}
.onOpenPalette=${this.openPalette}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Keep focus out of the closed drawer

On ≤1100px drawer viewports, this palette trigger now lives inside .shell-nav; passing openPalette directly lets the command palette save the drawer search button as the previously focused element. When the user selects a nav/session result, navigate() closes the drawer and then the palette restores focus back to that offscreen .sidebar-search, stranding keyboard/screen-reader users in the hidden drawer instead of returning them to the topbar drawer trigger. Wrap this path so opening from the drawer closes/focuses the drawer trigger first, or make palette focus restoration skip hidden drawer triggers.

Useful? React with 👍 / 👎.

The i18n sync initially recorded English fallbacks for the new key,
which the ships-no-recorded-English-fallbacks gate rejects. Regenerated
with a real translation provider; all 20 locales now carry translated
values (fallbacks=0).
@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge. Reviewed July 7, 2026, 5:00 AM ET / 09:00 UTC.

Summary
The branch moves Control UI search, color-mode, terminal, and sidebar-collapse chrome between the top bar and sidebar, adds the missing color-mode i18n key across generated locales, updates docs, and extends sidebar E2E coverage.

PR surface: Source -94, Tests +14, Docs 0. Total -80 across 71 files.

Reproducibility: yes. Source inspection shows that clicking sidebar search in a drawer saves that hidden drawer button as the palette restore target, and palette selection then closes the drawer before restoring focus.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: persistent cache schema: ui/src/i18n/.i18n/ar.tm.jsonl, persistent cache schema: ui/src/i18n/.i18n/de.tm.jsonl, persistent cache schema: ui/src/i18n/.i18n/es.tm.jsonl, persistent cache schema: ui/src/i18n/.i18n/fa.tm.jsonl, persistent cache schema: ui/src/i18n/.i18n/fr.tm.jsonl, persistent cache schema: ui/src/i18n/.i18n/hi.tm.jsonl, and 14 more. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🦞 diamond lobster ✨ media proof bonus
Patch quality: 🦐 gold shrimp
Result: needs maintainer review before merge.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Fix drawer-origin command-palette focus restoration and add an E2E assertion for selecting a palette result from an open drawer.

Risk before merge

  • [P1] Drawer search currently restores focus to an offscreen sidebar control after palette navigation until the focus path is fixed.

Maintainer options:

  1. Decide the mitigation before merge
    Keep the chrome redesign direction, but make drawer-origin palette opens restore focus to the topbar drawer trigger or skip hidden drawer triggers, with E2E coverage for selecting a palette result from an open drawer.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P2] A narrow automated repair can adjust the sidebar palette focus path and add the missing drawer E2E assertion without a product decision.

Security
Cleared: The diff is limited to Control UI code, docs, styles, tests, icons, and generated i18n output; I found no concrete security or supply-chain concern.

Review findings

  • [P2] Keep palette focus out of the closed drawer — ui/src/app/app-host.ts:738
Review details

Best possible solution:

Keep the chrome redesign direction, but make drawer-origin palette opens restore focus to the topbar drawer trigger or skip hidden drawer triggers, with E2E coverage for selecting a palette result from an open drawer.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection shows that clicking sidebar search in a drawer saves that hidden drawer button as the palette restore target, and palette selection then closes the drawer before restoring focus.

Is this the best way to solve the issue?

No. Moving search into the sidebar is a reasonable UI direction, but the implementation needs a focus-safe drawer opener or hidden-target-aware palette restoration before merge.

Full review comments:

  • [P2] Keep palette focus out of the closed drawer — ui/src/app/app-host.ts:738
    On drawer viewports, the new sidebar search button opens the command palette while focus is inside .shell-nav. Selecting a palette result calls navigate(), which closes the drawer, and then the palette restores focus to the saved sidebar search button, leaving keyboard/screen-reader focus in the hidden drawer. Please either close/focus the drawer trigger before opening from the drawer or make palette restoration ignore hidden drawer targets, and cover this drawer-origin path in the sidebar E2E.
    Confidence: 0.9

Overall correctness: patch is incorrect
Overall confidence: 0.87

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 13c1d3c4083a.

Label changes

Label changes:

  • add P2: The PR is a normal user-facing UI improvement with a concrete but limited accessibility regression in the drawer command-palette path.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes before/after screenshot artifacts and live local-gateway interaction notes; I inspected the manifest and sample PNGs, though this proof does not cover the drawer focus bug.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (linked_artifact): The PR body includes before/after screenshot artifacts and live local-gateway interaction notes; I inspected the manifest and sample PNGs, though this proof does not cover the drawer focus bug.

Label justifications:

  • P2: The PR is a normal user-facing UI improvement with a concrete but limited accessibility regression in the drawer command-palette path.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (linked_artifact): The PR body includes before/after screenshot artifacts and live local-gateway interaction notes; I inspected the manifest and sample PNGs, though this proof does not cover the drawer focus bug.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes before/after screenshot artifacts and live local-gateway interaction notes; I inspected the manifest and sample PNGs, though this proof does not cover the drawer focus bug.
Evidence reviewed

PR surface:

Source -94, Tests +14, Docs 0. Total -80 across 71 files.

View PR surface stats
Area Files Added Removed Net
Source 69 366 460 -94
Tests 1 14 0 +14
Docs 1 2 2 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 71 382 462 -80

Acceptance criteria:

  • [P1] pnpm test ui/src/e2e/sidebar-customization.e2e.test.ts.
  • [P1] pnpm check:changed -- ui/src/app/app-host.ts ui/src/components/app-sidebar.ts ui/src/components/command-palette.ts ui/src/e2e/sidebar-customization.e2e.test.ts.

What I checked:

  • Drawer search opens the palette from inside the sidebar: At the PR head, OpenClawShell passes this.openPalette directly into openclaw-app-sidebar; the sidebar search button invokes that callback from inside .shell-nav. (ui/src/app/app-host.ts:738, a0e9daead56c)
  • Palette focus restoration still targets the opener: command-palette.ts saves document.activeElement and restores it after item selection, so a drawer-origin sidebar search button remains the final restoration target unless the opener path changes. (ui/src/components/command-palette.ts:158, a0e9daead56c)
  • Navigation closes the drawer before palette restore runs: navigate() calls closeNavDrawer({ restoreFocus: true }), then palette selection calls restoreFocus(), leaving two scheduled focus restorations where the later one can focus the now-hidden sidebar search button. (ui/src/app/app-host.ts:491, a0e9daead56c)
  • Real behavior proof inspected: The artifact manifest lists before/after screenshots, and downloaded after-light-full and after-dark-collapsed PNGs are valid 2880x1760 images, supporting the visible chrome change but not the drawer focus edge case.
  • UI scoped policy applied: The UI scoped guide treats non-English locale bundles and .i18n files as generated output and says to update English plus run the i18n sync pipeline; this PR follows that shape rather than hand-maintaining only generated files. (ui/AGENTS.md:5, 13c1d3c4083a)
  • Current-main focus path provenance: Current-main blame attributes the drawer navigation helpers and command-palette focus restoration to commit 6e6d1aa, which is the local source history for the behavior this PR composes with. (ui/src/app/app-host.ts:486, 6e6d1aac4cbe)

Likely related people:

What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. labels Jul 7, 2026
One button drives both modes: rail collapse on desktop and the
slide-over drawer at the ≤1100px breakpoint, decided via matchMedia
(with the legacy addListener fallback used elsewhere in bootstrap).
Replaces the previous pair of CSS-swapped buttons.
@steipete
steipete merged commit 5a234d6 into main Jul 7, 2026
76 checks passed
@steipete
steipete deleted the claude/competent-bell-2e1cc2 branch July 7, 2026 09:57
@steipete

steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 8, 2026
…rch (openclaw#101497)

* feat(ui): redesign dashboard chrome with tiny top bar and sidebar search

Move the sidebar toggle to the top bar as a macOS-style panel button
(collapse on desktop, drawer on tablet/mobile), move search into a
sidebar field that opens the command palette, and move the color-mode
toggle into the sidebar footer. Shrink the top bar to 44px, make the
terminal toggle a quiet ghost button, and drop the shadow plate behind
the macOS titlebar brand mark so the transparent mascot renders bare.
Adds the missing common.colorModeOption i18n key (theme buttons were
announcing the raw key) and removes the dead theme-orb styles.

* fix(ui): translate common.colorModeOption across locale bundles

The i18n sync initially recorded English fallbacks for the new key,
which the ships-no-recorded-English-fallbacks gate rejects. Regenerated
with a real translation provider; all 20 locales now carry translated
values (fallbacks=0).

* refactor(ui): unify the topbar sidebar toggle into one button

One button drives both modes: rail collapse on desktop and the
slide-over drawer at the ≤1100px breakpoint, decided via matchMedia
(with the legacy addListener fallback used elsewhere in bootstrap).
Replaces the previous pair of CSS-swapped buttons.
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
…rch (openclaw#101497)

* feat(ui): redesign dashboard chrome with tiny top bar and sidebar search

Move the sidebar toggle to the top bar as a macOS-style panel button
(collapse on desktop, drawer on tablet/mobile), move search into a
sidebar field that opens the command palette, and move the color-mode
toggle into the sidebar footer. Shrink the top bar to 44px, make the
terminal toggle a quiet ghost button, and drop the shadow plate behind
the macOS titlebar brand mark so the transparent mascot renders bare.
Adds the missing common.colorModeOption i18n key (theme buttons were
announcing the raw key) and removes the dead theme-orb styles.

* fix(ui): translate common.colorModeOption across locale bundles

The i18n sync initially recorded English fallbacks for the new key,
which the ships-no-recorded-English-fallbacks gate rejects. Regenerated
with a real translation provider; all 20 locales now carry translated
values (fallbacks=0).

* refactor(ui): unify the topbar sidebar toggle into one button

One button drives both modes: rail collapse on desktop and the
slide-over drawer at the ≤1100px breakpoint, decided via matchMedia
(with the legacy addListener fallback used elsewhere in bootstrap).
Replaces the previous pair of CSS-swapped buttons.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui docs Improvements or additions to documentation maintainer Maintainer-authored PR P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. size: L status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant