lvwerra HF Staff Claude Opus 4.6 commited on
Commit
339deb5
·
1 Parent(s): ad948a8

Replace welcome SVG diagram with real timeline component, hide sidebar on welcome

Browse files

- Replace static SVG workflow diagram with actual timeline widgets (agent-box, tl-dot, tl-nested, etc.)
- Diagram auto-adapts to all themes via CSS vars — delete ~50 lines of dark-theme SVG overrides
- Hide timeline sidebar on welcome/session-selector page, restore on session start
- Add updateTimelineLines() call on init for welcome diagram line computation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

frontend/app.js CHANGED
@@ -48,6 +48,9 @@ document.addEventListener('DOMContentLoaded', async () => {
48
  // Always show session selector on load (don't auto-resume last session)
49
  const sessionsData = await fetchSessions();
50
  showSessionSelector(sessionsData.sessions);
 
 
 
51
  });
52
 
53
  // ============================================================
 
48
  // Always show session selector on load (don't auto-resume last session)
49
  const sessionsData = await fetchSessions();
50
  showSessionSelector(sessionsData.sessions);
51
+
52
+ // Compute line heights for the static welcome diagram (after layout)
53
+ requestAnimationFrame(() => updateTimelineLines());
54
  });
55
 
56
  // ============================================================
frontend/index.html CHANGED
@@ -110,57 +110,82 @@
110
  <li><strong style="color: var(--theme-accent)">IMAGE</strong> — Image generation and editing</li>
111
  <li><strong style="color: var(--theme-accent)">COMPUTER</strong> <em>(coming soon)</em> — Computer control and automation</li>
112
  </ul>
113
- <div class="workflow-diagram">
114
- <svg class="diagram-svg" viewBox="0 0 500 180" preserveAspectRatio="xMidYMid meet">
115
- <defs>
116
- <marker id="arrowhead" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
117
- <polygon points="0 0, 8 3, 0 6" fill="var(--theme-accent)" />
118
- </marker>
119
- </defs>
120
-
121
- <!-- Main Agent Box -->
122
- <rect x="20" y="10" width="180" height="160" rx="4" fill="#fafafa" stroke="#e0e0e0" stroke-width="1"/>
123
- <text x="110" y="28" text-anchor="middle" font-size="11" font-weight="600" fill="var(--theme-accent)">MAIN AGENT</text>
124
-
125
- <!-- User Message -->
126
- <rect x="35" y="40" width="150" height="24" rx="3" fill="white" stroke="var(--theme-accent)" stroke-width="1"/>
127
- <text x="110" y="56" text-anchor="middle" font-size="9" fill="#333">User input</text>
128
-
129
- <!-- Sub-Agent Widget (combined task + result) -->
130
- <rect x="35" y="74" width="150" height="86" rx="3" fill="white" stroke="#ccc" stroke-width="1"/>
131
- <rect x="35" y="74" width="150" height="20" rx="3" fill="var(--theme-accent)"/>
132
- <text x="110" y="88" text-anchor="middle" font-size="9" font-weight="500" fill="white">SUB-AGENT</text>
133
- <text x="110" y="115" text-anchor="middle" font-size="9" fill="#666">processing...</text>
134
- <line x1="45" y1="130" x2="175" y2="130" stroke="#eee" stroke-width="1"/>
135
- <text x="110" y="150" text-anchor="middle" font-size="9" fill="#333">Result</text>
136
-
137
- <!-- Sub-Agent Box -->
138
- <rect x="300" y="10" width="180" height="160" rx="4" fill="#fafafa" stroke="#e0e0e0" stroke-width="1"/>
139
- <text x="390" y="28" text-anchor="middle" font-size="11" font-weight="600" fill="var(--theme-accent)">SUB-AGENT</text>
140
-
141
- <!-- Query (top of agent) -->
142
- <rect x="315" y="40" width="150" height="24" rx="3" fill="white" stroke="var(--theme-accent)" stroke-width="1"/>
143
- <text x="390" y="56" text-anchor="middle" font-size="9" fill="#333">Query</text>
144
-
145
- <!-- Intermediate steps (faded) -->
146
- <rect x="315" y="72" width="150" height="14" rx="2" fill="#f5f5f5" stroke="#e8e8e8" stroke-width="1"/>
147
- <text x="390" y="82" text-anchor="middle" font-size="8" fill="#aaa">step 1</text>
148
- <rect x="315" y="90" width="150" height="14" rx="2" fill="#f8f8f8" stroke="#eee" stroke-width="1"/>
149
- <text x="390" y="100" text-anchor="middle" font-size="8" fill="#bbb">step 2</text>
150
- <rect x="315" y="108" width="150" height="14" rx="2" fill="#fbfbfb" stroke="#f0f0f0" stroke-width="1"/>
151
- <text x="390" y="118" text-anchor="middle" font-size="8" fill="#ccc">...</text>
152
-
153
- <!-- Result (bottom of sub-agent) - aligned with sub-agent result area at y=145 -->
154
- <rect x="315" y="130" width="150" height="30" rx="3" fill="white" stroke="var(--theme-accent)" stroke-width="1"/>
155
- <text x="390" y="150" text-anchor="middle" font-size="9" fill="#333">Result</text>
156
-
157
- <!-- Arrows (drawn last to be on top) -->
158
- <!-- Arrow from Sub-Agent widget to Query (straight with corners) -->
159
- <polyline points="185,84 250,84 250,52 307,52" fill="none" stroke="var(--theme-accent)" stroke-width="1.5" marker-end="url(#arrowhead)" stroke-dasharray="4,2"/>
160
-
161
- <!-- Arrow from Result back to Main Agent (straight horizontal) -->
162
- <line x1="315" y1="150" x2="193" y2="150" stroke="var(--theme-accent)" stroke-width="1.5" marker-end="url(#arrowhead)"/>
163
- </svg>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  </div>
165
  <p>When an agent is opened, you'll see a widget you can click to jump to it. A pulsing dot on the tab indicates active generation.</p>
