|
1 | 1 | package components |
2 | 2 |
|
3 | | -// ConsoleDrawer renders the markup for the remote-console drawer |
4 | | -// (one per layout, opened on demand by window.openConsole). The |
5 | | -// xterm.js terminal mounts into #console-xterm; the title bar shows |
6 | | -// which box the session targets so the user can't mix them up if |
7 | | -// they have multiple browser tabs open against different boxes. |
| 3 | +// ConsoleDrawer renders the chrome for the multi-session remote console. |
| 4 | +// One copy lives in the base layout (for the in-page drawer/dock) and is |
| 5 | +// also rendered standalone by the popout page. |
8 | 6 | // |
9 | | -// Hidden by default. Opened by static/js/console/console.js. The |
10 | | -// fullscreen overlay sits at z-[200] so it lands above existing |
11 | | -// modals (z-[100]); a console session is the most foreground thing |
12 | | -// the UI can show. |
| 7 | +// Sessions are managed by static/js/console/console.js (ConsoleManager). |
| 8 | +// The xterm.js terminals mount into #console-xterm; the manager swaps the |
| 9 | +// active session's <div> into/out of that host on tab switches. |
| 10 | +// |
| 11 | +// Layout state lives on the root #console-drawer element via the |
| 12 | +// `console-layout-drawer` and `console-layout-dock` classes; CSS in |
| 13 | +// components/console.css positions accordingly. Hidden by default. |
13 | 14 | templ ConsoleDrawer() { |
14 | 15 | <div id="console-drawer" |
15 | | - class="fixed inset-0 z-[200] hidden flex-col bg-slate-900 text-slate-100" |
| 16 | + class="hidden flex-col bg-slate-900 text-slate-100 console-layout-drawer" |
16 | 17 | role="dialog" |
17 | | - aria-labelledby="console-drawer-title" |
| 18 | + aria-label="Remote console" |
18 | 19 | aria-modal="true"> |
19 | | - <div class="flex items-center justify-between px-4 py-2 border-b border-slate-700 bg-slate-800"> |
20 | | - <div class="flex items-center gap-3 min-w-0"> |
21 | | - <svg class="w-5 h-5 text-emerald-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
22 | | - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path> |
23 | | - </svg> |
24 | | - <h2 id="console-drawer-title" class="text-sm font-medium truncate"> |
25 | | - Console: <span id="console-drawer-box" class="font-mono"></span> |
26 | | - </h2> |
27 | | - <span id="console-drawer-status" |
28 | | - class="text-xs px-2 py-0.5 rounded-full bg-slate-700 text-slate-300 flex-shrink-0"> |
29 | | - connecting… |
30 | | - </span> |
31 | | - <span id="console-drawer-mode" |
32 | | - class="text-xs px-2 py-0.5 rounded-full bg-slate-700 text-slate-400 flex-shrink-0 font-mono"></span> |
33 | | - <span id="console-drawer-uid" |
34 | | - class="text-xs px-2 py-0.5 rounded-full bg-slate-700 text-slate-400 flex-shrink-0 font-mono"></span> |
| 20 | + // Dock-only drag handle. CSS hides it in drawer mode. Mouse-down |
| 21 | + // captured by ConsoleManager._wireDockResize. |
| 22 | + <div id="console-dock-handle" |
| 23 | + class="console-dock-handle" |
| 24 | + role="separator" |
| 25 | + aria-orientation="horizontal" |
| 26 | + aria-label="Resize console dock" |
| 27 | + title="Drag to resize"></div> |
| 28 | + // Header: title block on the left, status pills next, toolbar on |
| 29 | + // the right, close button at the far end. |
| 30 | + // Header now hosts only the toolbar — the box name lives in the |
| 31 | + // active tab and the per-tab dot carries connection state, so the |
| 32 | + // header has no left-side content to render. Vertical padding |
| 33 | + // kept tight (py-1) so the bar stays thin. |
| 34 | + <div class="console-header flex items-center justify-end px-3 py-1 border-b border-slate-700 bg-slate-800 gap-3"> |
| 35 | + <div class="flex items-center gap-2 flex-shrink-0"> |
| 36 | + // Font-size slider — matches the logs-viewer pattern. Value |
| 37 | + // persisted via localStorage by ConsoleManager. |
| 38 | + <div class="flex items-center gap-2 mr-2"> |
| 39 | + <label for="console-font-slider" class="text-xs text-slate-300">Font</label> |
| 40 | + <input |
| 41 | + type="range" |
| 42 | + id="console-font-slider" |
| 43 | + min="10" |
| 44 | + max="24" |
| 45 | + value="13" |
| 46 | + class="w-20 h-2 bg-slate-700 rounded-lg appearance-none cursor-pointer" |
| 47 | + aria-label="Console font size" |
| 48 | + /> |
| 49 | + <span id="console-font-value" class="text-xs text-slate-400 w-10">13px</span> |
| 50 | + </div> |
| 51 | + <button type="button" |
| 52 | + id="console-btn-clear" |
| 53 | + class="console-tool-btn" |
| 54 | + aria-label="Clear terminal buffer" |
| 55 | + title="Clear (Ctrl-L sends to remote; this just clears the local buffer)"> |
| 56 | + <svg class="w-4 h-4" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 57 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6M1 7h22M9 7V4a1 1 0 011-1h4a1 1 0 011 1v3"></path> |
| 58 | + </svg> |
| 59 | + </button> |
| 60 | + // Layout switchers — drawer/dock are mutually exclusive, so |
| 61 | + // only the inactive one is visible at a time (JS toggles |
| 62 | + // .hidden on each based on the active layout). Popout |
| 63 | + // stays visible; the popout page hides all three. |
| 64 | + <button type="button" |
| 65 | + id="console-btn-layout-drawer" |
| 66 | + class="console-tool-btn" |
| 67 | + aria-label="Switch to fullscreen layout" |
| 68 | + title="Fullscreen drawer"> |
| 69 | + <svg class="w-4 h-4" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 70 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4"></path> |
| 71 | + </svg> |
| 72 | + </button> |
| 73 | + <button type="button" |
| 74 | + id="console-btn-layout-dock" |
| 75 | + class="console-tool-btn" |
| 76 | + aria-label="Switch to docked layout" |
| 77 | + title="Dock to bottom"> |
| 78 | + <svg class="w-4 h-4" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 79 | + <rect x="3" y="4" width="18" height="16" rx="2" stroke-width="2"></rect> |
| 80 | + <line x1="3" y1="14" x2="21" y2="14" stroke-width="2"></line> |
| 81 | + </svg> |
| 82 | + </button> |
| 83 | + <button type="button" |
| 84 | + id="console-btn-layout-popout" |
| 85 | + class="console-tool-btn" |
| 86 | + aria-label="Open console in new window" |
| 87 | + title="Open in new window"> |
| 88 | + <svg class="w-4 h-4" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 89 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path> |
| 90 | + </svg> |
| 91 | + </button> |
| 92 | + <button type="button" |
| 93 | + id="console-drawer-close" |
| 94 | + class="console-tool-btn" |
| 95 | + aria-label="Close console" |
| 96 | + title="Close console (Esc)"> |
| 97 | + <svg class="w-4 h-4" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 98 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path> |
| 99 | + </svg> |
| 100 | + </button> |
35 | 101 | </div> |
| 102 | + </div> |
| 103 | + // Tab bar — tabs (populated by ConsoleManager) + "+ new tab" button. |
| 104 | + // The bar is hidden by default and revealed by the manager once a |
| 105 | + // session opens; we keep the "+" inline with the tabs so it's |
| 106 | + // discoverable in the same place browsers/iTerm/etc. put it. |
| 107 | + <div id="console-tab-bar" class="console-tab-bar hidden"> |
| 108 | + <div id="console-tabs" class="console-tabs" role="tablist"></div> |
36 | 109 | <button type="button" |
37 | | - id="console-drawer-close" |
38 | | - class="text-slate-400 hover:text-white p-1" |
39 | | - title="Close console (Esc)"> |
40 | | - <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
41 | | - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path> |
| 110 | + id="console-btn-newtab" |
| 111 | + class="console-tab-new" |
| 112 | + aria-label="New tab" |
| 113 | + title="Open another tab to this box"> |
| 114 | + <svg class="w-3 h-3" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 115 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path> |
42 | 116 | </svg> |
43 | 117 | </button> |
44 | 118 | </div> |
45 | | - <div id="console-xterm" class="flex-1 overflow-hidden bg-black"></div> |
| 119 | + // xterm host. Sessions attach their own xterm <div> into this. |
| 120 | + // `console-xterm-pad` adds breathing room so cursor/text isn't |
| 121 | + // flush against the panel border. |
| 122 | + <div class="console-xterm-pad flex-1 overflow-hidden bg-black"> |
| 123 | + <div id="console-xterm" class="w-full h-full"></div> |
| 124 | + </div> |
46 | 125 | </div> |
47 | 126 | } |
48 | 127 |
|
49 | | -// ConsoleAssets pulls in the xterm.js bundle, fit addon, and CSS. |
50 | | -// Place once near the bottom of the layout (after the existing |
51 | | -// vendor scripts) so window.Terminal exists before console.js runs. |
52 | | -// |
53 | | -// The actual wiring code is in static/js/console/console.js — kept |
54 | | -// in JS so the bundler-free workflow stays simple and so tests can |
55 | | -// stub window.openConsole without recompiling Go. |
| 128 | +// ConsoleAssets pulls in the xterm.js bundle, fit addon, console CSS, and |
| 129 | +// the console manager. Place once near the bottom of any layout that |
| 130 | +// surfaces the console (the popout page uses this directly). |
56 | 131 | templ ConsoleAssets() { |
57 | 132 | <link rel="stylesheet" href="/static/css/vendor/xterm.min.css"/> |
| 133 | + <link rel="stylesheet" href="/static/css/components/console.css"/> |
58 | 134 | <script src="/static/js/vendor/xterm.min.js" defer></script> |
59 | 135 | <script src="/static/js/vendor/xterm-addon-fit.min.js" defer></script> |
60 | 136 | <script src="/static/js/console/console.js" defer></script> |
|
0 commit comments