Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions gearbox/internal/framework/templates/components/console.templ
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,65 @@ templ ConsoleDrawer() {
</svg>
</button>
</div>
// Search overlay — hidden until Ctrl-F/Cmd-F triggers it.
// Powered by xterm-addon-search; input wired in console.js.
<div id="console-search-bar" class="console-search-bar hidden" role="search">
<input
type="text"
id="console-search-input"
class="console-search-input"
placeholder="Find in terminal…"
aria-label="Find in terminal"
/>
<span id="console-search-count" class="console-search-count" aria-live="polite"></span>
<button type="button"
id="console-search-prev"
class="console-tool-btn"
aria-label="Previous match"
title="Previous match (Shift-Enter)">
<svg class="w-4 h-4" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7"></path>
</svg>
</button>
<button type="button"
id="console-search-next"
class="console-tool-btn"
aria-label="Next match"
title="Next match (Enter)">
<svg class="w-4 h-4" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<button type="button"
id="console-search-close"
class="console-tool-btn"
aria-label="Close search"
title="Close (Esc)">
<svg class="w-4 h-4" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
// xterm host. Sessions attach their own xterm <div> into this.
// `console-xterm-pad` adds breathing room so cursor/text isn't
// flush against the panel border.
<div class="console-xterm-pad flex-1 overflow-hidden bg-black">
<div id="console-xterm" class="w-full h-full"></div>
</div>
// Large-paste confirmation modal. Triggered by ConsoleManager
// when clipboard content exceeds the paste-confirm threshold
// (default 20 newlines). Buttons wired in console.js.
<div id="console-paste-modal" class="console-paste-modal hidden" role="dialog" aria-modal="true" aria-labelledby="console-paste-modal-title">
<div class="console-paste-modal-panel">
<h3 id="console-paste-modal-title" class="console-paste-modal-title">Paste <span id="console-paste-modal-lines">?</span> lines?</h3>
<p class="console-paste-modal-hint">Large pastes run many commands in sequence. Review the preview before confirming.</p>
<pre id="console-paste-modal-preview" class="console-paste-modal-preview" aria-label="Paste preview"></pre>
<div class="console-paste-modal-actions">
<button type="button" id="console-paste-modal-cancel" class="console-paste-modal-btn console-paste-modal-cancel">Cancel</button>
<button type="button" id="console-paste-modal-confirm" class="console-paste-modal-btn console-paste-modal-confirm">Paste</button>
</div>
</div>
</div>
</div>
}

Expand All @@ -133,5 +186,6 @@ templ ConsoleAssets() {
<link rel="stylesheet" href="/static/css/components/console.css"/>
<script src="/static/js/vendor/xterm.min.js" defer></script>
<script src="/static/js/vendor/xterm-addon-fit.min.js" defer></script>
<script src="/static/js/vendor/xterm-addon-search.min.js" defer></script>
<script src="/static/js/console/console.js" defer></script>
}
128 changes: 127 additions & 1 deletion gearbox/static/css/components/console.css
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ body.console-dock-open {
.console-tool-btn.hidden,
.console-tab-dot.hidden,
.console-tab-new.hidden,
.console-tab-bar.hidden {
.console-tab-bar.hidden,
.console-search-bar.hidden,
.console-paste-modal.hidden {
display: none;
}

Expand Down Expand Up @@ -203,6 +205,20 @@ body.console-dock-open {
cursor: pointer;
padding: 0;
}

/* Inline rename input — sized to match the original label so the tab
* doesn't jump width on edit. */
.console-tab-rename {
background: rgb(2, 6, 23);
color: rgb(226, 232, 240);
border: 1px solid rgb(52, 211, 153);
border-radius: 2px;
font: inherit;
font-size: 12px;
padding: 0 4px;
min-width: 80px;
max-width: 200px;
}
.console-tab-close {
background: none;
border: none;
Expand Down Expand Up @@ -231,6 +247,116 @@ body.console-dock-open {
display: none;
}

/* ---------- search overlay ---------- */

/* Floats below the header in drawer/dock; absolute so it doesn't push
* the xterm host. Width matches the panel content area. */
.console-search-bar {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
background: rgb(15, 23, 42);
border-bottom: 1px solid rgb(51, 65, 85);
}
Comment thread
sarg3nt marked this conversation as resolved.
.console-search-input {
flex: 1 1 auto;
min-width: 0;
background: rgb(2, 6, 23);
color: rgb(226, 232, 240);
border: 1px solid rgb(51, 65, 85);
border-radius: 4px;
padding: 4px 8px;
font-size: 12px;
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
.console-search-input:focus {
outline: none;
border-color: rgb(52, 211, 153);
}
.console-search-count {
font-size: 11px;
color: rgb(148, 163, 184);
min-width: 50px;
text-align: right;
font-variant-numeric: tabular-nums;
}

/* ---------- paste-confirm modal ---------- */

.console-paste-modal {
position: absolute;
inset: 0;
z-index: 5;
background: rgba(0, 0, 0, 0.7);
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
}
.console-paste-modal-panel {
background: rgb(15, 23, 42);
border: 1px solid rgb(51, 65, 85);
border-radius: 6px;
max-width: 560px;
width: 100%;
padding: 16px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}
.console-paste-modal-title {
font-size: 14px;
font-weight: 600;
color: rgb(226, 232, 240);
margin: 0 0 4px 0;
}
.console-paste-modal-hint {
font-size: 12px;
color: rgb(148, 163, 184);
margin: 0 0 8px 0;
}
.console-paste-modal-preview {
background: rgb(2, 6, 23);
color: rgb(203, 213, 225);
border: 1px solid rgb(51, 65, 85);
border-radius: 4px;
padding: 8px;
font-size: 11px;
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
max-height: 200px;
overflow: auto;
white-space: pre-wrap;
word-break: break-all;
margin: 0 0 12px 0;
}
.console-paste-modal-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
}
.console-paste-modal-btn {
padding: 6px 12px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
border: 1px solid rgb(51, 65, 85);
cursor: pointer;
}
.console-paste-modal-cancel {
background: rgb(30, 41, 59);
color: rgb(226, 232, 240);
}
.console-paste-modal-cancel:hover {
background: rgb(51, 65, 85);
}
.console-paste-modal-confirm {
background: rgb(52, 211, 153);
color: rgb(2, 6, 23);
border-color: rgb(52, 211, 153);
}
.console-paste-modal-confirm:hover {
background: rgb(110, 231, 183);
}

/* ---------- xterm padding ---------- */

/* xterm.js paints right up to its container's edges by default. The
Expand Down
Loading
Loading