Skip to content

ui: refresh dashboard-v2 theme and visual styles#36856

Closed
BunsDev wants to merge 1 commit intodashboard-v2-structurefrom
dashboard-v2-theme
Closed

ui: refresh dashboard-v2 theme and visual styles#36856
BunsDev wants to merge 1 commit intodashboard-v2-structurefrom
dashboard-v2-theme

Conversation

@BunsDev
Copy link
Copy Markdown
Member

@BunsDev BunsDev commented Mar 5, 2026

Summary

  • Problem: the dashboard-v2 visual overhaul is hard to review when mixed with the structural refactor.
  • Why it matters: reviewers should be able to inspect the styling and asset refresh separately from behavior changes.
  • What changed: this stacked PR isolates the theme tokens, layout/component/chat/config CSS refresh, plus the updated HTML metadata and icons.
  • What did NOT change (scope boundary): no new behavior/state wiring beyond what landed in the base structure PR.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • Dashboard-v2 styling, theme presentation, layout polish, and icon metadata are refreshed.

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local dev checkout
  • Model/provider: N/A
  • Integration/channel (if any): Control UI
  • Relevant config (redacted): default local UI build

Steps

  1. Check out dashboard-v2-theme.
  2. Run pnpm ui:build.
  3. Confirm the Control UI bundle builds successfully with the refreshed styles.

Expected

  • The theme/style branch builds successfully.

