mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(ui): calm composer focus treatment (#122232)
This commit is contained in:
committed by
GitHub
parent
7a1d5a86c7
commit
6c485842b1
@@ -0,0 +1,84 @@
|
||||
import { expect, it } from "vitest";
|
||||
import { installMockGateway } from "../test-helpers/control-ui-e2e.ts";
|
||||
import { createControlUiE2eSuite } from "./control-ui-e2e-suite.test-support.ts";
|
||||
|
||||
const suite = createControlUiE2eSuite({
|
||||
name: "Control UI chat composer focus",
|
||||
});
|
||||
|
||||
suite.define(() => {
|
||||
it("uses a visible neutral focus treatment in dark and light themes", async () => {
|
||||
await suite.withPage({ viewport: { width: 1440, height: 900 } }, async ({ page }) => {
|
||||
const gateway = await installMockGateway(page);
|
||||
await page.goto(`${suite.server.baseUrl}chat`);
|
||||
await gateway.waitForRequest("chat.startup");
|
||||
|
||||
const composer = page.locator(".agent-chat__input");
|
||||
const textarea = composer.locator("textarea");
|
||||
await composer.waitFor({ state: "visible" });
|
||||
|
||||
for (const theme of ["dark", "light"] as const) {
|
||||
await page.evaluate((nextTheme) => {
|
||||
document.documentElement.dataset.theme = "claw";
|
||||
document.documentElement.dataset.themeMode = nextTheme;
|
||||
}, theme);
|
||||
await textarea.evaluate((element) => element.blur());
|
||||
await page.waitForTimeout(150);
|
||||
const unfocused = await composer.evaluate((element) => {
|
||||
const style = getComputedStyle(element);
|
||||
return { borderColor: style.borderColor, boxShadow: style.boxShadow };
|
||||
});
|
||||
|
||||
await textarea.focus();
|
||||
await page.waitForTimeout(150);
|
||||
const focused = await composer.evaluate((element) => {
|
||||
const style = getComputedStyle(element);
|
||||
const parseRgb = (color: string): [number, number, number] => {
|
||||
const values = color
|
||||
.match(/[\d.]+/g)
|
||||
?.slice(0, 3)
|
||||
.map(Number);
|
||||
if (!values || values.length !== 3) {
|
||||
throw new Error(`expected an RGB color, received ${color}`);
|
||||
}
|
||||
return (
|
||||
color.startsWith("color(srgb") ? values.map((value) => value * 255) : values
|
||||
) as [number, number, number];
|
||||
};
|
||||
const luminance = (color: string): number => {
|
||||
const linearize = (channel: number) => {
|
||||
const normalized = channel / 255;
|
||||
return normalized <= 0.04045
|
||||
? normalized / 12.92
|
||||
: ((normalized + 0.055) / 1.055) ** 2.4;
|
||||
};
|
||||
const channels = parseRgb(color);
|
||||
return (
|
||||
0.2126 * linearize(channels[0]) +
|
||||
0.7152 * linearize(channels[1]) +
|
||||
0.0722 * linearize(channels[2])
|
||||
);
|
||||
};
|
||||
const borderLuminance = luminance(style.borderColor);
|
||||
const surfaceLuminance = luminance(style.backgroundColor);
|
||||
const borderChannels = parseRgb(style.borderColor);
|
||||
const contrast =
|
||||
(Math.max(borderLuminance, surfaceLuminance) + 0.05) /
|
||||
(Math.min(borderLuminance, surfaceLuminance) + 0.05);
|
||||
|
||||
return {
|
||||
borderColor: style.borderColor,
|
||||
boxShadow: style.boxShadow,
|
||||
contrast,
|
||||
neutralChannelSpread: Math.max(...borderChannels) - Math.min(...borderChannels),
|
||||
};
|
||||
});
|
||||
|
||||
expect(focused.borderColor).not.toBe(unfocused.borderColor);
|
||||
expect(focused.boxShadow).not.toBe(unfocused.boxShadow);
|
||||
expect(focused.neutralChannelSpread).toBeLessThanOrEqual(24);
|
||||
expect(focused.contrast).toBeGreaterThanOrEqual(3);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -2358,8 +2358,12 @@ openclaw-chat-video-player {
|
||||
}
|
||||
|
||||
.agent-chat__input:focus-within {
|
||||
border-color: color-mix(in srgb, var(--accent) 30%, var(--border));
|
||||
box-shadow: 0 0 0 3px var(--accent-subtle);
|
||||
/* Focus is a neutral state, not an accent/status signal. This mix clears 3:1
|
||||
against the composer surface in both claw themes; the halo keeps it legible. */
|
||||
border-color: color-mix(in srgb, var(--muted) 72%, var(--border));
|
||||
box-shadow:
|
||||
0 0 0 3px color-mix(in srgb, var(--muted) 14%, transparent),
|
||||
var(--shadow-sm);
|
||||
}
|
||||
|
||||
.agent-chat__input--prefill-attention {
|
||||
|
||||
Reference in New Issue
Block a user