ui: premium editor overhaul — selection, word highlight, find, status bar

Selection:
- ::selection fix: text selection now visible (bright blue) even when
  textarea color is transparent — the #1 complaint
- Overlay background changed transparent → #vv-editor-inner provides bg,
  allowing #vv-cur-line to show through

Current line highlight:
- #vv-cur-line div positioned absolutely behind overlay, tracks cursor
  line on every keyup/mouseup/click/scroll
- Gutter: current line number highlighted in bright white + bold

Word/variable occurrence highlight:
- Click or position cursor on any identifier → all occurrences highlighted
  in yellow throughout the overlay (whole-word, case-sensitive)
- Select a word → same treatment for the selection text
- Clears when cursor moves off the word or find bar opens

Find in file (Ctrl+F):
- Find bar slides in above editor, pre-filled with selected word
- Highlights all matches orange, current match in bright amber
- ↑/↓ buttons + Enter/Shift+Enter to navigate between matches
- Live match count "N / M"
- Red border + "no matches" feedback when term not found
- Escape or × closes, returns focus to editor

Status bar:
- Persistent bar below editor: Ln N, Col N | selection info | language
- Shows "Bash" or "Bash / Config" depending on file type
- Hides when editor is not open

Visual polish:
- Editor wrap: unified border + border-radius 4px 4px 0 0, overflow:hidden
  clips gutter and inner to rounded corners as one block
- Status bar border-radius 0 0 4px 4px — completes the block
- Gutter: 46px (was 42) — room for 3-digit line numbers
- Slim 8px scrollbar with styled track and hover state
- vvEditorReset() clears all editor state on open/close

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gmer4Lfe
2026-05-31 20:16:26 -04:00
co-authored by Claude Sonnet 4.6
parent 753f99ac0c
commit a250d590ca
2 changed files with 299 additions and 15 deletions
+59 -8
View File
@@ -324,24 +324,75 @@
border: 1px solid #333; border-radius: 4px; padding: 10px 12px; resize: none;
line-height: 1.5; scroll-behavior: auto; tab-size: 2; width: 100%; box-sizing: border-box; }
/* Editor layout: gutter + inner area */
#vv-editor-wrap { display: flex; }
#vv-ln-gutter { width: 42px; min-width: 42px; flex-shrink: 0;
/* Editor layout: gutter + inner area — unified bordered block */
#vv-editor-wrap { display: flex; border: 1px solid #2e2e2e; border-radius: 4px 4px 0 0;
overflow: hidden; background: #0d0d0d; }
#vv-ln-gutter { width: 46px; min-width: 46px; flex-shrink: 0;
background: #0a0a0a; border-right: 1px solid #1c1c1c;
font-family: monospace; font-size: 12px; line-height: 1.5; tab-size: 2;
color: #3a3a3a; text-align: right; padding: 10px 8px 10px 0;
overflow: hidden; user-select: none; white-space: pre; }
#vv-editor-inner { position: relative; flex: 1; overflow: hidden; }
.vv-gln-cur { color: #ccc; font-weight: bold; }
#vv-editor-inner { position: relative; flex: 1; overflow: hidden; background: #0d0d0d; }
/* Syntax-highlight overlay sits over the transparent textarea */
#vv-hl-overlay { display: none; position: absolute; top: 1px; left: 1px; right: 1px; bottom: 1px;
/* Current line highlight — sits behind overlay */
#vv-cur-line { position: absolute; left: 0; right: 0; height: 18px;
background: rgba(255,255,255,0.04);
border-top: 1px solid rgba(255,255,255,0.03);
border-bottom: 1px solid rgba(255,255,255,0.03);
pointer-events: none; display: none; }
/* Syntax-highlight overlay — transparent bg so cur-line shows through */
#vv-hl-overlay { display: none; position: absolute; top: 0; left: 0; right: 0; bottom: 0;
margin: 0; padding: 10px 12px; box-sizing: border-box;
font-family: monospace; font-size: 12px; line-height: 1.5; tab-size: 2;
white-space: pre-wrap; word-break: break-all; overflow: hidden;
pointer-events: none; user-select: none;
background: #0d0d0d; border: none; border-radius: 3px; }
background: transparent; border: none; border-radius: 0; }
.vv-editor-hl #vv-hl-overlay { display: block; }
.vv-editor-hl #vv-editor-body { color: transparent; caret-color: #ddd; background: transparent; }
.vv-editor-hl #vv-editor-body { color: transparent; caret-color: #ddd; background: transparent;
border: none !important; border-radius: 0 !important; }
/* Visible selection — works even when text is transparent */
.vv-editor-hl #vv-editor-body::selection { background: rgba(100,149,237,0.35); color: transparent; }
.vv-editor-hl #vv-editor-body::-moz-selection{ background: rgba(100,149,237,0.35); color: transparent; }
/* Word match and search marks in the overlay */
.vv-word-mark { background: rgba(255,220,60,0.14); outline: 1px solid rgba(255,220,60,0.35); border-radius: 2px; }
.vv-search-mark { background: rgba(255,140,20,0.22); outline: 1px solid rgba(255,140,20,0.45); border-radius: 2px; }
.vv-search-mark-current{ background: rgba(255,90,0,0.40); outline: 2px solid rgba(255,100,0,0.7); border-radius: 2px; }
/* Slim scrollbar for editor */
#vv-editor-body::-webkit-scrollbar { width: 8px; height: 8px; }
#vv-editor-body::-webkit-scrollbar-track { background: #0a0a0a; }
#vv-editor-body::-webkit-scrollbar-thumb { background: #2a2a2a; border-radius: 4px; }
#vv-editor-body::-webkit-scrollbar-thumb:hover { background: #444; }
/* Editor find bar */
#vv-editor-find { display: none; align-items: center; gap: 6px; padding: 5px 8px;
margin-bottom: 5px; background: #161616; border: 1px solid #333;
border-radius: 4px; font-size: 12px; }
#vv-editor-find.vv-find-open { display: flex; }
#vv-find-input { flex: 1; min-width: 0; background: #0d0d0d; border: 1px solid #333;
color: #ddd; padding: 4px 8px; border-radius: 3px;
font-family: monospace; font-size: 12px; }
#vv-find-input:focus { border-color: #6495ed; outline: none; box-shadow: 0 0 0 1px rgba(100,149,237,0.25); }
#vv-find-input.vv-find-no-match { border-color: #c62828; box-shadow: 0 0 0 1px rgba(198,40,40,0.3); }
.vv-find-count { font-size: 11px; color: #555; white-space: nowrap; flex-shrink: 0; min-width: 64px; text-align: right; }
.vv-find-nav-btn{ padding: 2px 8px !important; }
#vv-find-close { color: #555; cursor: pointer; font-size: 16px; line-height: 1;
padding: 0 2px; flex-shrink: 0; }
#vv-find-close:hover { color: #aaa; }
/* Editor status bar */
#vv-editor-status { display: none; align-items: center; gap: 14px; padding: 3px 10px;
background: #0e0e0e; border: 1px solid #2e2e2e; border-top: none;
border-radius: 0 0 4px 4px; font-family: monospace;
font-size: 10px; color: #444; user-select: none; flex-shrink: 0; }
#vv-editor-status.vv-ed-active { display: flex; }
.vv-es-pos { color: #666; }
.vv-es-sel { color: #555; }
.vv-es-lang { margin-left: auto; color: #4a6a7a; }
/* Suggestions panel — accordion */
#vv-suggestions { overflow-y: auto; }