mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 04:47:03 -06:00
fix(ui): contain transcript focus ring (#120693)
This commit is contained in:
committed by
GitHub
parent
51960f6579
commit
f25385fcda
@@ -35,6 +35,25 @@ async function dragAcross(page: Page, locator: Locator): Promise<string> {
|
||||
return page.evaluate(() => globalThis.getSelection()?.toString() ?? "");
|
||||
}
|
||||
|
||||
async function readFocusOutline(locator: Locator) {
|
||||
return locator.evaluate((element) => {
|
||||
const styles = getComputedStyle(element);
|
||||
const colorProbe = document.createElement("span");
|
||||
colorProbe.style.color = "var(--muted-strong)";
|
||||
document.body.append(colorProbe);
|
||||
const mutedStrongColor = getComputedStyle(colorProbe).color;
|
||||
colorProbe.remove();
|
||||
return {
|
||||
focusVisible: element.matches(":focus-visible"),
|
||||
mutedStrongColor,
|
||||
outlineColor: styles.outlineColor,
|
||||
outlineOffset: styles.outlineOffset,
|
||||
outlineStyle: styles.outlineStyle,
|
||||
outlineWidth: styles.outlineWidth,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async function captureUiProof(page: Page, fileName: string) {
|
||||
if (!captureUiProofEnabled) {
|
||||
return;
|
||||
@@ -94,8 +113,36 @@ suite.define(() => {
|
||||
sidebarScrollbar: "6px",
|
||||
});
|
||||
expect(await dragAcross(page, transcript)).toContain("Selectable transcript");
|
||||
const thread = page.locator(".chat-thread");
|
||||
expect(await readFocusOutline(thread)).toMatchObject({
|
||||
focusVisible: false,
|
||||
outlineStyle: "none",
|
||||
});
|
||||
await captureUiProof(page, "01-chat-selectable-transcript.png");
|
||||
|
||||
await thread.focus();
|
||||
await page.keyboard.press("Tab");
|
||||
await expect
|
||||
.poll(() => thread.evaluate((element) => element !== document.activeElement))
|
||||
.toBe(true);
|
||||
await page.keyboard.press("Shift+Tab");
|
||||
await expect
|
||||
.poll(() =>
|
||||
thread.evaluate(
|
||||
(element) => element === document.activeElement && element.matches(":focus-visible"),
|
||||
),
|
||||
)
|
||||
.toBe(true);
|
||||
const focusedOutline = await readFocusOutline(thread);
|
||||
expect(focusedOutline).toMatchObject({
|
||||
focusVisible: true,
|
||||
outlineOffset: "-2px",
|
||||
outlineStyle: "solid",
|
||||
outlineWidth: "2px",
|
||||
});
|
||||
expect(focusedOutline.outlineColor).toBe(focusedOutline.mutedStrongColor);
|
||||
await captureUiProof(page, "02-chat-thread-keyboard-focus.png");
|
||||
|
||||
await page.setViewportSize({ height: 650, width: 1440 });
|
||||
// Appearance renders schema-independent theme/UI sections that overflow
|
||||
// 650px even against the mock gateway's tiny config fixture; General
|
||||
@@ -148,7 +195,7 @@ suite.define(() => {
|
||||
await content.evaluate((element) => {
|
||||
element.scrollTop = Math.min(160, element.scrollHeight - element.clientHeight);
|
||||
});
|
||||
await captureUiProof(page, "02-settings-contextual-scrollbars.png");
|
||||
await captureUiProof(page, "03-settings-contextual-scrollbars.png");
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -316,6 +316,12 @@ openclaw-chat-page {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* The oversized clipped transcript owns its focus ring, so it stays inward to keep every edge visible. */
|
||||
.chat-thread:focus-visible {
|
||||
outline: 2px solid var(--muted-strong);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
:root .chat-thread::-webkit-scrollbar-thumb {
|
||||
background: var(--muted-strong);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user