Three xterm.js features, implemented together because they share the XtermPane mount + the single attachCustomKeyEventHandler: - Unicode 11: load @xterm/addon-unicode11, set activeVersion='11' after the canvas renderer so emoji/CJK/box-drawing widths stop drifting. - Find in scrollback: @xterm/addon-search + a new per-pane SearchBar overlay (Ctrl+Shift+F to open, Enter/Shift+Enter next/prev, regex + case toggles, Esc to close & refocus). Overlay is an absolutely- positioned sibling in a position:relative wrapper so fit() is unaffected. - Pane navigation: Ctrl+Alt+Arrow / Ctrl+Alt+HJKL (spatial neighbour via findNeighborInDirection) and Alt+1..9 (Nth leaf in walkLeaves order). XtermPane emits a NavigateIntent; App resolves the target leaf and sets it active, reusing the existing isActive->focusTrigger refocus chain. All chords live in one attachCustomKeyEventHandler (xterm replaces the handler on each call). Shortcuts added to shortcuts.ts (SoT for README + Help), including the Alt+digit shell-conflict caveat. tsc clean apart from the three not-yet-installed addon modules. Needs pnpm install on the Windows host + runtime verification. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
105 lines
2.2 KiB
CSS
105 lines
2.2 KiB
CSS
/* ---------------------------------------------------------------------------
|
|
SearchBar — find-in-scrollback overlay.
|
|
|
|
Positioned absolutely inside XtermPane's container div (which must be
|
|
position: relative). Sits at the top-right of the pane, z-index 10 so it
|
|
floats above the xterm canvas but below any app-level modals (z-index 100).
|
|
Colour palette matches Palette.css / Help.css: #181818 surface, #2a2a2a
|
|
borders, #e6e6e6 text, #1a3a5c accent.
|
|
--------------------------------------------------------------------------- */
|
|
|
|
.search-bar {
|
|
position: absolute;
|
|
top: 4px;
|
|
right: 4px;
|
|
z-index: 10;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 3px;
|
|
background: #181818;
|
|
border: 1px solid #2a2a2a;
|
|
border-radius: 5px;
|
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.55);
|
|
padding: 3px 4px;
|
|
font-family: "Cascadia Mono", "JetBrains Mono", "Consolas", monospace;
|
|
font-size: 12px;
|
|
color: #e6e6e6;
|
|
}
|
|
|
|
.search-input {
|
|
font: inherit;
|
|
font-size: 12px;
|
|
color: #e6e6e6;
|
|
background: #1f1f1f;
|
|
border: 1px solid #2a2a2a;
|
|
border-radius: 3px;
|
|
padding: 3px 7px;
|
|
outline: none;
|
|
width: 180px;
|
|
caret-color: #e6e6e6;
|
|
}
|
|
|
|
.search-input:focus {
|
|
border-color: #1a3a5c;
|
|
box-shadow: 0 0 0 1px #1a3a5c;
|
|
}
|
|
|
|
.search-input::placeholder {
|
|
color: #555;
|
|
}
|
|
|
|
/* Toggle buttons (Aa / .*) */
|
|
.search-toggle {
|
|
font: inherit;
|
|
font-size: 11px;
|
|
background: transparent;
|
|
border: 1px solid #2a2a2a;
|
|
border-radius: 3px;
|
|
color: #888;
|
|
padding: 2px 5px;
|
|
cursor: pointer;
|
|
line-height: 1;
|
|
transition: background 0.1s, color 0.1s;
|
|
}
|
|
|
|
.search-toggle:hover,
|
|
.search-toggle[aria-pressed="true"] {
|
|
background: #1a3a5c;
|
|
border-color: #1a5c8a;
|
|
color: #cce6ff;
|
|
}
|
|
|
|
/* Prev / Next navigation arrows */
|
|
.search-nav {
|
|
font: inherit;
|
|
font-size: 13px;
|
|
background: transparent;
|
|
border: 1px solid #2a2a2a;
|
|
border-radius: 3px;
|
|
color: #aaa;
|
|
padding: 1px 6px;
|
|
cursor: pointer;
|
|
line-height: 1;
|
|
}
|
|
|
|
.search-nav:hover {
|
|
background: #2a2a2a;
|
|
color: #e6e6e6;
|
|
}
|
|
|
|
/* Close button */
|
|
.search-close {
|
|
background: transparent;
|
|
border: none;
|
|
color: #666;
|
|
font-size: 16px;
|
|
line-height: 1;
|
|
padding: 1px 5px;
|
|
cursor: pointer;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.search-close:hover {
|
|
background: #2a2a2a;
|
|
color: #ddd;
|
|
}
|