mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
fix(split-pane): style and dismiss the split-picker menu
.split-picker-menu/-item/-empty (created in openSplitPicker()) had zero CSS and could not be dismissed except by picking an item — a default-path defect since the Split button ships enabled to anyone who flips showSplitButton on. Add CSS matching the sibling .run-mode-menu popover's look (floating-bg backdrop blur, border, shadow, z-index 1000 above the header's 100), and dismiss on outside click or Escape via the same one-shot listener pattern session-ui.js already uses for its other transient popovers (toggleCaseSettings(), toggleRunModeMenu()). Picking an item now routes through the same _dismissSplitPicker() method as the outside-click/Escape handlers, so the listeners never outlive the menu. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
57406f6c14
commit
2724c922ce
@@ -18635,3 +18635,43 @@ html[data-session-list="sidebar"][data-sidebar="collapsed"] .btn-sidebar-toggle
|
|||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Split-picker menu: a small popover listing sessions to split with, appended
|
||||||
|
to document.body and positioned `fixed` by openSplitPicker() (JS sets
|
||||||
|
top/right against the Split header button's own rect). z-index above the
|
||||||
|
header (100) with headroom to spare, matching the sibling .run-mode-menu
|
||||||
|
dropdown's 1000. Dismissed by openSplitPane()'s own inline onclick, or by
|
||||||
|
the click-outside/Escape listeners installed alongside it. */
|
||||||
|
.split-picker-menu {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1000;
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 320px;
|
||||||
|
padding: 4px;
|
||||||
|
background: var(--floating-bg);
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
border: 1px solid var(--control-border);
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-picker-item {
|
||||||
|
padding: 8px 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-picker-item:hover {
|
||||||
|
background: var(--control-bg-hover, rgba(255, 255, 255, 0.08));
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-picker-empty {
|
||||||
|
padding: 8px 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ Object.assign(CodemanApp.prototype, {
|
|||||||
menu.innerHTML = candidates
|
menu.innerHTML = candidates
|
||||||
.map(
|
.map(
|
||||||
(c) =>
|
(c) =>
|
||||||
`<div class="split-picker-item" data-session-id="${escapeHtml(c.id)}" onclick="app.openSplitPane(${escapeHtml(JSON.stringify(c.id))}); document.getElementById('splitPickerMenu')?.remove();">${escapeHtml(c.label)}</div>`
|
`<div class="split-picker-item" data-session-id="${escapeHtml(c.id)}" onclick="app.openSplitPane(${escapeHtml(JSON.stringify(c.id))}); app._dismissSplitPicker();">${escapeHtml(c.label)}</div>`
|
||||||
)
|
)
|
||||||
.join('');
|
.join('');
|
||||||
}
|
}
|
||||||
@@ -158,6 +158,31 @@ Object.assign(CodemanApp.prototype, {
|
|||||||
menu.style.top = `${rect.bottom + 4}px`;
|
menu.style.top = `${rect.bottom + 4}px`;
|
||||||
menu.style.right = `${window.innerWidth - rect.right}px`;
|
menu.style.right = `${window.innerWidth - rect.right}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dismiss on outside click or Escape — same one-shot listener pattern as
|
||||||
|
// session-ui.js's other transient popovers (toggleCaseSettings(),
|
||||||
|
// toggleRunModeMenu()). Deferred by a tick so the click that OPENED the
|
||||||
|
// menu (still bubbling) doesn't immediately close it. Picking an item
|
||||||
|
// (above) calls the SAME dismiss method, so these listeners never
|
||||||
|
// outlive the menu either way.
|
||||||
|
const closeOnOutsideClick = (e) => {
|
||||||
|
if (!menu.contains(e.target) && e.target !== splitBtn) this._dismissSplitPicker();
|
||||||
|
};
|
||||||
|
const closeOnEscape = (e) => {
|
||||||
|
if (e.key === 'Escape') this._dismissSplitPicker();
|
||||||
|
};
|
||||||
|
this._splitPickerDismissHandlers = { closeOnOutsideClick, closeOnEscape };
|
||||||
|
setTimeout(() => document.addEventListener('click', closeOnOutsideClick), 0);
|
||||||
|
document.addEventListener('keydown', closeOnEscape);
|
||||||
|
},
|
||||||
|
|
||||||
|
_dismissSplitPicker() {
|
||||||
|
document.getElementById('splitPickerMenu')?.remove();
|
||||||
|
if (this._splitPickerDismissHandlers) {
|
||||||
|
document.removeEventListener('click', this._splitPickerDismissHandlers.closeOnOutsideClick);
|
||||||
|
document.removeEventListener('keydown', this._splitPickerDismissHandlers.closeOnEscape);
|
||||||
|
this._splitPickerDismissHandlers = null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
openSplitPane(sessionId) {
|
openSplitPane(sessionId) {
|
||||||
|
|||||||
Reference in New Issue
Block a user