166
  </div>
 
110
  <li><strong style="color: var(--theme-accent)">IMAGE</strong> — Image generation and editing</li>
111
  <li><strong style="color: var(--theme-accent)">COMPUTER</strong> <em>(coming soon)</em> — Computer control and automation</li>
112
  </ul>
113
+ <div class="welcome-diagram">
114
+ <div class="tl-widget compact">
115
+ <div class="workspace-block">
116
+ <div class="workspace-label">Agent</div>
117
+ <div class="workspace-name">Main agent</div>
118
+ </div>
119
+ <div class="tl">
120
+ <!-- User query -->
121
+ <div class="tl-row turn user"><div class="tl-dot"></div><span class="tl-label">User query</span></div>
122
+ <!-- Thinking -->
123
+ <div class="tl-row turn"><div class="tl-dot"></div><span class="tl-label">Routing to sub-agents...</span></div>
124
+
125
+ <!-- Research sub-agent -->
126
+ <div class="tl-row has-agent has-nested">
127
+ <div class="tl-dot"></div>
128
+ <div class="agent-box">
129
+ <div class="agent-header"><div class="collapse-toggle"></div><span>Research</span></div>
130
+ <div class="agent-body">
131
+ <span class="agent-body-text">Sub-agent</span>
132
+ <div class="agent-status"><span>12 turns</span><div class="agent-done"></div></div>
133
+ </div>
134
+ </div>
135
+ </div>
136
+ <div class="tl-nested complete">
137
+ <div class="tl">
138
+ <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">search</span><span class="tl-tool-text">"topic overview"</span></div></div>
139
+ <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">read</span><span class="tl-tool-text">4 sources</span></div></div>
140
+ <div class="tl-row turn"><div class="tl-dot"></div><span class="tl-label">Synthesizing...</span></div>
141
+ <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">result</span></div></div>
142
+ </div>
143
+ </div>
144
+ <div class="tl-row tl-return"><div class="tl-dot"></div><div class="tl-return-connector"></div></div>
145
+
146
+ <!-- Code sub-agent -->
147
+ <div class="tl-row has-agent has-nested">
148
+ <div class="tl-dot"></div>
149
+ <div class="agent-box">
150
+ <div class="agent-header"><div class="collapse-toggle"></div><span>Code</span></div>
151
+ <div class="agent-body">
152
+ <span class="agent-body-text">Sub-agent</span>
153
+ <div class="agent-status"><span>4 turns</span><div class="agent-done"></div></div>
154
+ </div>
155
+ </div>
156
+ </div>
157
+ <div class="tl-nested complete">
158
+ <div class="tl">
159
+ <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">code</span><span class="tl-tool-text">import numpy as np</span></div></div>
160
+ <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">code</span><span class="tl-tool-text">plt.show()</span></div></div>
161
+ <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">result</span><span class="tl-tool-text">2 figures</span></div></div>
162
+ </div>
163
+ </div>
164
+ <div class="tl-row tl-return"><div class="tl-dot"></div><div class="tl-return-connector"></div></div>
165
+
166
+ <!-- Image sub-agent -->
167
+ <div class="tl-row has-agent has-nested">
168
+ <div class="tl-dot"></div>
169
+ <div class="agent-box">
170
+ <div class="agent-header"><div class="collapse-toggle"></div><span>Image</span></div>
171
+ <div class="agent-body">
172
+ <span class="agent-body-text">Sub-agent</span>
173
+ <div class="agent-status"><span>2 turns</span><div class="agent-done"></div></div>
174
+ </div>
175
+ </div>
176
+ </div>
177
+ <div class="tl-nested complete">
178
+ <div class="tl">
179
+ <div class="tl-row turn"><div class="tl-dot"></div><span class="tl-label">Generating image...</span></div>
180
+ <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">result</span><span class="tl-tool-text">1 image</span></div></div>
181
+ </div>
182
+ </div>
183
+ <div class="tl-row tl-return"><div class="tl-dot"></div><div class="tl-return-connector"></div></div>
184
+
185
+ <!-- Assistant summarizes -->
186
+ <div class="tl-row turn"><div class="tl-dot"></div><span class="tl-label">Summarize results</span></div>
187
+ </div>
188
+ </div>
189
  </div>
