Polish Launcher host access controls

Keep the Core trigger compact until hover, focus, or open, and use the supported computer glyph for disconnected state. Raise the open popover above the compact Canvas rail so its controls remain unobstructed.

Alessandro committed Jul 14, 2026 at 21:27 UTC df6065d5b1f66af9cbf2414914d5147dd1aa1673
3 files changed +24 -7
plugins/_a0_connector/AGENTS.md
+4 -1
@@ -39,7 +39,10 @@
39 - The `chat-top-end` Launcher gateway extension renders only when the user agent
40 includes `A0-Launcher/`. It may show status, master/scope controls,
41 preparation errors, and Emergency disconnect; standard browser sessions must
42 - not expose it.
42 + not expose it. Keep its trigger icon-only at rest and reveal the status label
43 + on hover, keyboard focus, or while open. Connected and disconnected states
44 + share the computer glyph; the adjacent status dot communicates connectivity.
45 + Keep the open popover above the compact right-canvas rail.
46 - File operation results may arrive as chunked JSON/base64
47 `connector_file_op_result` frames; resolve the pending file operation only
48 after all chunks for the `op_id` are assembled.
plugins/_a0_connector/extensions/webui/chat-top-end/launcher-gateway.html
+18 -4
@@ -15,7 +15,7 @@
15 <button
16 type="button"
17 class="launcher-gateway-trigger"
18 - :class="`is-${$store.launcherGateway.state}`"
18 + :class="`is-${$store.launcherGateway.state}${$store.launcherGateway.open ? ' is-open' : ''}`"
19 :title="`Host access: ${$store.launcherGateway.stateLabel}`"
20 :aria-label="`Host access: ${$store.launcherGateway.stateLabel}`"
21 aria-haspopup="dialog"
@@ -92,15 +92,27 @@
92 </div>
93
94 <style>
95 + #time-date-container:has(.launcher-gateway-trigger.is-open) { z-index: 3500; }
96 .launcher-gateway-root { position: relative; }
97 .launcher-gateway-trigger {
97 - display: inline-flex; align-items: center; gap: .35rem; min-height: 2rem;
98 + display: inline-flex; align-items: center; gap: 0; min-height: 2rem;
99 padding: .25rem .55rem; border: 1px solid var(--color-border); border-radius: 999px;
100 color: var(--color-text); background: color-mix(in srgb, var(--color-panel) 92%, transparent);
101 cursor: pointer; font: inherit; font-size: .75rem;
102 }
103 .launcher-gateway-trigger .material-symbols-outlined { font-size: 1rem; }
103 - .launcher-gateway-dot { width: .45rem; height: .45rem; border-radius: 50%; background: #7b8491; }
104 + .launcher-gateway-trigger-label {
105 + max-width: 0; margin-left: 0; overflow: hidden; opacity: 0; white-space: nowrap;
106 + transition: max-width 180ms cubic-bezier(.4, 0, .2, 1),
107 + margin-left 180ms cubic-bezier(.4, 0, .2, 1),
108 + opacity 120ms ease-out;
109 + }
110 + .launcher-gateway-root:hover .launcher-gateway-trigger-label,
111 + .launcher-gateway-trigger:focus-visible .launcher-gateway-trigger-label,
112 + .launcher-gateway-trigger.is-open .launcher-gateway-trigger-label {
113 + max-width: 8rem; margin-left: .35rem; opacity: 1;
114 + }
115 + .launcher-gateway-dot { width: .45rem; height: .45rem; margin-right: .35rem; border-radius: 50%; background: #7b8491; }
116 .launcher-gateway-trigger.is-connected .launcher-gateway-dot { background: #45b86b; }
117 .launcher-gateway-trigger.is-connecting .launcher-gateway-dot { background: #5b9cff; }
118 .launcher-gateway-trigger.is-paused .launcher-gateway-dot { background: #d6a43d; }
@@ -127,5 +139,7 @@
139 .launcher-gateway-empty { margin: .7rem 0 0; color: var(--color-text-secondary); font-size: .78rem; }
140 .launcher-gateway-disconnect { width: 100%; margin-top: .75rem; padding: .48rem .65rem; border: 1px solid color-mix(in srgb, #db5b61 55%, var(--color-border)); border-radius: .45rem; background: transparent; color: #db5b61; cursor: pointer; }
141 .launcher-gateway-disconnect:disabled { opacity: .55; cursor: default; }
130 - @media (max-width: 700px) { .launcher-gateway-trigger-label { display: none; } }
142 + @media (prefers-reduced-motion: reduce) {
143 + .launcher-gateway-trigger-label { transition: none; }
144 + }
145 </style>
plugins/_a0_connector/webui/launcher-gateway-store.js
+2 -2
@@ -44,9 +44,9 @@ const model = {
44 needs_action: "warning",
45 error: "error",
46 multiple_hosts: "devices",
47 - disconnected: "computer_off",
47 + disconnected: "computer",
48 };
49 - return icons[this.state] || "computer_off";
49 + return icons[this.state] || "computer";
50 },
51
52 get hostLabel() {