Actual

  • pnpm ui:build passed.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: successful pnpm ui:build on dashboard-v2-theme.
  • Edge cases checked: N/A
  • What you did not verify: browser-based UI Vitest flows and manual UI interaction.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert this PR branch.
  • Files/config to restore: affected ui/src/styles/**, ui/index.html, and ui/public/* files from the previous stacked branch.
  • Known bad symptoms reviewers should watch for: broken styling, unreadable layouts, or missing icon/meta assets.

Risks and Mitigations

  • Risk: the style refresh depends on the DOM/class structure from the base dashboard-v2 refactor.
    • Mitigation: this PR is stacked directly on dashboard-v2-structure and does not add new behavior changes.

Review Guidance

@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot Bot commented Mar 5, 2026

🔒 Aisle Security Analysis

We found 1 potential security issue(s) in this PR:

# Severity Title
1 🟡 Medium Phishing/UI deception risk: automatic blurring of link text via chat-link-tail-blur class

1. 🟡 Phishing/UI deception risk: automatic blurring of link text via chat-link-tail-blur class

Property Value
Severity Medium
CWE CWE-451
Location ui/src/styles/chat/text.css:49-56

Description

The UI introduces a new CSS rule that blurs the rendered text of certain links in chat messages, only revealing the link on hover/focus.

This becomes security-relevant because the class is applied automatically during markdown sanitization for any anchor whose href contains the substring "tail" (attacker-controllable within markdown link destinations):

  • Input (attacker-controlled): chat markdown content can include arbitrary links (e.g. [text](https://attacker.example/detail) contains tail).
  • Transformation: toSanitizedMarkdownHtml() sanitizes with DOMPurify and then adds chat-link-tail-blur based on href contents.
  • Effect: .chat-link-tail-blur applies filter: blur(4px) to the entire anchor element, obscuring the visible destination.
  • Impact: enables UI deception/phishing patterns in chat—users may click a blurred link without being able to visually verify the destination. On touch devices (no hover), the blur may never be removed before navigation.

Vulnerable behavior (CSS):

.chat-text :where(a.chat-link-tail-blur) {
  filter: blur(4px);
}

Relevant application logic (not in diff but activates the new CSS):

if (href.toLowerCase().includes("tail")) {
  node.classList.add("chat-link-tail-blur");
}

Notes:

  • Direct XSS via javascript:/data: links appears mitigated by DOMPurify + tests; this issue is primarily social engineering / UI misrepresentation.

Recommendation

Avoid obscuring link destinations in security-relevant contexts (chat content is adversary-controllable).

Suggested mitigations (pick one):

  1. Remove the blur behavior entirely, or restrict it to non-clickable text.

  2. If the goal is to hide only part of a long URL, render the link with explicit markup (e.g., wrap only the tail in a <span>), and ensure the destination is still inspectable on touch devices:

// Example idea: render as <a><span class="url-host">…</span><span class="url-tail">…</span></a>
.chat-text a .url-tail { filter: blur(4px); }
.chat-text a:focus-visible .url-tail,
.chat-text a:hover .url-tail { filter: blur(0); }
  1. Provide an always-visible indicator of the true destination (e.g., show hostname next to the link, or show the URL in a long-press/click-to-reveal popover) and consider requiring an explicit user action to reveal before opening on touch devices.

Additionally, if you keep any conditional styling, do not base it on attacker-controlled substrings like href.includes("tail"); instead use explicit metadata from trusted code paths.


Analyzed PR: #36856 at commit 9dcdb8b

Last updated on: 2026-03-05T23:45:04Z

Copy link
Copy Markdown

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

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: 3e2e5dacbb

ℹ️ 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/index.html
Comment on lines +16 to +18
var t = s && s.theme;
if (t && VALID.indexOf(t) !== -1) {
document.documentElement.setAttribute("data-theme", t);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Resolve stored theme selection before setting data-theme

This bootstrap script reads openclaw.control.settings.v1.theme and applies it directly as data-theme, but settings now persist theme family ("claw" | "knot" | "dash") plus themeMode (see ui/src/ui/storage.ts / ui/src/ui/theme.ts). As a result, the prepaint theme is wrong for most users (e.g. claw/knot are ignored, and dash + light mode is forced to dark dash), so the page flashes to a different theme once the app initializes and calls resolveTheme.

Useful? React with 👍 / 👎.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 5, 2026

Greptile Summary

This PR isolates the visual/theme refresh for dashboard-v2 into a standalone stacked branch, keeping it separate from the structural refactor. It introduces a multi-family theme system in base.css (dark, light, openknot/openknot-light, dash/dash-light, clawdash), adds new chat-component CSS (agent-chat.css), refreshes layout, component, config, glass, and mobile styles, and adds a pre-render theme script in index.html to prevent flash-of-unstyled-content.

Key Issues Found:

  • The pre-render VALID allowlist in index.html includes "openai", which has no matching [data-theme="openai"] CSS rule and no LEGACY_MAP entry in theme.ts — it is effectively dead code that silently no-ops for affected users.
  • "clawdash" is in the VALID list and has a CSS definition (chrome metallic), but theme.ts maps the raw value "clawdash""dash-light" via LEGACY_MAP, so users with that value stored in localStorage will experience a visible theme flash as the pre-render chrome-metallic style is immediately overwritten by the warm-parchment dash-light resolved theme.

The new base.css token architecture (foundation → semantic alias layer → per-theme decorative overrides) is clean and well-commented.

Confidence Score: 2/5

  • Not safe to merge until the ui/index.html pre-render theme allowlist is reconciled with both base.css theme definitions and theme.ts LEGACY_MAP entries.
  • Two concrete issues block this PR: (1) a stale "openai" theme name in the allowlist that silently fails to apply any styles, and (2) a "clawdash" mismatch that causes a visible theme flash for users with that legacy localStorage value. Neither breaks the build, but both represent user-visible failures or regressions in the theme system. The CSS architecture itself is sound and well-designed.
  • ui/index.html — the VALID theme allowlist needs to be reconciled with both base.css theme definitions and the resolved theme names in theme.ts before merging.

Last reviewed commit: 3e2e5da

Comment thread ui/index.html
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<script>
(function () {
var VALID = ["dark", "light", "openknot", "dash", "openai", "clawdash"];
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.

The VALID allowlist includes "openai", but there is no matching [data-theme="openai"] CSS rule in base.css and no entry for "openai" in the LEGACY_MAP in theme.ts. If a user has { theme: "openai" } in localStorage, this script will write data-theme="openai" to the root element, but no CSS will match it, causing a silent fallback to the dark theme defaults. This entry should either be removed or mapped via LEGACY_MAP to an actual defined theme (e.g., "dark").

Suggested change
var VALID = ["dark", "light", "openknot", "dash", "openai", "clawdash"];
var VALID = ["dark", "light", "openknot", "dash", "clawdash"];
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/index.html
Line: 13

Comment:
The `VALID` allowlist includes `"openai"`, but there is no matching `[data-theme="openai"]` CSS rule in `base.css` and no entry for `"openai"` in the `LEGACY_MAP` in `theme.ts`. If a user has `{ theme: "openai" }` in localStorage, this script will write `data-theme="openai"` to the root element, but no CSS will match it, causing a silent fallback to the dark theme defaults. This entry should either be removed or mapped via `LEGACY_MAP` to an actual defined theme (e.g., `"dark"`).

```suggestion
        var VALID = ["dark", "light", "openknot", "dash", "clawdash"];
```

How can I resolve this? If you propose a fix, please make it concise.

Comment thread ui/index.html
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<script>
(function () {
var VALID = ["dark", "light", "openknot", "dash", "openai", "clawdash"];
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.

"clawdash" is in the VALID list and has a matching [data-theme="clawdash"] CSS definition in base.css (chrome metallic theme, lines 391–445). However, theme.ts maps the raw value "clawdash" via LEGACY_MAP (line 26) to { theme: "dash", mode: "light" }, which resolves to the "dash-light" theme (warm parchment colors, lines 333–387) — a completely different palette. Users with "clawdash" stored in localStorage will see the chrome metallic style (from the pre-render) immediately flash to warm parchment (when JS hydrates and resolves to "dash-light").

Either remove [data-theme="clawdash"] from base.css and replace "clawdash" in the VALID list with "dash-light" (if it is truly a legacy alias), or remove the LEGACY_MAP entry and treat "clawdash" as a first-class theme.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/index.html
Line: 13

Comment:
`"clawdash"` is in the `VALID` list and has a matching `[data-theme="clawdash"]` CSS definition in `base.css` (chrome metallic theme, lines 391–445). However, `theme.ts` maps the raw value `"clawdash"` via `LEGACY_MAP` (line 26) to `{ theme: "dash", mode: "light" }`, which resolves to the `"dash-light"` theme (warm parchment colors, lines 333–387) — a completely different palette. Users with `"clawdash"` stored in localStorage will see the chrome metallic style (from the pre-render) immediately flash to warm parchment (when JS hydrates and resolves to `"dash-light"`).

Either remove `[data-theme="clawdash"]` from `base.css` and replace `"clawdash"` in the `VALID` list with `"dash-light"` (if it is truly a legacy alias), or remove the `LEGACY_MAP` entry and treat `"clawdash"` as a first-class theme.

How can I resolve this? If you propose a fix, please make it concise.

@BunsDev BunsDev force-pushed the dashboard-v2-theme branch from 3e2e5da to 9dcdb8b Compare March 5, 2026 23:33
@BunsDev BunsDev force-pushed the dashboard-v2-structure branch from dac2c5c to 1f1f444 Compare March 5, 2026 23:33
Copy link
Copy Markdown

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

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: 9dcdb8b4d3

ℹ️ 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".


.cmd-palette__item:hover,
.cmd-palette__item--active {
background: var(--hover);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use a defined token for command palette row highlighting

cmd-palette__item:hover/--active sets background: var(--hover), but this commit does not define --hover in the theme tokens (the palette tokens in ui/src/styles/base.css define --bg-hover instead). Because var(--hover) is unresolved, the declaration is dropped, so hover and keyboard-active command palette rows have no visual highlight, which makes result selection hard to track.

Useful? React with 👍 / 👎.

@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui size: XL maintainer Maintainer-authored PR labels Mar 6, 2026
@BunsDev BunsDev marked this pull request as draft March 9, 2026 23:21
@BunsDev BunsDev closed this Mar 18, 2026
@BunsDev
Copy link
Copy Markdown
Member Author

BunsDev commented Mar 18, 2026

Triaged this PR alongside #36857. The base branch diverged ~3,135 commits from main/ui/touch-ups.

The FOUC-prevention concept from index.html was rewritten for the current theme system and applied to ui/touch-ups. The prototype pollution fix from the stacked PR #36857 was also applied.

All CSS rewrites and production TS deletions were discarded — the deleted files and gutted modules are still actively used on the current branch. See #36857 comment for the full breakdown.

@BunsDev BunsDev deleted the dashboard-v2-theme branch April 7, 2026 00:40
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 maintainer Maintainer-authored PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant