mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-05-25 19:20:16 +00:00
feat: make clarify prompt collapsible
This commit is contained in:
committed by
nesquena-hermes
parent
e08eecefb1
commit
581da3da2b
@@ -3,6 +3,10 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- **PR #2731** by @Michaelyklam — Clarification prompts now include a compact Collapse/Expand control so users can temporarily shrink a blocking decision card and reread the chat context behind it before responding.
|
||||
|
||||
## [v0.51.114] — 2026-05-22 — Release CL (stage-407 — 1-PR — update-check recovery from remote re-tags)
|
||||
|
||||
### Fixed
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
@@ -488,6 +488,7 @@
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 17h.01"/><path d="M9.09 9a3 3 0 1 1 5.82 1c0 2-3 2-3 4"/><circle cx="12" cy="12" r="10"/></svg>
|
||||
<span id="clarifyHeading" data-i18n="clarify_heading">Clarification needed</span>
|
||||
<span class="clarify-countdown" id="clarifyCountdown"></span>
|
||||
<button type="button" class="clarify-collapse" id="clarifyCollapse" aria-expanded="true" aria-controls="clarifyQuestion clarifyChoices clarifyInput clarifyHint" onclick="toggleClarifyCardCollapsed()" title="Collapse clarification">Collapse</button>
|
||||
</div>
|
||||
<div class="clarify-question" id="clarifyQuestion"></div>
|
||||
<div class="clarify-choices" id="clarifyChoices"></div>
|
||||
|
||||
@@ -2502,6 +2502,7 @@ function _ensureClarifyCardDom() {
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 17h.01"/><path d="M9.09 9a3 3 0 1 1 5.82 1c0 2-3 2-3 4"/><circle cx="12" cy="12" r="10"/></svg>
|
||||
<span id="clarifyHeading" data-i18n="clarify_heading">Clarification needed</span>
|
||||
<span class="clarify-countdown" id="clarifyCountdown"></span>
|
||||
<button type="button" class="clarify-collapse" id="clarifyCollapse" aria-expanded="true" aria-controls="clarifyQuestion clarifyChoices clarifyInput clarifyHint" onclick="toggleClarifyCardCollapsed()" title="Collapse clarification">Collapse</button>
|
||||
</div>
|
||||
<div class="clarify-question" id="clarifyQuestion"></div>
|
||||
<div class="clarify-choices" id="clarifyChoices"></div>
|
||||
@@ -2515,10 +2516,29 @@ function _ensureClarifyCardDom() {
|
||||
host.appendChild(card);
|
||||
const submit = $("clarifySubmit");
|
||||
if (submit) submit.onclick = () => respondClarify();
|
||||
const collapse = $("clarifyCollapse");
|
||||
if (collapse) collapse.onclick = () => toggleClarifyCardCollapsed();
|
||||
if (typeof applyLocaleToDOM === "function") applyLocaleToDOM();
|
||||
return card;
|
||||
}
|
||||
|
||||
function _syncClarifyCollapseButton(card) {
|
||||
const collapse = $("clarifyCollapse");
|
||||
if (!collapse || !card) return;
|
||||
const collapsed = card.classList.contains("collapsed");
|
||||
collapse.setAttribute("aria-expanded", collapsed ? "false" : "true");
|
||||
collapse.textContent = collapsed ? "Expand" : "Collapse";
|
||||
collapse.title = collapsed ? "Expand clarification" : "Collapse clarification";
|
||||
}
|
||||
|
||||
function toggleClarifyCardCollapsed(forceCollapsed) {
|
||||
const card = $("clarifyCard");
|
||||
if (!card) return;
|
||||
const collapsed = typeof forceCollapsed === "boolean" ? forceCollapsed : !card.classList.contains("collapsed");
|
||||
card.classList.toggle("collapsed", collapsed);
|
||||
_syncClarifyCollapseButton(card);
|
||||
}
|
||||
|
||||
function _clearClarifyHideTimer() {
|
||||
if (_clarifyHideTimer) {
|
||||
clearTimeout(_clarifyHideTimer);
|
||||
@@ -2685,6 +2705,7 @@ function showClarifyCard(pending) {
|
||||
if (!sameClarify) {
|
||||
_clarifyVisibleSince = Date.now();
|
||||
_clearClarifyHideTimer();
|
||||
card.classList.remove("collapsed");
|
||||
}
|
||||
if (questionEl) questionEl.textContent = question;
|
||||
if (choicesEl) {
|
||||
@@ -2745,6 +2766,7 @@ function showClarifyCard(pending) {
|
||||
}
|
||||
_clarifySetControlsDisabled(false, false);
|
||||
card.classList.add("visible");
|
||||
_syncClarifyCollapseButton(card);
|
||||
if (typeof applyLocaleToDOM === "function") applyLocaleToDOM();
|
||||
if (input && !sameClarify) setTimeout(() => input.focus({preventScroll: true}), 50);
|
||||
}
|
||||
|
||||
+7
-1
@@ -963,11 +963,13 @@
|
||||
/* ── Clarify card ── */
|
||||
.clarify-card{position:absolute;left:0;right:0;bottom:-24px;max-width:var(--msg-max);margin:0 auto;padding:0 20px;box-sizing:border-box;width:100%;overflow:hidden;pointer-events:none;max-height:min(calc(100vh - 280px),420px);}
|
||||
.clarify-card.visible{pointer-events:auto;}
|
||||
.clarify-card .clarify-inner{max-height:min(calc(100vh - 280px),420px);overflow-y:auto;transform:translateY(100%);opacity:0;transition:transform .4s cubic-bezier(.32,.72,.16,1),opacity .25s ease;}
|
||||
.clarify-card .clarify-inner{max-height:min(calc(100vh - 280px),420px);overflow-y:auto;transform:translateY(100%);opacity:0;transition:transform .4s cubic-bezier(.32,.72,.16,1),opacity .25s ease,max-height .2s ease;}
|
||||
.clarify-card.visible .clarify-inner{transform:translateY(0);opacity:1;}
|
||||
.clarify-inner{background:var(--surface);backdrop-filter:blur(8px);border:1px solid var(--accent-bg-strong);border-radius:12px;padding:12px 14px 36px;box-shadow:0 1px 0 rgba(255,255,255,.02) inset;}
|
||||
.clarify-header{display:flex;align-items:center;gap:8px;margin-bottom:10px;font-size:12px;font-weight:700;color:var(--blue);letter-spacing:.01em;}
|
||||
.clarify-countdown{margin-left:auto;min-width:42px;text-align:right;color:var(--muted);font-variant-numeric:tabular-nums;font-weight:700;}
|
||||
.clarify-collapse{margin-left:4px;border:1px solid var(--border2);border-radius:999px;background:var(--surface);color:var(--muted);font:inherit;font-size:11px;font-weight:700;line-height:1;padding:5px 8px;cursor:pointer;}
|
||||
.clarify-collapse:hover,.clarify-collapse:focus-visible{color:var(--text);border-color:var(--accent-bg-strong);outline:none;}
|
||||
.clarify-countdown.urgent{color:var(--error);box-shadow:inset 0 -2px 0 var(--error);border-radius:2px;}
|
||||
.clarify-question{font-size:14px;color:var(--text);line-height:1.7;white-space:pre-wrap;margin-bottom:12px;}
|
||||
.clarify-choices{display:flex;flex-direction:column;gap:8px;margin-bottom:12px;}
|
||||
@@ -988,6 +990,10 @@
|
||||
.clarify-submit.loading{opacity:.75;cursor:wait;}
|
||||
.clarify-hint{margin-top:8px;font-size:11px;line-height:1.45;color:var(--muted);}
|
||||
.clarify-card.visible .clarify-question{padding-left:1px;}
|
||||
.clarify-card.collapsed{max-height:72px;}
|
||||
.clarify-card.collapsed .clarify-inner{max-height:56px;overflow:hidden;padding-bottom:12px;}
|
||||
.clarify-card.collapsed .clarify-header{margin-bottom:0;}
|
||||
.clarify-card.collapsed .clarify-question,.clarify-card.collapsed .clarify-choices,.clarify-card.collapsed .clarify-response,.clarify-card.collapsed .clarify-hint{display:none;}
|
||||
/* Left rail (desktop primary navigation) */
|
||||
.rail{display:none;width:48px;flex-shrink:0;flex-direction:column;align-items:center;gap:4px;padding:8px 0;background:var(--sidebar);border-right:1px solid var(--border);}
|
||||
.rail-btn{width:36px;height:36px;border-radius:8px;border:none;background:none;color:var(--muted);cursor:pointer;display:flex;align-items:center;justify-content:center;position:relative;transition:color .15s,background .15s;flex-shrink:0;padding:0;}
|
||||
|
||||
@@ -98,6 +98,7 @@ class TestClarifyCardHTML:
|
||||
assert 'id="clarifyChoices"' in html, "clarify choices container missing"
|
||||
assert 'id="clarifyInput"' in html, "clarify input missing"
|
||||
assert 'id="clarifySubmit"' in html, "clarify submit button missing"
|
||||
assert 'id="clarifyCollapse"' in html, "clarify collapse button missing"
|
||||
|
||||
def test_clarify_card_has_data_i18n(self):
|
||||
html = read(REPO / "static/index.html")
|
||||
@@ -167,7 +168,9 @@ class TestClarifyCardCSS:
|
||||
".clarify-response",
|
||||
".clarify-input",
|
||||
".clarify-submit",
|
||||
".clarify-collapse",
|
||||
".clarify-hint",
|
||||
".clarify-card.collapsed",
|
||||
):
|
||||
assert cls in css, f"CSS class '{cls}' missing"
|
||||
|
||||
@@ -317,6 +320,13 @@ class TestClarifyMessagesJS:
|
||||
for token in ("startClarifyPolling", "stopClarifyPolling", "hideClarifyCard", "_clarifySessionId"):
|
||||
assert token in src, f"{token} missing from messages.js"
|
||||
|
||||
def test_clarify_card_can_collapse_without_hiding_prompt(self):
|
||||
src = read(REPO / "static/messages.js")
|
||||
assert "function toggleClarifyCardCollapsed" in src, "clarify collapse toggle missing"
|
||||
assert "aria-expanded" in src, "clarify collapse button should expose expanded state"
|
||||
assert "card.classList.remove(\"collapsed\")" in src, \
|
||||
"new clarification prompts should reopen rather than stay collapsed"
|
||||
|
||||
|
||||
# ── boot.js keyboard shortcut ────────────────────────────────────────────────
|
||||
|
||||
|
||||
Reference in New Issue
Block a user