Files
gstack/extension/sidepanel.html
T
Garry Tan a36a3ac4d7 feat: sidebar per-tab chat context, tab bar sync, stop button, UX polish
Extension changes:
- sidepanel.js: per-tab chat history (tabChatHistories map), switchChatTab()
  swaps entire chat view, browserTabActivated handler for instant tab sync,
  stop button wired to /sidebar-agent/stop, pollTabs renders tab bar
- sidepanel.html: updated banner text ("Browser co-pilot"), stop button markup,
  input placeholder "Ask about this page..."
- sidepanel.css: tab bar styles, stop button styles, loading state fixes
- background.js: chrome.tabs.onActivated sends browserTabActivated to sidepanel
  with tab URL for instant tab switch detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:19:30 -07:00

167 lines
6.9 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="sidepanel.css">
</head>
<body>
<!-- Connection status banner -->
<div class="conn-banner" id="conn-banner" style="display:none">
<span class="conn-banner-text" id="conn-banner-text">Reconnecting...</span>
<div class="conn-banner-actions" id="conn-banner-actions" style="display:none">
<button class="conn-btn" id="conn-reconnect">Reconnect</button>
<button class="conn-btn conn-copy" id="conn-copy" title="Copy command">/connect-chrome</button>
</div>
</div>
<!-- Browser tab bar -->
<div class="browser-tabs" id="browser-tabs" style="display:none"></div>
<!-- Chat Tab (default, full height) -->
<main id="tab-chat" class="tab-content active">
<div class="chat-messages" id="chat-messages">
<div class="chat-loading" id="chat-loading">
<div class="chat-loading-spinner"></div>
<p>Connecting...</p>
</div>
<div class="chat-welcome" id="chat-welcome" style="display:none">
<div class="chat-welcome-icon">G</div>
<p>Send a message to Claude Code.</p>
<p class="muted">Your agent will see it and act on it.</p>
</div>
</div>
</main>
<!-- Debug: Activity Tab (hidden by default) -->
<main id="tab-activity" class="tab-content" role="log" aria-live="polite">
<div class="empty-state" id="empty-state">
<p>Waiting for commands...</p>
<p class="muted">Run a browse command to see activity here.</p>
</div>
<div id="activity-feed"></div>
</main>
<!-- Debug: Refs Tab (hidden by default) -->
<main id="tab-refs" class="tab-content">
<div class="empty-state" id="refs-empty">
<p>No refs yet</p>
<p class="muted">Run <code>snapshot</code> to see element refs.</p>
</div>
<div id="refs-list"></div>
<div class="refs-footer" id="refs-footer"></div>
</main>
<!-- Debug: Inspector Tab (hidden by default) -->
<main id="tab-inspector" class="tab-content">
<!-- Toolbar: always visible -->
<div class="inspector-toolbar" id="inspector-toolbar">
<button class="inspector-pick-btn" id="inspector-pick-btn" title="Pick an element (click, then click any element on the page)">
<span class="inspector-pick-icon">&#x271B;</span> Pick
</button>
<span class="inspector-selected" id="inspector-selected"></span>
<span class="inspector-mode-badge" id="inspector-mode-badge" style="display:none"></span>
</div>
<!-- Inspector content area -->
<div class="inspector-content" id="inspector-content">
<!-- Empty state (before first pick) -->
<div class="inspector-empty" id="inspector-empty">
<div class="inspector-empty-icon">&#x271B;</div>
<p>Pick an element to inspect</p>
<p class="muted">Click the button above, then click any element on the page</p>
</div>
<!-- Loading state -->
<div class="inspector-loading" id="inspector-loading" style="display:none">
<div class="inspector-loading-text">Inspecting...</div>
<div class="inspector-skeleton">
<div class="inspector-skeleton-bar"></div>
<div class="inspector-skeleton-bar"></div>
<div class="inspector-skeleton-bar"></div>
</div>
</div>
<!-- Error state -->
<div class="inspector-error" id="inspector-error" style="display:none"></div>
<!-- Inspector data panels -->
<div class="inspector-panels" id="inspector-panels" style="display:none">
<!-- Box Model -->
<div class="inspector-section" id="inspector-boxmodel-section">
<div class="inspector-section-header">Box Model</div>
<div class="inspector-boxmodel" id="inspector-boxmodel"></div>
</div>
<!-- Matched Rules -->
<div class="inspector-section" id="inspector-rules-section">
<button class="inspector-section-toggle" data-section="rules" aria-expanded="true">
<span class="inspector-toggle-arrow">&#x25BC;</span>
<span>Matched Rules</span>
<span class="inspector-rule-count" id="inspector-rule-count"></span>
</button>
<div class="inspector-section-body" id="inspector-rules" role="tree"></div>
</div>
<!-- Computed Styles -->
<div class="inspector-section" id="inspector-computed-section">
<button class="inspector-section-toggle collapsed" data-section="computed" aria-expanded="false">
<span class="inspector-toggle-arrow">&#x25B6;</span>
<span>Computed</span>
</button>
<div class="inspector-section-body collapsed" id="inspector-computed"></div>
</div>
<!-- Quick Edit -->
<div class="inspector-section" id="inspector-quickedit-section">
<button class="inspector-section-toggle collapsed" data-section="quickedit" aria-expanded="false">
<span class="inspector-toggle-arrow">&#x25B6;</span>
<span>Quick Edit</span>
</button>
<div class="inspector-section-body collapsed" id="inspector-quickedit"></div>
</div>
</div>
</div>
<!-- Send to Agent: sticky bottom -->
<div class="inspector-send" id="inspector-send" style="display:none">
<button class="inspector-send-btn" id="inspector-send-btn">Send to Agent</button>
</div>
</main>
<!-- Experimental chat banner (shown when chatEnabled) -->
<div id="experimental-banner" class="experimental-banner" style="display: none;">
Browser co-pilot &mdash; controls this browser, reports back to your workspace
</div>
<!-- Command Bar -->
<div class="command-bar">
<button class="stop-btn" id="stop-agent-btn" title="Stop agent" style="display: none;">&#x25A0;</button>
<input type="text" class="command-input" id="command-input" placeholder="Ask about this page..." autocomplete="off" spellcheck="false">
<button class="send-btn" id="send-btn" title="Send">&#x2191;</button>
</div>
<!-- Footer with connection + debug toggle -->
<footer>
<div class="footer-left">
<button class="debug-toggle" id="debug-toggle" title="Toggle debug panels">debug</button>
<button class="footer-btn" id="clear-chat" title="Clear chat">clear</button>
</div>
<div class="footer-right">
<span class="dot" id="footer-dot"></span>
<span class="footer-port" id="footer-port" title="Click to change port"></span>
<input type="text" class="port-input" id="port-input" placeholder="34567" autocomplete="off" style="display:none">
</div>
</footer>
<!-- Debug tab bar (hidden by default) -->
<nav class="tabs debug-tabs" id="debug-tabs" role="tablist" style="display:none">
<button class="tab" role="tab" data-tab="activity">Activity</button>
<button class="tab" role="tab" data-tab="refs">Refs</button>
<button class="tab" role="tab" data-tab="inspector">Inspector</button>
<button class="tab close-debug" id="close-debug" title="Close debug">&times;</button>
</nav>
<script src="sidepanel.js"></script>
</body>
</html>