fix: 修复工作区状态构建明细浮层
This commit is contained in:
@@ -799,6 +799,7 @@ test("layout smoke verifies desktop and mobile default workbench geometry withou
|
||||
"layout-narrow-desktop-default",
|
||||
"layout-mobile-default",
|
||||
"layout-feedback-352-resource-explorer-removed",
|
||||
"layout-feedback-437-live-build-overlay",
|
||||
"layout-left-sidebar-collapse",
|
||||
"layout-gate-desktop",
|
||||
"layout-gate-narrow-desktop",
|
||||
@@ -820,6 +821,7 @@ test("layout smoke verifies desktop and mobile default workbench geometry withou
|
||||
assert.match(report.safety.statement, /does not send Code Agent chat, call M3 IO/u);
|
||||
assert.equal(report.checks.find((check) => check.id === "layout-issue-287-future-hardware-status-tabs")?.status, "pass");
|
||||
assert.equal(report.checks.find((check) => check.id === "layout-feedback-352-resource-explorer-removed")?.status, "pass");
|
||||
assert.equal(report.checks.find((check) => check.id === "layout-feedback-437-live-build-overlay")?.status, "pass");
|
||||
assert.equal(report.checks.find((check) => check.id === "layout-issue-288-future-single-table-gate")?.status, "skip");
|
||||
|
||||
const desktopDefault = report.checks.find((check) => check.id === "layout-desktop-default")?.observations;
|
||||
@@ -843,6 +845,11 @@ test("layout smoke verifies desktop and mobile default workbench geometry withou
|
||||
assert.equal(desktopDefault.wiring.metadataInDetails, true);
|
||||
assert.equal(desktopDefault.wiring.horizontalScroll.panelScrollWidth <= desktopDefault.wiring.horizontalScroll.panelClientWidth + 2, true);
|
||||
assert.equal(desktopDefault.noHorizontalOverflow.right, true);
|
||||
assert.equal(desktopDefault.liveBuildLayout.overlayPositioned, true);
|
||||
assert.equal(desktopDefault.liveBuildLayout.popoverVisible, true);
|
||||
assert.equal(desktopDefault.liveBuildLayout.popoverViewportContained, true);
|
||||
assert.equal(desktopDefault.liveBuildLayout.stableGeometry, true);
|
||||
assert.equal(desktopDefault.liveBuildLayout.closedByButton, true);
|
||||
assert.equal(Object.hasOwn(desktopDefault.boxes.shell, "text"), false);
|
||||
assert.equal(Object.hasOwn(desktopDefault.semanticOverlapChecks[0].boxes["#m3-control-form"], "text"), false);
|
||||
assert.equal(desktopDefault.failures.length, 0);
|
||||
@@ -863,6 +870,10 @@ test("layout smoke verifies desktop and mobile default workbench geometry withou
|
||||
assert.equal(mobileDefault.wiring.metadataInSummary, true);
|
||||
assert.equal(mobileDefault.wiring.metadataInDetails, true);
|
||||
assert.equal(mobileDefault.noHorizontalOverflow.right, true);
|
||||
assert.equal(mobileDefault.liveBuildLayout.overlayPositioned, true);
|
||||
assert.equal(mobileDefault.liveBuildLayout.popoverVisible, true);
|
||||
assert.equal(mobileDefault.liveBuildLayout.popoverViewportContained, true);
|
||||
assert.equal(mobileDefault.liveBuildLayout.stableGeometry, true);
|
||||
|
||||
const leftCollapse = report.checks.find((check) => check.id === "layout-left-sidebar-collapse")?.observations;
|
||||
assert.equal(leftCollapse.status, "pass");
|
||||
@@ -906,5 +917,6 @@ test("repo-owned web checks expose source build and DEV live layout smoke gates"
|
||||
assert.match(cloudWebCheckSource, /runDevCloudWorkbenchLayoutSmoke/u);
|
||||
assert.match(cloudWebCheckSource, /tmp\/dev-cloud-workbench-layout-web-check\.json/u);
|
||||
assert.match(cloudWebCheckSource, /layout-feedback-352-resource-explorer-removed/u);
|
||||
assert.match(cloudWebCheckSource, /layout-feedback-437-live-build-overlay/u);
|
||||
assert.match(cloudWebCheckSource, /compactLayoutSmokeFailures/u);
|
||||
});
|
||||
|
||||
@@ -1140,6 +1140,12 @@ export async function runDevCloudWorkbenchLayoutSmoke(args = {}) {
|
||||
summary: "#352 default workbench has no aside#resource-explorer, #explorer-resize, resource tree/capability copy, or reclaimed left panel across desktop and mobile.",
|
||||
observations: summarizeResourceExplorerRemovalCoverage(viewportResults)
|
||||
},
|
||||
{
|
||||
id: "layout-feedback-437-live-build-overlay",
|
||||
status: allViewportCoverage(viewportResults, "liveBuildOverlayStable") ? "pass" : "blocked",
|
||||
summary: "#437 workbench status build details open as an overlay without changing the topbar, workspace, or conversation geometry across desktop and mobile.",
|
||||
observations: summarizeCoverageGap(viewportResults, "liveBuildOverlay")
|
||||
},
|
||||
{
|
||||
id: "layout-left-sidebar-collapse",
|
||||
status: Object.values(viewportResults).every((result) => result.leftCollapse?.pass) ? "pass" : "blocked",
|
||||
@@ -1271,7 +1277,7 @@ export async function runDevCloudWorkbenchLayoutSmoke(args = {}) {
|
||||
summary: useLiveUrl
|
||||
? "Live browser layout smoke verifies workbench layout, hit targets, overflow, /gate usability, and the two-column wiring panel only; it is not M3 hardware acceptance."
|
||||
: "Static local browser layout smoke verifies workbench layout, hit targets, overflow, /gate usability, and the two-column wiring panel only; deployment still requires DEV live verification.",
|
||||
refs: ["pikasTech/HWLAB#273", "pikasTech/HWLAB#276", "pikasTech/HWLAB#278", "pikasTech/HWLAB#287", "pikasTech/HWLAB#288", "pikasTech/HWLAB#352", "pikasTech/HWLAB#99", "pikasTech/HWLAB#227"],
|
||||
refs: ["pikasTech/HWLAB#273", "pikasTech/HWLAB#276", "pikasTech/HWLAB#278", "pikasTech/HWLAB#287", "pikasTech/HWLAB#288", "pikasTech/HWLAB#352", "pikasTech/HWLAB#437", "pikasTech/HWLAB#239", "pikasTech/HWLAB#99", "pikasTech/HWLAB#227"],
|
||||
viewports: layoutViewports.map(({ id, width, height }) => ({ id, width, height })),
|
||||
checks,
|
||||
blockers,
|
||||
@@ -3171,22 +3177,26 @@ async function inspectLiveDom(url, options = {}) {
|
||||
liveBuildListVisibleWhenClosed: visible("#live-build-list"),
|
||||
liveBuildDetailWhenOpen: (() => {
|
||||
const details = document.querySelector("#live-build-summary");
|
||||
const popover = document.querySelector("#live-build-popover");
|
||||
const list = document.querySelector("#live-build-list");
|
||||
if (!details || !list) {
|
||||
if (!details || !popover || !list) {
|
||||
return {
|
||||
visible: false,
|
||||
rows: 0,
|
||||
scrollContained: false,
|
||||
overlay: false,
|
||||
text: "",
|
||||
overflowX: 0
|
||||
};
|
||||
}
|
||||
details.open = true;
|
||||
const popoverStyle = getComputedStyle(popover);
|
||||
const rows = [...list.querySelectorAll(".live-build-row")];
|
||||
return {
|
||||
visible: visible("#live-build-list"),
|
||||
rows: rows.length,
|
||||
scrollContained: list.clientHeight <= Math.ceil(window.innerHeight * 0.42) + 4,
|
||||
scrollContained: list.clientHeight <= Math.ceil(window.innerHeight * 0.58) + 4,
|
||||
overlay: popoverStyle.position === "absolute",
|
||||
text: list.textContent?.replace(/\s+/gu, " ").trim() ?? "",
|
||||
overflowX: Math.max(0, ...rows.map((row) => row.scrollWidth - row.clientWidth), list.scrollWidth - list.clientWidth)
|
||||
};
|
||||
@@ -7830,36 +7840,103 @@ async function inspectLayoutState(page, { mode, viewport, compareTo }) {
|
||||
const inspectLiveBuildLayout = async () => {
|
||||
const details = document.querySelector("#live-build-summary");
|
||||
const label = document.querySelector("#live-build-latest");
|
||||
const toggle = document.querySelector("#live-build-toggle");
|
||||
const popover = document.querySelector("#live-build-popover");
|
||||
const list = document.querySelector("#live-build-list");
|
||||
if (!details || !label || !list) {
|
||||
const topbar = document.querySelector(".topbar");
|
||||
const workspace = document.querySelector('[data-view="workspace"]');
|
||||
const conversation = document.querySelector(".conversation-column");
|
||||
const boxSnapshot = () => ({
|
||||
topbar: boxForElement(topbar),
|
||||
workspace: boxForElement(workspace),
|
||||
conversation: boxForElement(conversation)
|
||||
});
|
||||
if (!details || !label || !toggle || !popover || !list || !topbar || !workspace || !conversation) {
|
||||
return { ok: false, exists: false, summaryOverflowX: null, listOverflowX: null, maxRowOverflowX: null, rows: 0 };
|
||||
}
|
||||
const wasOpen = details.open;
|
||||
const labelBox = boxForElement(label);
|
||||
const detailsBox = boxForElement(details);
|
||||
const labelStyle = getComputedStyle(label);
|
||||
const summaryOverflowX = Math.max(0, label.scrollWidth - label.clientWidth);
|
||||
const summaryContained =
|
||||
Boolean(labelBox && detailsBox) &&
|
||||
labelBox.left >= detailsBox.left - 1 &&
|
||||
labelBox.right <= detailsBox.right + 1 &&
|
||||
labelStyle.overflow === "hidden" &&
|
||||
labelStyle.textOverflow === "ellipsis" &&
|
||||
labelStyle.whiteSpace === "nowrap";
|
||||
details.open = false;
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
const before = boxSnapshot();
|
||||
details.open = true;
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
const rows = [...list.querySelectorAll(".live-build-row")];
|
||||
const rowOverflows = rows.map((row) => Math.max(0, row.scrollWidth - row.clientWidth));
|
||||
const maxRowOverflowX = Math.max(0, ...rowOverflows);
|
||||
const listOverflowX = Math.max(0, list.scrollWidth - list.clientWidth);
|
||||
const scrollContained = list.clientHeight <= Math.ceil(window.innerHeight * 0.42) + 4;
|
||||
const popoverBox = boxForElement(popover);
|
||||
const popoverStyle = getComputedStyle(popover);
|
||||
const toggleExpanded = toggle.getAttribute("aria-expanded") === "true";
|
||||
const popoverVisible = popoverBox && popoverBox.width > 0 && popoverBox.height > 0 && popoverStyle.display !== "none";
|
||||
const popoverViewportContained =
|
||||
Boolean(popoverBox) &&
|
||||
popoverBox.left >= -1 &&
|
||||
popoverBox.right <= window.innerWidth + 1 &&
|
||||
popoverBox.top >= -1 &&
|
||||
popoverBox.bottom <= window.innerHeight + 1;
|
||||
const overlayPositioned = popoverStyle.position === "absolute";
|
||||
const scrollContained = list.clientHeight <= Math.ceil(window.innerHeight * 0.58) + 4;
|
||||
const text = list.textContent?.replace(/\s+/gu, " ").trim() ?? "";
|
||||
const expectedRows = rows.length >= 4;
|
||||
const expectedText = /构建时间不可用/u.test(text) && /外部镜像或非 HWLAB 构建产物/u.test(text);
|
||||
const afterOpen = boxSnapshot();
|
||||
const stableGeometry = ["topbar", "workspace", "conversation"].every((key) => {
|
||||
const a = before[key];
|
||||
const b = afterOpen[key];
|
||||
return a && b && Math.abs(a.top - b.top) <= 1 && Math.abs(a.height - b.height) <= 1;
|
||||
});
|
||||
document.querySelector("#live-build-close")?.click();
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
const closedByButton = details.open === false && toggle.getAttribute("aria-expanded") === "false";
|
||||
details.open = wasOpen;
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
return {
|
||||
ok: summaryOverflowX <= 1 && listOverflowX <= 1 && maxRowOverflowX <= 1 && scrollContained && expectedRows && expectedText,
|
||||
ok:
|
||||
summaryContained &&
|
||||
listOverflowX <= 1 &&
|
||||
maxRowOverflowX <= 1 &&
|
||||
scrollContained &&
|
||||
expectedRows &&
|
||||
expectedText &&
|
||||
overlayPositioned &&
|
||||
popoverVisible &&
|
||||
popoverViewportContained &&
|
||||
toggleExpanded &&
|
||||
stableGeometry &&
|
||||
closedByButton,
|
||||
exists: true,
|
||||
openStateRestored: details.open === wasOpen,
|
||||
summaryContained,
|
||||
summaryOverflowX,
|
||||
labelBox,
|
||||
detailsBox,
|
||||
listOverflowX,
|
||||
maxRowOverflowX,
|
||||
rowOverflows,
|
||||
rows: rows.length,
|
||||
expectedRows,
|
||||
expectedText,
|
||||
overlayPositioned,
|
||||
popoverVisible,
|
||||
popoverViewportContained,
|
||||
toggleExpanded,
|
||||
scrollContained,
|
||||
stableGeometry,
|
||||
closedByButton,
|
||||
before,
|
||||
afterOpen,
|
||||
popoverBox,
|
||||
textSample: text.slice(0, 240)
|
||||
};
|
||||
};
|
||||
@@ -8231,6 +8308,7 @@ async function inspectLayoutState(page, { mode, viewport, compareTo }) {
|
||||
rightResizeHandle,
|
||||
sidePanelScroll,
|
||||
sidePanelOverflowUsable,
|
||||
liveBuildOverlayStable: liveBuildLayout.ok,
|
||||
hardwareTabsCenterHit,
|
||||
wiring: {
|
||||
longTableOk: wiringLongTableOk,
|
||||
@@ -8640,7 +8718,8 @@ function summarizeCoverageGap(viewportResults, issueKey) {
|
||||
issue288: "issue288SingleTableReady",
|
||||
issue287: "issue287HardwareTabsReady",
|
||||
hardwareTabs: "hardwareTabsCenterHit",
|
||||
wiring: "wiringReadableTwoColumn"
|
||||
wiring: "wiringReadableTwoColumn",
|
||||
liveBuildOverlay: "liveBuildOverlayStable"
|
||||
}[issueKey] ?? "issue287HardwareTabsReady";
|
||||
return {
|
||||
status: allViewportCoverage(viewportResults, fieldName) ? "pass" : "skip",
|
||||
|
||||
@@ -104,6 +104,9 @@ const el = {
|
||||
liveStatus: byId("live-status"),
|
||||
liveDetail: byId("live-detail"),
|
||||
liveBuildSummary: byId("live-build-summary"),
|
||||
liveBuildToggle: byId("live-build-toggle"),
|
||||
liveBuildPopover: byId("live-build-popover"),
|
||||
liveBuildClose: byId("live-build-close"),
|
||||
liveBuildLatest: byId("live-build-latest"),
|
||||
liveBuildList: byId("live-build-list"),
|
||||
agentChatStatus: byId("agent-chat-status"),
|
||||
@@ -196,6 +199,7 @@ initSideTabs();
|
||||
initHardwareTabs();
|
||||
initQuickActions();
|
||||
initCommandBar();
|
||||
initLiveBuildOverlay();
|
||||
initWorkbenchLogout(el.logoutButton);
|
||||
initM3Control();
|
||||
initGateControls();
|
||||
@@ -228,6 +232,35 @@ function resolveTimeoutMs(name, fallback, { min, max }) {
|
||||
return Math.min(Math.max(Math.trunc(configured), min), max);
|
||||
}
|
||||
|
||||
function initLiveBuildOverlay() {
|
||||
syncLiveBuildOverlayState();
|
||||
el.liveBuildSummary.addEventListener("toggle", syncLiveBuildOverlayState);
|
||||
el.liveBuildClose.addEventListener("click", () => closeLiveBuildOverlay({ restoreFocus: true }));
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Escape" && el.liveBuildSummary.open) {
|
||||
event.preventDefault();
|
||||
closeLiveBuildOverlay({ restoreFocus: true });
|
||||
}
|
||||
});
|
||||
document.addEventListener("click", (event) => {
|
||||
if (!el.liveBuildSummary.open || el.liveBuildSummary.contains(event.target)) return;
|
||||
closeLiveBuildOverlay();
|
||||
});
|
||||
}
|
||||
|
||||
function syncLiveBuildOverlayState() {
|
||||
const expanded = el.liveBuildSummary.open === true;
|
||||
el.liveBuildToggle.setAttribute("aria-expanded", expanded ? "true" : "false");
|
||||
el.liveBuildPopover.setAttribute("aria-hidden", expanded ? "false" : "true");
|
||||
}
|
||||
|
||||
function closeLiveBuildOverlay(options = {}) {
|
||||
if (!el.liveBuildSummary.open) return;
|
||||
el.liveBuildSummary.open = false;
|
||||
syncLiveBuildOverlayState();
|
||||
if (options.restoreFocus === true) el.liveBuildToggle.focus();
|
||||
}
|
||||
|
||||
function initRoutes() {
|
||||
window.addEventListener("hashchange", () => showView(routeFromLocation()));
|
||||
for (const button of document.querySelectorAll("[data-route]")) {
|
||||
|
||||
@@ -72,10 +72,16 @@
|
||||
<strong id="live-status" class="tone-pending">等待验证</strong>
|
||||
<small id="live-detail">正在验证 hwlab-cloud-api /health/live、/v1、/v1/agent/chat 与 /v1/m3/io;未完成前不标为通过。</small>
|
||||
<details class="live-build-summary" id="live-build-summary">
|
||||
<summary>
|
||||
<summary id="live-build-toggle" aria-controls="live-build-popover" aria-expanded="false">
|
||||
<span class="live-build-summary-label" id="live-build-latest">最新镜像构建时间:等待实时元数据</span>
|
||||
</summary>
|
||||
<div class="live-build-list" id="live-build-list" aria-label="live HWLAB 微服务构建时间明细"></div>
|
||||
<div class="live-build-popover" id="live-build-popover" role="dialog" aria-modal="false" aria-label="live HWLAB 微服务构建时间明细">
|
||||
<div class="live-build-popover-head">
|
||||
<strong>构建版本明细</strong>
|
||||
<button class="live-build-close" id="live-build-close" type="button" aria-label="关闭构建版本明细">关闭</button>
|
||||
</div>
|
||||
<div class="live-build-list" id="live-build-list" tabindex="0" aria-label="live HWLAB 微服务构建时间明细"></div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<button class="logout-button" id="logout-button" type="button">退出</button>
|
||||
|
||||
@@ -278,6 +278,11 @@ assert.equal(
|
||||
"pass",
|
||||
"#352 resource explorer removal must remain covered by desktop and 390x844 layout smoke"
|
||||
);
|
||||
assert.equal(
|
||||
layoutSmoke.checks.find((check) => check.id === "layout-feedback-437-live-build-overlay")?.status,
|
||||
"pass",
|
||||
"#437 live build details overlay must not move the topbar, workspace, or conversation geometry"
|
||||
);
|
||||
assert.equal(
|
||||
layoutSmoke.checks.find((check) => check.id === "layout-left-sidebar-collapse")?.status,
|
||||
"pass",
|
||||
@@ -293,6 +298,7 @@ for (const layoutCheckId of [
|
||||
"layout-narrow-desktop-default",
|
||||
"layout-mobile-default",
|
||||
"layout-feedback-352-resource-explorer-removed",
|
||||
"layout-feedback-437-live-build-overlay",
|
||||
"layout-left-sidebar-collapse",
|
||||
"layout-right-sidebar-resize-desktop",
|
||||
"layout-right-sidebar-resize-narrow-desktop",
|
||||
@@ -934,7 +940,13 @@ assert.match(app, /fetchJson\("\/v1\/diagnostics\/gate"/);
|
||||
assert.match(app, /fetchJson\("\/v1\/live-builds"\)/);
|
||||
assert.match(html, /id="live-build-latest"/);
|
||||
assert.match(html, /id="live-build-list"/);
|
||||
assert.match(html, /id="live-build-toggle"[^>]*aria-controls="live-build-popover"[^>]*aria-expanded="false"/);
|
||||
assert.match(html, /id="live-build-popover"[^>]*role="dialog"[^>]*aria-modal="false"/);
|
||||
assert.match(html, /id="live-build-close"/);
|
||||
assert.match(styles, /\.live-build-summary\s*{/);
|
||||
assert.match(app, /initLiveBuildOverlay/);
|
||||
assert.match(app, /closeLiveBuildOverlay/);
|
||||
assert.match(app, /aria-expanded/);
|
||||
assert.match(app, /formatBeijingTime/);
|
||||
assert.match(app, /Asia\/Shanghai/);
|
||||
assert.match(app, /最新镜像构建时间/);
|
||||
@@ -946,9 +958,12 @@ assert.match(app, /liveBuildDesiredStateText/);
|
||||
assert.match(app, /外部镜像或非 HWLAB 构建产物/);
|
||||
assert.doesNotMatch(app, /artifact report|artifact-report/);
|
||||
assert.match(app, /live health/);
|
||||
assert.match(styles, /\.live-build-summary-label\s*{[^}]*min-width:\s*0;[^}]*max-width:\s*100%;[^}]*overflow-wrap:\s*anywhere;/s);
|
||||
assert.match(styles, /\.live-build-list\s*{[^}]*max-height:\s*min\(280px,\s*42dvh\);[^}]*min-width:\s*0;[^}]*overflow:\s*auto;/s);
|
||||
assert.match(styles, /\.live-build-summary-label\s*{[^}]*min-width:\s*0;[^}]*max-width:\s*100%;[^}]*overflow:\s*hidden;[^}]*text-overflow:\s*ellipsis;[^}]*white-space:\s*nowrap;/s);
|
||||
assert.match(styles, /\.live-build-popover\s*{[^}]*position:\s*absolute;[^}]*max-height:\s*min\(420px,\s*58dvh\);[^}]*overflow:\s*hidden;/s);
|
||||
assert.match(styles, /\.live-build-summary\[open\]\s+\.live-build-popover\s*{[^}]*display:\s*grid;/s);
|
||||
assert.match(styles, /\.live-build-list\s*{[^}]*min-width:\s*0;[^}]*max-height:\s*min\(352px,\s*calc\(58dvh - 54px\)\);[^}]*overflow:\s*auto;/s);
|
||||
assert.match(styles, /\.live-build-row-head\s*{[^}]*grid-template-columns:\s*minmax\(0,\s*0\.8fr\)\s*minmax\(0,\s*1\.2fr\);/s);
|
||||
assert.match(styles, /@media \(max-width: 860px\)[\s\S]*?\.live-build-popover\s*{[\s\S]*?width:\s*100%;/);
|
||||
assert.match(styles, /@media \(max-width: 860px\)[\s\S]*?\.live-build-row-head\s*{[\s\S]*?grid-template-columns:\s*1fr;/);
|
||||
assert.match(styles, /\.live-build-meta span\s*{[^}]*overflow-wrap:\s*anywhere;/s);
|
||||
assert.match(app, /fetchJson\("\/health\/live"\)/);
|
||||
|
||||
@@ -504,6 +504,7 @@ h3 {
|
||||
}
|
||||
|
||||
.probe-card {
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
align-content: center;
|
||||
@@ -526,6 +527,7 @@ h3 {
|
||||
}
|
||||
|
||||
.live-build-summary {
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
margin-top: 4px;
|
||||
@@ -543,19 +545,88 @@ h3 {
|
||||
font-size: 10px;
|
||||
line-height: 1.35;
|
||||
cursor: pointer;
|
||||
overflow-wrap: anywhere;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
.live-build-summary summary::marker {
|
||||
color: var(--accent-2);
|
||||
}
|
||||
|
||||
.live-build-summary-label {
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.live-build-list {
|
||||
max-height: min(280px, 42dvh);
|
||||
.live-build-popover {
|
||||
position: absolute;
|
||||
z-index: 30;
|
||||
top: calc(100% + 8px);
|
||||
right: 0;
|
||||
width: min(100%, 560px);
|
||||
max-width: 100%;
|
||||
max-height: min(420px, 58dvh);
|
||||
display: none;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
gap: 8px;
|
||||
padding: 10px;
|
||||
background: rgba(20, 22, 20, 0.99);
|
||||
border: 1px solid var(--line-strong);
|
||||
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.42);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.live-build-summary[open] .live-build-popover {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.live-build-popover-head {
|
||||
min-width: 0;
|
||||
margin-top: 7px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.live-build-popover-head strong {
|
||||
min-width: 0;
|
||||
color: var(--text);
|
||||
font-family: var(--mono);
|
||||
font-size: 11px;
|
||||
line-height: 1.2;
|
||||
text-transform: none;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.live-build-close {
|
||||
flex: 0 0 auto;
|
||||
min-height: 26px;
|
||||
padding: 3px 8px;
|
||||
border: 1px solid var(--line);
|
||||
background: var(--surface-2);
|
||||
color: var(--muted);
|
||||
font-family: var(--mono);
|
||||
font-size: 10px;
|
||||
font-weight: 760;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.live-build-close:hover,
|
||||
.live-build-close:focus-visible {
|
||||
border-color: var(--line-strong);
|
||||
color: var(--text);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.live-build-list {
|
||||
min-width: 0;
|
||||
max-height: min(352px, calc(58dvh - 54px));
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
overflow: auto;
|
||||
@@ -2261,6 +2332,18 @@ tbody tr:last-child td {
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.live-build-popover {
|
||||
right: 0;
|
||||
left: auto;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
max-height: min(420px, 56dvh);
|
||||
}
|
||||
|
||||
.live-build-list {
|
||||
max-height: min(352px, calc(56dvh - 54px));
|
||||
}
|
||||
|
||||
.live-build-time {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user