Spaces:
Running
Running
Fix help tooltips: floating body tooltip with fallback title for question-mark hints
Browse files
app.py
CHANGED
|
@@ -288,12 +288,11 @@ APP_CSS = """
|
|
| 288 |
vertical-align: middle;
|
| 289 |
}
|
| 290 |
|
| 291 |
-
.setting-help-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
transform: translateX(-50%);
|
| 297 |
min-width: 180px;
|
| 298 |
max-width: 320px;
|
| 299 |
padding: 0.42rem 0.55rem;
|
|
@@ -306,15 +305,14 @@ APP_CSS = """
|
|
| 306 |
line-height: 1.25;
|
| 307 |
box-shadow: var(--shadow);
|
| 308 |
opacity: 0;
|
| 309 |
-
pointer-events: none;
|
| 310 |
visibility: hidden;
|
| 311 |
transition: opacity 120ms ease;
|
| 312 |
-
z-index:
|
|
|
|
| 313 |
white-space: normal;
|
| 314 |
}
|
| 315 |
|
| 316 |
-
.setting-help-
|
| 317 |
-
.setting-help-q:focus-visible::after {
|
| 318 |
opacity: 1;
|
| 319 |
visibility: visible;
|
| 320 |
}
|
|
@@ -397,22 +395,69 @@ SETTING_HELP_JS = """
|
|
| 397 |
["Upload incomplete shard buffers", "On crawl finish/stop, flush the current partial shard buffer and upload it too."],
|
| 398 |
];
|
| 399 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 400 |
const clean = (value) => String(value || "").replace(/\\s+/g, " ").trim();
|
| 401 |
const labels = document.querySelectorAll(".gradio-container label");
|
| 402 |
|
| 403 |
for (const label of labels) {
|
| 404 |
-
if (label.querySelector(".setting-help-q")) continue;
|
| 405 |
const text = clean(label.textContent);
|
| 406 |
const match = helpByPrefix.find(([prefix]) => text.startsWith(prefix));
|
| 407 |
if (!match) continue;
|
| 408 |
|
| 409 |
-
|
| 410 |
-
q
|
| 411 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 412 |
q.setAttribute("data-help", match[1]);
|
| 413 |
q.setAttribute("aria-label", match[1]);
|
|
|
|
| 414 |
q.tabIndex = 0;
|
| 415 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 416 |
}
|
| 417 |
return [];
|
| 418 |
}
|
|
|
|
| 288 |
vertical-align: middle;
|
| 289 |
}
|
| 290 |
|
| 291 |
+
.setting-help-tooltip {
|
| 292 |
+
position: fixed;
|
| 293 |
+
left: 0;
|
| 294 |
+
top: 0;
|
| 295 |
+
transform: translate(-50%, -100%);
|
|
|
|
| 296 |
min-width: 180px;
|
| 297 |
max-width: 320px;
|
| 298 |
padding: 0.42rem 0.55rem;
|
|
|
|
| 305 |
line-height: 1.25;
|
| 306 |
box-shadow: var(--shadow);
|
| 307 |
opacity: 0;
|
|
|
|
| 308 |
visibility: hidden;
|
| 309 |
transition: opacity 120ms ease;
|
| 310 |
+
z-index: 10000;
|
| 311 |
+
pointer-events: none;
|
| 312 |
white-space: normal;
|
| 313 |
}
|
| 314 |
|
| 315 |
+
.setting-help-tooltip.is-visible {
|
|
|
|
| 316 |
opacity: 1;
|
| 317 |
visibility: visible;
|
| 318 |
}
|
|
|
|
| 395 |
["Upload incomplete shard buffers", "On crawl finish/stop, flush the current partial shard buffer and upload it too."],
|
| 396 |
];
|
| 397 |
|
| 398 |
+
const tooltipId = "setting-help-tooltip";
|
| 399 |
+
let tooltip = document.getElementById(tooltipId);
|
| 400 |
+
if (!tooltip) {
|
| 401 |
+
tooltip = document.createElement("div");
|
| 402 |
+
tooltip.id = tooltipId;
|
| 403 |
+
tooltip.className = "setting-help-tooltip";
|
| 404 |
+
document.body.appendChild(tooltip);
|
| 405 |
+
}
|
| 406 |
+
|
| 407 |
+
const placeTooltip = (target) => {
|
| 408 |
+
const rect = target.getBoundingClientRect();
|
| 409 |
+
const aboveTop = rect.top - 10;
|
| 410 |
+
|
| 411 |
+
tooltip.style.left = `${rect.left + (rect.width / 2)}px`;
|
| 412 |
+
if (aboveTop < 44) {
|
| 413 |
+
tooltip.style.top = `${rect.bottom + 10}px`;
|
| 414 |
+
tooltip.style.transform = "translate(-50%, 0)";
|
| 415 |
+
} else {
|
| 416 |
+
tooltip.style.top = `${rect.top - 10}px`;
|
| 417 |
+
tooltip.style.transform = "translate(-50%, -100%)";
|
| 418 |
+
}
|
| 419 |
+
};
|
| 420 |
+
|
| 421 |
+
const showTooltip = (target) => {
|
| 422 |
+
const message = target.getAttribute("data-help") || "";
|
| 423 |
+
if (!message) return;
|
| 424 |
+
tooltip.textContent = message;
|
| 425 |
+
placeTooltip(target);
|
| 426 |
+
tooltip.classList.add("is-visible");
|
| 427 |
+
};
|
| 428 |
+
|
| 429 |
+
const hideTooltip = () => {
|
| 430 |
+
tooltip.classList.remove("is-visible");
|
| 431 |
+
};
|
| 432 |
+
|
| 433 |
const clean = (value) => String(value || "").replace(/\\s+/g, " ").trim();
|
| 434 |
const labels = document.querySelectorAll(".gradio-container label");
|
| 435 |
|
| 436 |
for (const label of labels) {
|
|
|
|
| 437 |
const text = clean(label.textContent);
|
| 438 |
const match = helpByPrefix.find(([prefix]) => text.startsWith(prefix));
|
| 439 |
if (!match) continue;
|
| 440 |
|
| 441 |
+
let q = label.querySelector(".setting-help-q");
|
| 442 |
+
if (!q) {
|
| 443 |
+
q = document.createElement("span");
|
| 444 |
+
q.className = "setting-help-q";
|
| 445 |
+
q.textContent = "?";
|
| 446 |
+
label.appendChild(q);
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
q.setAttribute("data-help", match[1]);
|
| 450 |
q.setAttribute("aria-label", match[1]);
|
| 451 |
+
q.setAttribute("title", match[1]);
|
| 452 |
q.tabIndex = 0;
|
| 453 |
+
|
| 454 |
+
if (!q.hasAttribute("data-help-bound")) {
|
| 455 |
+
q.addEventListener("mouseenter", () => showTooltip(q));
|
| 456 |
+
q.addEventListener("mouseleave", hideTooltip);
|
| 457 |
+
q.addEventListener("focus", () => showTooltip(q));
|
| 458 |
+
q.addEventListener("blur", hideTooltip);
|
| 459 |
+
q.setAttribute("data-help-bound", "1");
|
| 460 |
+
}
|
| 461 |
}
|
| 462 |
return [];
|
| 463 |
}
|