ui: editor-like QoL — selection highlight, drag feedback, keyboard nav
Selection / highlight: - .vv-row-selected: blue tint + left accent bar (was barely-visible gray) - .vv-sb-selected: same treatment, consistent across both panels - .vv-df-active (containers): match new selection style - .vv-job-row + .vv-sb-row: smooth transition on state changes - .vv-orch-row: hover feedback + pointer cursor (was no visual response) Drag and drop: - .vv-drag-ghost: adds dashed ring so source item stays visible while dragging - .vv-drop-line: blue glow to match selection accent (was flat green) - All drop targets: unified blue theme (.vv-children, .vv-folder-children) - .vv-library-zone drop target: improved red with inset glow - .vv-drag-handle:active: grabbing cursor state - document.body.vv-is-dragging: cursor:grabbing on entire page during drag (added to all three drag start handlers + failsafe document dragend) Keyboard navigation (scheduler): - ↑/↓: navigate between top-level orchestrator cards - Home/End: jump to first/last card - Escape: close right panel, return to suggestions - /: focus log search when log panel is open - All shortcuts suppressed when focus is in any input/textarea/select Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
a943a5c294
commit
753f99ac0c
@@ -3051,6 +3051,7 @@ function _vvOrchScriptDragStart(e) {
|
||||
vvDragFromArray = this.dataset.confArray || null;
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
e.dataTransfer.setData('text/plain', vvDragScript);
|
||||
document.body.classList.add('vv-is-dragging');
|
||||
setTimeout(() => this.classList.add('vv-drag-ghost'), 0);
|
||||
}
|
||||
|
||||
@@ -3060,6 +3061,7 @@ function _vvCustomDragStart(e) {
|
||||
vvDragFromArray = null;
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
e.dataTransfer.setData('text/plain', vvDragScript);
|
||||
document.body.classList.add('vv-is-dragging');
|
||||
setTimeout(() => this.classList.add('vv-drag-ghost'), 0);
|
||||
}
|
||||
|
||||
@@ -3069,13 +3071,17 @@ function vvLibDragStart(e, el) {
|
||||
vvDragFromArray = null;
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
e.dataTransfer.setData('text/plain', vvDragScript);
|
||||
document.body.classList.add('vv-is-dragging');
|
||||
setTimeout(() => el.classList.add('vv-drag-ghost'), 0);
|
||||
}
|
||||
|
||||
function vvDragEnd(e) {
|
||||
if (vvDragEl) vvDragEl.classList.remove('vv-drag-ghost');
|
||||
document.body.classList.remove('vv-is-dragging');
|
||||
vvDragEl = null;
|
||||
}
|
||||
// Failsafe: clear dragging class if drop lands outside the window
|
||||
document.addEventListener('dragend', () => document.body.classList.remove('vv-is-dragging'));
|
||||
|
||||
// Return the .vv-script element that the cursor is above the midpoint of,
|
||||
// or null if cursor is below all items (meaning: append).
|
||||
@@ -3470,4 +3476,46 @@ requestAnimationFrame(function() {
|
||||
vvStartStatusPoll();
|
||||
vvStartSnapPoll();
|
||||
});
|
||||
|
||||
// ── Keyboard navigation ───────────────────────────────────────────────────────
|
||||
// ↑/↓ — navigate top-level orchestrator cards
|
||||
// Home/End — jump to first/last card
|
||||
// Escape — close right panel
|
||||
// / — focus log search when visible
|
||||
document.addEventListener('keydown', function(e) {
|
||||
// Don't intercept when typing in any input/textarea/select
|
||||
const t = document.activeElement;
|
||||
if (t && (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' ||
|
||||
t.tagName === 'SELECT' || t.isContentEditable)) return;
|
||||
|
||||
// Escape — back to suggestions
|
||||
if (e.key === 'Escape' && vvActiveId) {
|
||||
e.preventDefault();
|
||||
vvBackToSuggestions();
|
||||
return;
|
||||
}
|
||||
|
||||
// / — focus log search when the log panel is open
|
||||
if (e.key === '/' && document.getElementById('vv-log-search').style.display !== 'none') {
|
||||
e.preventDefault();
|
||||
document.getElementById('vv-log-search').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// ↑/↓/Home/End — navigate top-level orchestrator cards
|
||||
if (!['ArrowUp','ArrowDown','Home','End'].includes(e.key)) return;
|
||||
const cards = [...document.querySelectorAll('#vv-sched-cards > .vv-sched-card')];
|
||||
if (!cards.length) return;
|
||||
const cur = vvActiveId ? cards.findIndex(c => c.dataset.id === vvActiveId) : -1;
|
||||
let next;
|
||||
if (e.key === 'ArrowDown') next = cur < cards.length - 1 ? cur + 1 : cur;
|
||||
else if (e.key === 'ArrowUp') next = cur > 0 ? cur - 1 : 0;
|
||||
else if (e.key === 'Home') next = 0;
|
||||
else next = cards.length - 1;
|
||||
if (next === cur && cur !== -1) return;
|
||||
if (next < 0) next = 0;
|
||||
e.preventDefault();
|
||||
cards[next].scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||
vvOpenRight(cards[next].dataset.id);
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user