diff --git a/infra/shell/system-ui.html b/infra/shell/system-ui.html index 56672d4..517b0c6 100644 --- a/infra/shell/system-ui.html +++ b/infra/shell/system-ui.html @@ -133,6 +133,39 @@ flex-shrink: 0; } + weft-taskbar-app { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 12px; + color: var(--text-secondary); + padding: 0 4px 0 6px; + cursor: pointer; + border-radius: 6px; + transition: background 0.15s; + } + + weft-taskbar-app:hover { + background: var(--surface-border); + } + + weft-taskbar-app .task-close { + opacity: 0; + font-size: 11px; + line-height: 1; + padding: 1px 3px; + border-radius: 3px; + transition: opacity 0.1s, background 0.1s; + } + + weft-taskbar-app:hover .task-close { + opacity: 1; + } + + weft-taskbar-app .task-close:hover { + background: rgba(255,80,80,0.3); + } + weft-notification-center { position: fixed; top: 8px; @@ -307,9 +340,21 @@ el.id = id; el.dataset.sessionId = sessionId; if (appId) { el.dataset.appId = appId; } - el.textContent = '● ' + label; - el.style.cssText = 'font-size:12px;color:var(--text-secondary);padding:0 6px;cursor:pointer;'; el.title = appId ? appId + ' (session ' + sessionId + ')' : 'Session ' + sessionId; + var span = document.createElement('span'); + span.textContent = '● ' + label; + var close = document.createElement('span'); + close.className = 'task-close'; + close.textContent = '×'; + close.title = 'Terminate'; + close.addEventListener('click', function (e) { + e.stopPropagation(); + if (ws && ws.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ type: 'TERMINATE_APP', session_id: sessionId })); + } + }); + el.appendChild(span); + el.appendChild(close); var taskbar = document.querySelector('weft-taskbar'); var clock = document.getElementById('clock'); taskbar.insertBefore(el, clock);