fix(session-ui): restore blue user bubbles with grey pending steers (#57001)

This commit is contained in:
Luke Parker
2026-10-19 17:41:54 +10:00
committed by GitHub
Unverified
parent 518ca745a8
commit e6bd84965b
4 changed files with 61 additions and 42 deletions
@@ -418,7 +418,7 @@ for (const row of [
accent: false,
},
]) {
test(`keeps the user message grey for ${row.name}`, async ({ page }) => {
test(`keeps the user message blue for ${row.name}`, async ({ page }) => {
const inventory: WorktreeDirectory[] = [{ directory: accentRoot }, { directory: accentWorkspace, strategy: "git" }]
const listed = page.waitForResponse(
@@ -464,8 +464,8 @@ for (const row of [
await expectBackground(send, "icon-button-contrast")
const message = page.locator('[data-slot="user-message-text"]')
await expect(message).toHaveText("Check this fixture workspace.")
await expectToken(message, "background-color", "--v2-background-bg-layer-02")
await expectToken(message, "color", "--v2-text-text-base")
await expectToken(message, "background-color", "--v2-blue-100")
await expectToken(message, "color", "--v2-blue-700")
if (!row.accent) return
@@ -946,20 +946,36 @@ for (const delivery of ["steer", "queue"] as const) {
const colors =
delivery === "steer"
? await userRow(page, userID)
.locator('[data-slot="user-message-text"]')
.evaluate((element) => ({
background: getComputedStyle(element).backgroundColor,
text: getComputedStyle(element).color,
}))
? {
delivered: await userRow(page, userID)
.locator('[data-slot="user-message-text"]')
.evaluate((element) => ({
background: getComputedStyle(element).backgroundColor,
text: getComputedStyle(element).color,
})),
pending: await bubble.evaluate((element) => {
const probe = document.createElement("span")
probe.style.backgroundColor = "var(--v2-background-bg-layer-02)"
probe.style.color = "var(--v2-text-text-base)"
element.appendChild(probe)
const colors = {
background: getComputedStyle(probe).backgroundColor,
text: getComputedStyle(probe).color,
}
probe.remove()
return colors
}),
}
: undefined
if (colors) {
// A pending steer shares the delivered bubble, dimmed, and keeps its Pending row in view without hover.
await expect(bubble).toHaveCSS("background-color", colors.background)
await expect(bubble).toHaveCSS("color", colors.text)
await expect(pending.locator('[data-slot="user-message-body"]')).toHaveCSS("opacity", "0.6")
await expect(pending.locator('[data-slot="user-message-body"]')).toHaveCSS("transition-duration", "0s")
// A pending steer is grey, switches to it without a transition, and keeps its Pending row in view without hover.
await expect(bubble).toHaveCSS("background-color", colors.pending.background)
await expect(bubble).toHaveCSS("color", colors.pending.text)
await expect(bubble).toHaveCSS("transition-duration", "0s")
await expect(pending.locator('[data-slot="user-message-copy-wrapper"]')).toHaveCSS("opacity", "1")
await expect(pending.locator('[data-slot="user-message-meta"]')).toHaveText(
/^Pending\s*·\s*Build\s*·\s*Queue Model$/,
@@ -1046,15 +1062,13 @@ for (const delivery of ["steer", "queue"] as const) {
if (colors) {
await expect(bubble).toHaveAttribute("data-delivery-marker", "pending")
await expect(pending.locator('[data-slot="user-message-meta"]')).toHaveText(/^Build\s*·\s*Queue Model$/)
await expect(bubble).toHaveCSS("background-color", colors.background)
await expect(bubble).toHaveCSS("color", colors.text)
// Only delivery animates the dim away; reduced motion switches instantly.
const body = pending.locator('[data-slot="user-message-body"]')
await expect(body).toHaveCSS("transition-property", "opacity")
await expect(body).toHaveCSS("opacity", "1")
await expect(bubble).toHaveCSS("background-color", colors.delivered.background)
await expect(bubble).toHaveCSS("color", colors.delivered.text)
// Only delivery animates the colour; reduced motion switches instantly.
await expect(bubble).toHaveCSS("transition-property", "background-color, color")
await transcript.screenshot({ path: testInfo.outputPath("delivered-steer.png") })
await page.emulateMedia({ reducedMotion: "reduce" })
await expect(body).toHaveCSS("transition-duration", "0s")
await expect(bubble).toHaveCSS("transition-duration", "0s")
}
await expect(transcript.locator('[data-timeline-row="UserMessage"]')).toHaveCount(2)
+1 -1
View File
@@ -2,7 +2,7 @@ import type { Page } from "@playwright/test"
export type PromptPosition = { frame: number; top: number | null }
// User bubbles are neutral grey, so paint them a test-only blue that the frame reader can tell from everything else.
// Paint user bubbles a test-only blue that the frame reader can tell from everything else, whatever the theme colour.
export async function markPrompt(page: Page) {
await page.addStyleTag({ content: '[data-slot="user-message-text"] { background: rgb(0 0 255) !important; }' })
}
@@ -175,6 +175,13 @@
border: none;
padding: 8px 12px;
border-radius: 10px;
transition:
background-color 150ms ease-out,
color 150ms ease-out;
@media (prefers-reduced-motion: reduce) {
transition: none;
}
[data-highlight="file"],
[data-highlight="agent"] {
@@ -185,7 +192,7 @@
}
[data-slot="user-message-mention-prefix"] {
color: var(--v2-text-text-accent);
color: var(--v2-blue-500);
}
max-width: 100%;
@@ -247,23 +254,7 @@
pointer-events: auto;
}
[data-slot="user-message-attachments"],
[data-slot="user-message-body"] {
transition: opacity 150ms ease-out;
@media (prefers-reduced-motion: reduce) {
transition: none;
}
}
/* A pending steer is dimmed and keeps its Pending label and actions in view. Only delivery animates: a steer can
render once before its admission marks it pending, and must not fade down from the delivered look. */
&[data-pending] [data-slot="user-message-attachments"],
&[data-pending] [data-slot="user-message-body"] {
opacity: 0.6;
transition: none;
}
/* A pending steer keeps its Pending label and actions in view. */
&[data-pending] [data-slot="user-message-copy-wrapper"] {
opacity: 1;
pointer-events: auto;
@@ -1459,7 +1450,8 @@
font-weight: 440;
[data-slot="user-message-text"] {
background: var(--v2-background-bg-layer-01);
background: var(--v2-blue-1200);
color: var(--v2-blue-300);
}
[data-slot="user-message-comments"] {
@@ -1501,5 +1493,18 @@
}
:root[data-color-scheme="light"] body [data-component="user-message"] [data-slot="user-message-text"] {
background: var(--v2-background-bg-layer-02);
background: var(--v2-blue-100);
color: var(--v2-blue-700);
}
/* Only delivery animates. A steer can render once before its admission marks it pending, and must not fade from the
delivered color. */
:root body [data-component="user-message"][data-pending] [data-slot="user-message-text"] {
background: var(--v2-background-bg-layer-02);
color: var(--v2-text-text-base);
transition: none;
[data-slot="user-message-mention-prefix"] {
color: currentColor;
}
}