fix: harden workbench sidebar resizing
Merge #348: add right hardware sidebar resize state and expand source/build Playwright layout coverage for #278 without changing M3 control paths or claiming DEV-LIVE hardware acceptance.
This commit is contained in:
@@ -1054,6 +1054,27 @@ export async function runDevCloudWorkbenchLayoutSmoke(args = {}) {
|
||||
summary: "Mobile layout disables the drag handle as a hit target and keeps the drawer/collapse flow reachable without horizontal overflow.",
|
||||
observations: mobile.resize
|
||||
},
|
||||
{
|
||||
id: "layout-right-sidebar-resize-desktop",
|
||||
status: desktop.rightResize?.pass ? "pass" : "blocked",
|
||||
viewport: desktop.rightResize?.viewport ?? desktop.expanded.viewport,
|
||||
summary: "Desktop right hardware sidebar resize supports pointer drag, keyboard bounds, localStorage v1 restore, and keeps Code Agent plus M3 controls reachable.",
|
||||
observations: desktop.rightResize
|
||||
},
|
||||
{
|
||||
id: "layout-right-sidebar-resize-narrow-desktop",
|
||||
status: narrowDesktop.rightResize?.pass ? "pass" : "blocked",
|
||||
viewport: narrowDesktop.rightResize?.viewport ?? narrowDesktop.expanded.viewport,
|
||||
summary: "Narrow desktop disables the right-sidebar drag handle while the stacked M3 hardware area remains reachable without outer page scroll.",
|
||||
observations: narrowDesktop.rightResize
|
||||
},
|
||||
{
|
||||
id: "layout-right-sidebar-resize-mobile",
|
||||
status: mobile.rightResize?.pass ? "pass" : "blocked",
|
||||
viewport: mobile.rightResize?.viewport ?? mobile.collapsed.viewport,
|
||||
summary: "Mobile disables the right-sidebar drag handle so it cannot cover M3 tabs, Code Agent input, or the hardware status area.",
|
||||
observations: mobile.rightResize
|
||||
},
|
||||
{
|
||||
id: "layout-gate-desktop",
|
||||
status: desktop.gate.currentRoute.pass ? "pass" : "blocked",
|
||||
@@ -2158,11 +2179,30 @@ function hasSidebarCollapseContract({ html, app, styles }) {
|
||||
/--explorer-width:\s*292px/u.test(styles) &&
|
||||
/--explorer-min-width:\s*220px/u.test(styles) &&
|
||||
/--explorer-max-width:\s*420px/u.test(styles) &&
|
||||
/--right-width:\s*clamp\(560px,\s*38vw,\s*740px\)/u.test(styles) &&
|
||||
/--right-width-expanded:\s*clamp\(560px,\s*45vw,\s*740px\)/u.test(styles) &&
|
||||
/id=["']hardware-sidebar["']/u.test(html) &&
|
||||
/id=["']right-sidebar-resize["']/u.test(html) &&
|
||||
/aria-label=["']拖拽调整右侧硬件状态栏宽度["']/u.test(html) &&
|
||||
/aria-valuemin=["']560["']/u.test(html) &&
|
||||
/aria-valuemax=["']760["']/u.test(html) &&
|
||||
/aria-valuenow=["']620["']/u.test(html) &&
|
||||
/RIGHT_SIDEBAR_DEFAULT_WIDTH\s*=\s*620/u.test(app) &&
|
||||
/RIGHT_SIDEBAR_MIN_WIDTH\s*=\s*560/u.test(app) &&
|
||||
/RIGHT_SIDEBAR_MAX_WIDTH\s*=\s*760/u.test(app) &&
|
||||
/function\s+initRightSidebarResize\s*\(/u.test(app) &&
|
||||
/function\s+clampRightSidebarWidth\s*\(/u.test(app) &&
|
||||
/function\s+rightSidebarResizeBounds\s*\(/u.test(app) &&
|
||||
/setRightSidebarWidth\(drag\.startWidth \+ drag\.startX - event\.clientX/u.test(app) &&
|
||||
/rightSidebarWidth:\s*state\.layout\.rightSidebarWidth/u.test(app) &&
|
||||
/--right-sidebar-width:\s*620px/u.test(styles) &&
|
||||
/--right-sidebar-min-width:\s*560px/u.test(styles) &&
|
||||
/--right-sidebar-max-width:\s*760px/u.test(styles) &&
|
||||
/--right-width:\s*clamp\(var\(--right-sidebar-min-width\),\s*var\(--right-sidebar-width\),\s*var\(--right-sidebar-max-width\)\)/u.test(styles) &&
|
||||
/--right-width-expanded:\s*clamp\(var\(--right-sidebar-min-width\),\s*var\(--right-sidebar-width\),\s*var\(--right-sidebar-max-width\)\)/u.test(styles) &&
|
||||
/\.explorer-resize\s*\{[^}]*cursor:\s*col-resize;/su.test(styles) &&
|
||||
/\.right-sidebar-resize\s*\{[^}]*cursor:\s*col-resize;/su.test(styles) &&
|
||||
/\.explorer-collapsed\s+\.explorer-resize\s*\{[^}]*display:\s*none;/su.test(styles) &&
|
||||
/@media\s*\(max-width:\s*860px\)[\s\S]*?\.explorer-resize\s*\{[\s\S]*?display:\s*none;/u.test(styles) &&
|
||||
/@media\s*\(max-width:\s*1240px\)[\s\S]*?\.right-sidebar-resize\s*\{[\s\S]*?display:\s*none;/u.test(styles) &&
|
||||
/\.explorer-collapsed\s*\{[^}]*--explorer-width:\s*0px;[^}]*grid-template-columns:\s*var\(--rail-width\)\s+0\s+minmax\(420px,\s*1fr\)\s+var\(--right-width\);/su.test(styles) &&
|
||||
/\.side-panel\s*\{[^}]*overflow:\s*auto;[^}]*overscroll-behavior:\s*contain;/su.test(styles)
|
||||
);
|
||||
@@ -4963,8 +5003,9 @@ async function inspectWorkbenchLayoutViewport(browser, url, viewport, options =
|
||||
};
|
||||
drawer.pass = drawer.pass && recollapsed.explorerCollapsed === true && recollapsed.keyTargetsReachable;
|
||||
const resize = await inspectExplorerResizeMobile(page, { viewport });
|
||||
const rightResize = await inspectRightSidebarResizeDisabled(page, { viewport });
|
||||
const gate = await inspectWorkbenchGateLayout(browser, url, viewport, options);
|
||||
return { collapsed, drawer, resize, gate, artifacts };
|
||||
return { collapsed, drawer, resize, rightResize, gate, artifacts };
|
||||
}
|
||||
|
||||
const expanded = await inspectLayoutState(page, {
|
||||
@@ -4989,8 +5030,11 @@ async function inspectWorkbenchLayoutViewport(browser, url, viewport, options =
|
||||
compareTo: expanded
|
||||
});
|
||||
const resize = await inspectExplorerResizeDesktop(page, { viewport });
|
||||
const rightResize = viewport.width > 1240
|
||||
? await inspectRightSidebarResizeDesktop(page, { viewport })
|
||||
: await inspectRightSidebarResizeDisabled(page, { viewport });
|
||||
const gate = await inspectWorkbenchGateLayout(browser, url, viewport, options);
|
||||
return { expanded, collapsed, restored, resize, gate, artifacts };
|
||||
return { expanded, collapsed, restored, resize, rightResize, gate, artifacts };
|
||||
} finally {
|
||||
await page.close();
|
||||
}
|
||||
@@ -5305,6 +5349,306 @@ async function inspectExplorerResizeMobile(page, { viewport }) {
|
||||
};
|
||||
}
|
||||
|
||||
async function inspectRightSidebarResizeDesktop(page, { viewport }) {
|
||||
const before = await page.evaluate(() => {
|
||||
const shell = document.querySelector("[data-app-shell]");
|
||||
const right = document.querySelector("#hardware-sidebar");
|
||||
const center = document.querySelector(".center-workspace");
|
||||
const handle = document.querySelector("#right-sidebar-resize");
|
||||
return {
|
||||
rightWidth: right?.getBoundingClientRect().width ?? 0,
|
||||
centerWidth: center?.getBoundingClientRect().width ?? 0,
|
||||
cssWidth: Number.parseFloat(getComputedStyle(shell).getPropertyValue("--right-sidebar-width")),
|
||||
storage: localStorage.getItem("hwlab.workbench.layout.v1"),
|
||||
handle: {
|
||||
ariaLabel: handle?.getAttribute("aria-label") ?? "",
|
||||
title: handle?.getAttribute("title") ?? "",
|
||||
role: handle?.getAttribute("role") ?? "",
|
||||
tabIndex: handle?.tabIndex ?? null,
|
||||
valueMin: handle?.getAttribute("aria-valuemin") ?? "",
|
||||
valueMax: handle?.getAttribute("aria-valuemax") ?? "",
|
||||
valueNow: handle?.getAttribute("aria-valuenow") ?? "",
|
||||
valueText: handle?.getAttribute("aria-valuetext") ?? ""
|
||||
}
|
||||
};
|
||||
});
|
||||
const min = Number(before.handle.valueMin);
|
||||
const max = Number(before.handle.valueMax);
|
||||
const growTarget = Math.min(max, before.rightWidth + 56);
|
||||
const shrinkTarget = Math.max(min, before.rightWidth - 48);
|
||||
const dragTarget = growTarget - before.rightWidth >= 24 ? growTarget : shrinkTarget;
|
||||
await dragRightSidebarResizeHandle(page, dragTarget);
|
||||
const afterDrag = await rightSidebarResizeMetrics(page);
|
||||
await page.locator("#right-sidebar-resize").press("ArrowRight");
|
||||
const afterArrowRight = await rightSidebarResizeMetrics(page);
|
||||
await page.locator("#right-sidebar-resize").press("End");
|
||||
const afterEnd = await rightSidebarResizeMetrics(page);
|
||||
await page.locator("#right-sidebar-resize").press("Home");
|
||||
const afterHome = await rightSidebarResizeMetrics(page);
|
||||
await page.locator("#right-sidebar-resize").press("ArrowLeft");
|
||||
const afterArrowLeft = await rightSidebarResizeMetrics(page);
|
||||
await page.locator("#explorer-toggle").click();
|
||||
await page.waitForFunction(() => document.querySelector("[data-app-shell]")?.classList.contains("explorer-collapsed"), null, { timeout: 8000 });
|
||||
const collapsedLeft = await rightSidebarResizeMetrics(page);
|
||||
await page.locator("#explorer-toggle").click();
|
||||
await page.waitForFunction(() => !document.querySelector("[data-app-shell]")?.classList.contains("explorer-collapsed"), null, { timeout: 8000 });
|
||||
const restoredLeft = await rightSidebarResizeMetrics(page);
|
||||
await page.reload({ waitUntil: "domcontentloaded", timeout: 15000 });
|
||||
await page.locator("#right-sidebar-resize").waitFor({ state: "visible", timeout: 12000 });
|
||||
await page.waitForTimeout(150);
|
||||
const restoredFromStorage = await rightSidebarResizeMetrics(page);
|
||||
const expectedArrowLeft = Math.min(afterHome.bounds.max, afterHome.bounds.min + 16);
|
||||
const pass =
|
||||
before.handle.role === "separator" &&
|
||||
before.handle.ariaLabel === "拖拽调整右侧硬件状态栏宽度" &&
|
||||
before.handle.title.includes("左右方向键") &&
|
||||
before.handle.tabIndex === 0 &&
|
||||
Number.isFinite(min) &&
|
||||
Number.isFinite(max) &&
|
||||
max >= min &&
|
||||
Math.abs(afterDrag.rightWidth - before.rightWidth) >= 20 &&
|
||||
afterDrag.rightWidth >= min &&
|
||||
afterDrag.rightWidth <= max &&
|
||||
afterArrowRight.rightWidth <= afterDrag.rightWidth - 12 &&
|
||||
Math.abs(afterEnd.rightWidth - afterEnd.bounds.max) <= 2 &&
|
||||
Math.abs(afterHome.rightWidth - afterHome.bounds.min) <= 2 &&
|
||||
Math.abs(afterArrowLeft.rightWidth - expectedArrowLeft) <= 2 &&
|
||||
collapsedLeft.leftExplorerCollapsed === true &&
|
||||
collapsedLeft.handleTabIndex === 0 &&
|
||||
collapsedLeft.keyTargetsReachable &&
|
||||
Math.abs(restoredLeft.rightWidth - afterArrowLeft.rightWidth) <= 2 &&
|
||||
restoredLeft.storage?.version === 1 &&
|
||||
restoredLeft.storage?.rightSidebarWidth === afterArrowLeft.rightWidth &&
|
||||
Math.abs(restoredFromStorage.rightWidth - afterArrowLeft.rightWidth) <= 2 &&
|
||||
restoredFromStorage.keyTargetsReachable &&
|
||||
restoredFromStorage.rootScrollLocked &&
|
||||
restoredFromStorage.noHorizontalOverflow;
|
||||
return {
|
||||
viewport,
|
||||
pass,
|
||||
targetWidth: dragTarget,
|
||||
before,
|
||||
afterDrag,
|
||||
afterArrowRight,
|
||||
afterEnd,
|
||||
afterHome,
|
||||
afterArrowLeft,
|
||||
collapsedLeft,
|
||||
restoredLeft,
|
||||
restoredFromStorage
|
||||
};
|
||||
}
|
||||
|
||||
async function dragRightSidebarResizeHandle(page, targetWidth) {
|
||||
const start = await page.evaluate(() => {
|
||||
const right = document.querySelector("#hardware-sidebar");
|
||||
const handle = document.querySelector("#right-sidebar-resize");
|
||||
const rightBox = right.getBoundingClientRect();
|
||||
const handleBox = handle.getBoundingClientRect();
|
||||
return {
|
||||
startX: handleBox.left + handleBox.width / 2,
|
||||
startY: handleBox.top + Math.min(80, handleBox.height / 2),
|
||||
currentWidth: rightBox.width
|
||||
};
|
||||
});
|
||||
const targetX = start.startX - (targetWidth - start.currentWidth);
|
||||
await page.mouse.move(start.startX, start.startY);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(targetX, start.startY, { steps: 8 });
|
||||
await page.mouse.up();
|
||||
}
|
||||
|
||||
async function rightSidebarResizeMetrics(page) {
|
||||
return page.evaluate(async () => {
|
||||
const shell = document.querySelector("[data-app-shell]");
|
||||
const explorer = document.querySelector("#resource-explorer");
|
||||
const center = document.querySelector(".center-workspace");
|
||||
const right = document.querySelector("#hardware-sidebar");
|
||||
const handle = document.querySelector("#right-sidebar-resize");
|
||||
const ownsHit = (element, hit) => hit === element || element.contains(hit);
|
||||
const hitLabel = (hit) => hit ? `${hit.tagName.toLowerCase()}${hit.id ? `#${hit.id}` : ""}${hit.className ? `.${String(hit.className).trim().replace(/\s+/gu, ".")}` : ""}` : "none";
|
||||
const nearestScrollableAncestor = (element) => {
|
||||
let current = element.parentElement;
|
||||
while (current && current !== document.documentElement) {
|
||||
const style = getComputedStyle(current);
|
||||
const scrollable = current.scrollHeight > current.clientHeight + 2 && !["visible", "clip"].includes(style.overflowY);
|
||||
if (scrollable) return current;
|
||||
current = current.parentElement;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const scrollIntoNearestContainer = async (element) => {
|
||||
const container = nearestScrollableAncestor(element);
|
||||
if (!container) {
|
||||
element.scrollIntoView({ block: "center", inline: "nearest" });
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
return null;
|
||||
}
|
||||
const elementBox = element.getBoundingClientRect();
|
||||
const containerBox = container.getBoundingClientRect();
|
||||
const inset = Math.max(6, Math.min(24, (container.clientHeight - Math.min(elementBox.height, container.clientHeight)) / 2));
|
||||
container.scrollTop += elementBox.top - containerBox.top - inset;
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
return container;
|
||||
};
|
||||
const clipBoxForElement = (element) => {
|
||||
let visible = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: window.innerWidth,
|
||||
bottom: window.innerHeight
|
||||
};
|
||||
let current = element.parentElement;
|
||||
while (current && current !== document.documentElement) {
|
||||
const style = getComputedStyle(current);
|
||||
if (!["visible", "clip"].includes(style.overflow) || !["visible", "clip"].includes(style.overflowY) || !["visible", "clip"].includes(style.overflowX)) {
|
||||
const box = current.getBoundingClientRect();
|
||||
visible = {
|
||||
left: Math.max(visible.left, box.left),
|
||||
top: Math.max(visible.top, box.top),
|
||||
right: Math.min(visible.right, box.right),
|
||||
bottom: Math.min(visible.bottom, box.bottom)
|
||||
};
|
||||
}
|
||||
current = current.parentElement;
|
||||
}
|
||||
return visible;
|
||||
};
|
||||
const targetSelectors = [
|
||||
"#command-input",
|
||||
"#command-send",
|
||||
"#m3-write-do",
|
||||
"#m3-read-di",
|
||||
"#tab-control",
|
||||
"#tab-wiring",
|
||||
"[data-hardware-tab='overview']",
|
||||
"[data-hardware-tab='gateways']",
|
||||
"[data-hardware-tab='box1']",
|
||||
"[data-hardware-tab='box2']",
|
||||
"[data-hardware-tab='patch']"
|
||||
];
|
||||
const keyTargets = [];
|
||||
for (const selector of targetSelectors) {
|
||||
const element = document.querySelector(selector);
|
||||
if (!element) {
|
||||
keyTargets.push({ selector, ok: false, missing: true });
|
||||
continue;
|
||||
}
|
||||
const scrollContainer = await scrollIntoNearestContainer(element);
|
||||
const box = element.getBoundingClientRect();
|
||||
const clipBox = clipBoxForElement(element);
|
||||
const visibleBox = {
|
||||
left: Math.max(box.left, clipBox.left),
|
||||
top: Math.max(box.top, clipBox.top),
|
||||
right: Math.min(box.right, clipBox.right),
|
||||
bottom: Math.min(box.bottom, clipBox.bottom)
|
||||
};
|
||||
const visibleWidth = Math.max(0, visibleBox.right - visibleBox.left);
|
||||
const visibleHeight = Math.max(0, visibleBox.bottom - visibleBox.top);
|
||||
const x = visibleBox.left + visibleWidth / 2;
|
||||
const y = visibleBox.top + visibleHeight / 2;
|
||||
const stack = document.elementsFromPoint(x, y);
|
||||
keyTargets.push({
|
||||
selector,
|
||||
ok:
|
||||
box.width > 0 &&
|
||||
box.height > 0 &&
|
||||
visibleWidth > 0 &&
|
||||
visibleHeight > 0 &&
|
||||
x >= 0 &&
|
||||
x <= window.innerWidth &&
|
||||
y >= 0 &&
|
||||
y <= window.innerHeight &&
|
||||
stack.some((candidate) => ownsHit(element, candidate)),
|
||||
hit: hitLabel(stack[0] ?? null),
|
||||
center: { x, y },
|
||||
visibleBox,
|
||||
scrollContainer: scrollContainer ? scrollContainer.id ? `#${scrollContainer.id}` : scrollContainer.className ? `.${String(scrollContainer.className).trim().replace(/\s+/gu, ".")}` : scrollContainer.tagName.toLowerCase() : null
|
||||
});
|
||||
}
|
||||
let storage = null;
|
||||
try {
|
||||
storage = JSON.parse(localStorage.getItem("hwlab.workbench.layout.v1") ?? "null");
|
||||
} catch {
|
||||
storage = "parse_failed";
|
||||
}
|
||||
return {
|
||||
leftExplorerCollapsed: shell?.classList.contains("explorer-collapsed") === true,
|
||||
explorerWidth: explorer?.getBoundingClientRect().width ?? 0,
|
||||
centerWidth: center?.getBoundingClientRect().width ?? 0,
|
||||
rightWidth: right?.getBoundingClientRect().width ?? 0,
|
||||
cssWidth: Number.parseFloat(getComputedStyle(shell).getPropertyValue("--right-sidebar-width")),
|
||||
bounds: {
|
||||
min: Number(handle?.getAttribute("aria-valuemin")),
|
||||
max: Number(handle?.getAttribute("aria-valuemax"))
|
||||
},
|
||||
handleTabIndex: handle?.tabIndex ?? null,
|
||||
handleAriaDisabled: handle?.getAttribute("aria-disabled") ?? "",
|
||||
handleAriaHidden: handle?.getAttribute("aria-hidden") ?? "",
|
||||
handleAriaValueNow: Number(handle?.getAttribute("aria-valuenow")),
|
||||
handleAriaValueText: handle?.getAttribute("aria-valuetext") ?? "",
|
||||
storage,
|
||||
keyTargets,
|
||||
keyTargetsReachable: keyTargets.every((target) => target.ok),
|
||||
noHorizontalOverflow:
|
||||
document.documentElement.scrollWidth <= document.documentElement.clientWidth + 2 &&
|
||||
document.body.scrollWidth <= document.body.clientWidth + 2 &&
|
||||
(!right || right.scrollWidth <= right.clientWidth + 2),
|
||||
rootScrollLocked:
|
||||
getComputedStyle(document.documentElement).overflow === "hidden" &&
|
||||
getComputedStyle(document.body).overflow === "hidden" &&
|
||||
document.documentElement.scrollHeight <= document.documentElement.clientHeight + 2 &&
|
||||
document.body.scrollHeight <= document.body.clientHeight + 2
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async function inspectRightSidebarResizeDisabled(page, { viewport }) {
|
||||
const observation = await page.evaluate(() => {
|
||||
const handle = document.querySelector("#right-sidebar-resize");
|
||||
const box = handle?.getBoundingClientRect();
|
||||
const style = handle ? getComputedStyle(handle) : null;
|
||||
const right = document.querySelector("#hardware-sidebar");
|
||||
const command = document.querySelector("#command-form");
|
||||
const hardwareStatus = document.querySelector(".hardware-status");
|
||||
return {
|
||||
viewport: { width: window.innerWidth, height: window.innerHeight },
|
||||
handlePresent: Boolean(handle),
|
||||
handleDisplay: style?.display ?? "missing",
|
||||
handleWidth: box?.width ?? 0,
|
||||
handleTabIndex: handle?.tabIndex ?? null,
|
||||
handleAriaDisabled: handle?.getAttribute("aria-disabled") ?? "",
|
||||
handleAriaHidden: handle?.getAttribute("aria-hidden") ?? "",
|
||||
rightWidth: right?.getBoundingClientRect().width ?? 0,
|
||||
commandVisible: Boolean(command && command.getBoundingClientRect().width > 0 && command.getBoundingClientRect().height > 0),
|
||||
hardwareVisible: Boolean(hardwareStatus && hardwareStatus.getBoundingClientRect().width > 0 && hardwareStatus.getBoundingClientRect().height > 0),
|
||||
noHorizontalOverflow:
|
||||
document.documentElement.scrollWidth <= document.documentElement.clientWidth + 2 &&
|
||||
document.body.scrollWidth <= document.body.clientWidth + 2 &&
|
||||
(!right || right.scrollWidth <= right.clientWidth + 2),
|
||||
rootScrollLocked:
|
||||
getComputedStyle(document.documentElement).overflow === "hidden" &&
|
||||
getComputedStyle(document.body).overflow === "hidden" &&
|
||||
document.documentElement.scrollHeight <= document.documentElement.clientHeight + 2 &&
|
||||
document.body.scrollHeight <= document.body.clientHeight + 2
|
||||
};
|
||||
});
|
||||
return {
|
||||
viewport,
|
||||
pass:
|
||||
observation.handlePresent &&
|
||||
observation.handleDisplay === "none" &&
|
||||
observation.handleTabIndex === -1 &&
|
||||
observation.handleAriaDisabled === "true" &&
|
||||
observation.handleAriaHidden === "true" &&
|
||||
observation.commandVisible &&
|
||||
observation.hardwareVisible &&
|
||||
observation.noHorizontalOverflow &&
|
||||
observation.rootScrollLocked,
|
||||
...observation
|
||||
};
|
||||
}
|
||||
|
||||
async function inspectLayoutState(page, { mode, viewport, compareTo }) {
|
||||
return page.evaluate(async ({ mode, viewport, compareTo }) => {
|
||||
const failures = [];
|
||||
@@ -5566,6 +5910,7 @@ async function inspectLayoutState(page, { mode, viewport, compareTo }) {
|
||||
keyTargets.push(await inspectHitTarget(selector, label));
|
||||
}
|
||||
const resizeHandle = await inspectHitTarget("#explorer-resize", "左侧资源树宽度调整手柄");
|
||||
const rightResizeHandle = await inspectHitTarget("#right-sidebar-resize", "右侧硬件状态栏宽度调整手柄");
|
||||
const drawerTargets = [];
|
||||
for (const [selector, label] of drawerSelectorLabels) {
|
||||
drawerTargets.push(await inspectFirstHit(selector, label));
|
||||
@@ -5984,6 +6329,7 @@ async function inspectLayoutState(page, { mode, viewport, compareTo }) {
|
||||
keyTargetsRequirement,
|
||||
blockedKeyTargets,
|
||||
resizeHandle,
|
||||
rightResizeHandle,
|
||||
drawerReachable,
|
||||
blockedDrawerTargets,
|
||||
sidePanelScroll,
|
||||
|
||||
Reference in New Issue
Block a user