190
  <p>When an agent is opened, you'll see a widget you can click to jump to it. A pulsing dot on the tab indicates active generation.</p>
191
  </div>
frontend/sessions.js CHANGED
@@ -20,11 +20,13 @@ function showSessionSelector(sessions) {
20
  const sessionIndicator = document.getElementById('sessionIndicator');
21
  const inputArea = document.getElementById('commandInputArea');
22
 
23
- // Show welcome message and session selector
24
  if (welcome) welcome.style.display = 'block';
25
  if (selector) selector.style.display = 'block';
26
  if (sessionIndicator) sessionIndicator.style.display = 'none';
27
  if (inputArea) inputArea.style.display = 'none';
 
 
28
 
29
  // Populate existing sessions dropdown
30
  const select = document.getElementById('existingSessionSelect');
@@ -45,11 +47,13 @@ function hideSessionSelector() {
45
  const sessionIndicator = document.getElementById('sessionIndicator');
46
  const inputArea = document.getElementById('commandInputArea');
47
 
48
- // Hide session selector, keep welcome visible, show session indicator and input
49
  if (selector) selector.style.display = 'none';
50
  if (welcome) welcome.style.display = 'block';
51
  if (sessionIndicator) sessionIndicator.style.display = 'block';
52
  if (inputArea) inputArea.style.display = 'block';
 
 
53
  }
54
 
55
  async function onSessionSelected(sessionName) {
 
20
  const sessionIndicator = document.getElementById('sessionIndicator');
21
  const inputArea = document.getElementById('commandInputArea');
22
 
23
+ // Show welcome message and session selector, hide sidebar
24
  if (welcome) welcome.style.display = 'block';
25
  if (selector) selector.style.display = 'block';
26
  if (sessionIndicator) sessionIndicator.style.display = 'none';
27
  if (inputArea) inputArea.style.display = 'none';
28
+ const sidebar = document.getElementById('agentsSidebar');
29
+ if (sidebar) sidebar.style.display = 'none';
30
 
31
  // Populate existing sessions dropdown
32
  const select = document.getElementById('existingSessionSelect');
 
47
  const sessionIndicator = document.getElementById('sessionIndicator');
48
  const inputArea = document.getElementById('commandInputArea');
49
 
50
+ // Hide session selector, show session indicator, input, and sidebar
51
  if (selector) selector.style.display = 'none';
52
  if (welcome) welcome.style.display = 'block';
53
  if (sessionIndicator) sessionIndicator.style.display = 'block';
54
  if (inputArea) inputArea.style.display = 'block';
55
+ const sidebar = document.getElementById('agentsSidebar');
56
+ if (sidebar) sidebar.style.display = '';
57
  }
58
 
59
  async function onSessionSelected(sessionName) {
frontend/style.css CHANGED
@@ -992,22 +992,23 @@ body {
992
  font-weight: 500;
993
  }
994
 
995
- .workflow-diagram {
996
- margin: 20px 0;
997
- padding: 16px;
998
- background: var(--bg-tertiary);
999
- border: 1px solid var(--border-primary);
1000
- border-radius: 4px;
1001
  }
1002
 
1003
- .diagram-svg {
1004
- width: 100%;
1005
- max-width: 500px;
1006
- height: auto;
1007
- display: block;
1008
- margin: 0 auto;
1009
- font-family: inherit;
1010
  }
 
 
 
 
 
1011
 
1012
  /* Messages */
1013
  .message {
@@ -4032,57 +4033,6 @@ pre code [class*="token"] {
4032
  [data-theme="noir"] .input-container textarea { caret-color: #e0e0e0; }
4033
  [data-theme="eclipse"] .input-container textarea { caret-color: #5c9eff; }
4034
 
4035
- /* Dark themes: SVG workflow diagrams (hardcoded fill/stroke attributes) */
4036
- [data-theme="terminal"] .diagram-svg rect[fill="#fafafa"],
4037
- [data-theme="noir"] .diagram-svg rect[fill="#fafafa"],
4038
- [data-theme="eclipse"] .diagram-svg rect[fill="#fafafa"] { fill: var(--bg-card); }
4039
-
4040
- [data-theme="terminal"] .diagram-svg rect[fill="white"],
4041
- [data-theme="noir"] .diagram-svg rect[fill="white"],
4042
- [data-theme="eclipse"] .diagram-svg rect[fill="white"] { fill: var(--bg-tertiary); }
4043
-
4044
- [data-theme="terminal"] .diagram-svg rect[fill="#f5f5f5"],
4045
- [data-theme="terminal"] .diagram-svg rect[fill="#f8f8f8"],
4046
- [data-theme="terminal"] .diagram-svg rect[fill="#fbfbfb"],
4047
- [data-theme="noir"] .diagram-svg rect[fill="#f5f5f5"],
4048
- [data-theme="noir"] .diagram-svg rect[fill="#f8f8f8"],
4049
- [data-theme="noir"] .diagram-svg rect[fill="#fbfbfb"],
4050
- [data-theme="eclipse"] .diagram-svg rect[fill="#f5f5f5"],
4051
- [data-theme="eclipse"] .diagram-svg rect[fill="#f8f8f8"],
4052
- [data-theme="eclipse"] .diagram-svg rect[fill="#fbfbfb"] { fill: var(--bg-secondary); }
4053
-
4054
- [data-theme="terminal"] .diagram-svg rect[stroke="#e0e0e0"],
4055
- [data-theme="terminal"] .diagram-svg rect[stroke="#ccc"],
4056
- [data-theme="terminal"] .diagram-svg rect[stroke="#e8e8e8"],
4057
- [data-theme="terminal"] .diagram-svg rect[stroke="#eee"],
4058
- [data-theme="terminal"] .diagram-svg rect[stroke="#f0f0f0"],
4059
- [data-theme="noir"] .diagram-svg rect[stroke="#e0e0e0"],
4060
- [data-theme="noir"] .diagram-svg rect[stroke="#ccc"],
4061
- [data-theme="noir"] .diagram-svg rect[stroke="#e8e8e8"],
4062
- [data-theme="noir"] .diagram-svg rect[stroke="#eee"],
4063
- [data-theme="noir"] .diagram-svg rect[stroke="#f0f0f0"],
4064
- [data-theme="eclipse"] .diagram-svg rect[stroke="#e0e0e0"],
4065
- [data-theme="eclipse"] .diagram-svg rect[stroke="#ccc"],
4066
- [data-theme="eclipse"] .diagram-svg rect[stroke="#e8e8e8"],
4067
- [data-theme="eclipse"] .diagram-svg rect[stroke="#eee"],
4068
- [data-theme="eclipse"] .diagram-svg rect[stroke="#f0f0f0"] { stroke: var(--border-primary); }
4069
-
4070
- [data-theme="terminal"] .diagram-svg text[fill="#333"],
4071
- [data-theme="noir"] .diagram-svg text[fill="#333"],
4072
- [data-theme="eclipse"] .diagram-svg text[fill="#333"] { fill: var(--text-primary); }
4073
-
4074
- [data-theme="terminal"] .diagram-svg text[fill="#666"],
4075
- [data-theme="noir"] .diagram-svg text[fill="#666"],
4076
- [data-theme="eclipse"] .diagram-svg text[fill="#666"] { fill: var(--text-secondary); }
4077
-
4078
- [data-theme="terminal"] .diagram-svg text[fill="#999"],
4079
- [data-theme="noir"] .diagram-svg text[fill="#999"],
4080
- [data-theme="eclipse"] .diagram-svg text[fill="#999"] { fill: var(--text-muted); }
4081
-
4082
- [data-theme="terminal"] .diagram-svg line[stroke="#eee"],
4083
- [data-theme="noir"] .diagram-svg line[stroke="#eee"],
4084
- [data-theme="eclipse"] .diagram-svg line[stroke="#eee"] { stroke: var(--border-primary); }
4085
-
4086
  /* Dark themes: research tree lines (hardcoded #666/#888) */
4087
  [data-theme="terminal"] .query-tree-container::before,
4088
  [data-theme="terminal"] .query-tree::before,
 
992
  font-weight: 500;
993
  }
994
 
995
+ .welcome-diagram {
996
+ margin: 20px auto;
997
+ max-width: 280px;
 
 
 
998
  }
999
 
1000
+ /* Disable hover popups and click behaviors on static welcome diagram */
1001
+ .welcome-diagram .tl-dot { cursor: default; }
1002
+ .welcome-diagram .tl-dot:hover { transform: none; }
1003
+ .welcome-diagram .tl-row.turn:hover .tl-label,
1004
+ .welcome-diagram .tl-row.turn:hover .tl-tool {
1005
+ background: none; border: none; box-shadow: none; padding: 0; border-radius: 0; z-index: auto;
 
1006
  }
1007
+ .welcome-diagram .tl-row.turn:hover .tl-tool-text { color: var(--text-muted); white-space: nowrap; overflow: hidden; }
1008
+ .welcome-diagram .tl-row.turn:hover .tl-label { color: var(--text-muted); white-space: nowrap; overflow: hidden; }
1009
+ .welcome-diagram .tl-row.user:hover .tl-label { color: var(--text-primary); }
1010
+ .welcome-diagram .agent-box { cursor: default; }
1011
+ .welcome-diagram .collapse-toggle { cursor: default; }
1012
 
1013
  /* Messages */
1014
  .message {
 
4033
  [data-theme="noir"] .input-container textarea { caret-color: #e0e0e0; }
4034
  [data-theme="eclipse"] .input-container textarea { caret-color: #5c9eff; }
4035
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4036
  /* Dark themes: research tree lines (hardcoded #666/#888) */
4037
  [data-theme="terminal"] .query-tree-container::before,
4038
  [data-theme="terminal"] .query-tree::before,