Skip to content

Commit 8251c40

Browse files
fix(ui): align activity error badges (#100163)
Co-authored-by: Peter Steinberger <[email protected]>
1 parent 851156a commit 8251c40

3 files changed

Lines changed: 63 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Docs: https://docs.openclaw.ai
3131

3232
### Fixes
3333

34+
- **Control UI activity alignment:** keep tool-call bubbles and per-tool error badges on one consistent right edge across desktop and narrow chat layouts.
3435
- **Status signal:** omit the redundant `Plugins: OK` row from compact `/status` output while retaining actionable plugin-health warnings and detailed plugin status.
3536
- **Control UI terminal rendering:** adopt the shared `@openclaw/libterminal` browser lifecycle and add Nerd Font fallbacks so icon-enabled shell listings render their glyphs when a compatible local font is installed.
3637
- **Slack transcript history:** let Codex app-server own its persisted assistant replies so Slack does not append redundant delivery-mirror rows, while the Control UI keeps legacy duplicate mirrors hidden.

ui/src/pages/chat/chat-responsive.browser.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,43 @@ function iconSvg() {
8282
return `<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14M5 12h14"></path></svg>`;
8383
}
8484

85+
function activityErrorAlignmentHtml() {
86+
return `
87+
<div class="chat-thread" role="log">
88+
<div class="chat-thread-inner">
89+
<div class="chat-group tool chat-group--activity">
90+
<div class="chat-avatar tool">A</div>
91+
<div class="chat-group-messages">
92+
<div class="chat-activity-group is-open">
93+
<button class="chat-activity-group__summary chat-activity-group__summary--error" type="button">
94+
<span class="chat-activity-group__icon">${iconSvg()}</span>
95+
<span class="chat-activity-group__label">Activity: 2 tools</span>
96+
<span class="chat-activity-group__preview">Bash, Gateway</span>
97+
<span class="chat-activity-group__badge">${iconSvg()}<span>Error</span></span>
98+
</button>
99+
<div class="chat-activity-group__body">
100+
<div class="chat-bubble" data-activity-call-bubble>
101+
<div class="chat-text">Bash searched a deliberately long workspace path with enough detail to occupy the activity row and expose mismatched width constraints.</div>
102+
</div>
103+
<div class="chat-bubble chat-bubble--tool-shell">
104+
<div class="chat-tool-msg-collapse">
105+
<button class="chat-tool-msg-summary chat-tool-msg-summary--error" type="button">
106+
<span class="chat-tool-msg-summary__icon">${iconSvg()}</span>
107+
<span class="chat-tool-msg-summary__label">Tool error</span>
108+
<span class="chat-tool-msg-summary__names">Bash</span>
109+
<span class="chat-tool-msg-summary__error-badge">${iconSvg()}<span>Error</span></span>
110+
</button>
111+
</div>
112+
</div>
113+
</div>
114+
</div>
115+
</div>
116+
</div>
117+
</div>
118+
</div>
119+
`;
120+
}
121+
85122
function chatBubbleActionsHtml() {
86123
return `
87124
<div class="chat-bubble-actions">
@@ -456,6 +493,27 @@ describeBrowserLayout("chat responsive browser layout", () => {
456493
}
457494
});
458495

496+
it.each([
497+
[430, 720],
498+
[1366, 900],
499+
] as const)("right-aligns activity errors with call bubbles at %sx%s", async (width, height) => {
500+
const page = await openBrowserPage(width, height);
501+
try {
502+
await page.setContent(
503+
`<!doctype html><html><head><style>${readUiCss()}</style></head><body>${activityErrorAlignmentHtml()}</body></html>`,
504+
);
505+
506+
await expectNoHorizontalOverflow(page);
507+
const callBubble = await getRect(page, "[data-activity-call-bubble]");
508+
const errorSummary = await getRect(page, ".chat-tool-msg-summary--error");
509+
const errorBadge = await getRect(page, ".chat-tool-msg-summary__error-badge");
510+
expect(Math.abs(callBubble.right - errorSummary.right)).toBeLessThanOrEqual(1);
511+
expect(Math.abs(errorBadge.right - (errorSummary.right - 8))).toBeLessThanOrEqual(1);
512+
} finally {
513+
await closeBrowserPage(page);
514+
}
515+
});
516+
459517
it.each([
460518
[1120, 740],
461519
[1366, 900],

ui/src/styles/chat/tool-cards.css

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,11 +554,14 @@
554554
}
555555

556556
/* ── Activity group (a turn's run of tool rows) ── */
557-
.chat-group--activity .chat-group-messages {
557+
/* Keep the activity summary, call bubbles, and flat result rows on one width.
558+
Include the role classes so this wins over the generic tool-group rule. */
559+
.chat-group.tool.chat-group--activity .chat-group-messages {
558560
max-width: min(760px, 100%);
559561
}
560562

561563
.chat-activity-group {
564+
width: 100%;
562565
min-width: 0;
563566
max-width: 100%;
564567
}

0 commit comments

Comments
 (0)