lvwerra HF Staff commited on
Commit
088b27a
·
verified ·
1 Parent(s): 4e43f1d

AM ligature mark; grid overview icon; sidebar polish (frame gap, play, mono panels, collapse count); settings de-box

Browse files
web/src/components/Locked.tsx CHANGED
@@ -1,5 +1,5 @@
1
  import { useState } from 'react';
2
- import { SlidersGlyph, SunGlyph, PulseGlyph, PlusGlyph, AmMark } from './icons';
3
  import Logo from './Logo';
4
 
5
  // A frozen, slightly dimmed replica of the real sidebar so the install page
@@ -40,7 +40,7 @@ function MockSidebar() {
40
  <div className="ov-fixed">
41
  <div className="row ov-row">
42
  <span className="status ov-spacer" />
43
- <span className="ov-tile"><PulseGlyph /></span>
44
  <span className="name">overview</span>
45
  </div>
46
  </div>
 
1
  import { useState } from 'react';
2
+ import { SlidersGlyph, SunGlyph, GridGlyph, PlusGlyph, AmMark } from './icons';
3
  import Logo from './Logo';
4
 
5
  // A frozen, slightly dimmed replica of the real sidebar so the install page
 
40
  <div className="ov-fixed">
41
  <div className="row ov-row">
42
  <span className="status ov-spacer" />
43
+ <span className="ov-tile"><GridGlyph /></span>
44
  <span className="name">overview</span>
45
  </div>
46
  </div>
web/src/components/Sidebar.tsx CHANGED
@@ -4,7 +4,7 @@ import { STATE_LABEL } from '../types';
4
  import Logo from './Logo';
5
  import NewSession from './NewSession';
6
  import FolderPicker from './FolderPicker';
7
- import { SlidersGlyph, SunGlyph, MoonGlyph, CloseGlyph, PencilGlyph, StopGlyph, PulseGlyph, PlusGlyph, AmMark } from './icons';
8
 
9
  type Zone = 'before' | 'after' | 'on';
10
 
@@ -149,7 +149,9 @@ export default function Sidebar({
149
  )}
150
  <span className="age">{fmtAgo(ages?.[s.id])}</span>
151
  <span className="row-actions">
152
- {s.running && <button className="mini-btn" title="Stop" onClick={(e) => { e.stopPropagation(); onStopSession(s.id); }}><StopGlyph /></button>}
 
 
153
  <button className="mini-btn" title="Delete" onClick={(e) => { e.stopPropagation(); onDeleteSession(s.id); }}><CloseGlyph /></button>
154
  </span>
155
  </div>
@@ -183,7 +185,7 @@ export default function Sidebar({
183
  ) : (
184
  <>
185
  <span className="name">{g.name}</span>
186
- <span className="count">{g.sessionIds.length}</span>
187
  <span className="row-actions">
188
  <button className="mini-btn" title="Rename" onClick={(e) => { e.stopPropagation(); startEdit(ref, g.name); }}><PencilGlyph /></button>
189
  <button className="mini-btn" title="Delete group" onClick={(e) => { e.stopPropagation(); onDeleteGroup(g.id); }}><CloseGlyph /></button>
@@ -274,7 +276,7 @@ export default function Sidebar({
274
  title="All agents: digests, states, replies"
275
  >
276
  <span className="status ov-spacer" />
277
- <span className="ov-tile"><PulseGlyph /></span>
278
  <span className="name">overview</span>
279
  {waiting > 0 && <span className="ov-wait">{waiting} waiting</span>}
280
  </div>
 
4
  import Logo from './Logo';
5
  import NewSession from './NewSession';
6
  import FolderPicker from './FolderPicker';
7
+ import { SlidersGlyph, SunGlyph, MoonGlyph, CloseGlyph, PencilGlyph, StopGlyph, PlayGlyph, GridGlyph, PlusGlyph, AmMark } from './icons';
8
 
9
  type Zone = 'before' | 'after' | 'on';
10
 
 
149
  )}
150
  <span className="age">{fmtAgo(ages?.[s.id])}</span>
151
  <span className="row-actions">
152
+ {s.running
153
+ ? <button className="mini-btn" title="Stop" onClick={(e) => { e.stopPropagation(); onStopSession(s.id); }}><StopGlyph /></button>
154
+ : <button className="mini-btn" title="Start" onClick={(e) => { e.stopPropagation(); onOpenSession(s.id, groupId); }}><PlayGlyph /></button>}
155
  <button className="mini-btn" title="Delete" onClick={(e) => { e.stopPropagation(); onDeleteSession(s.id); }}><CloseGlyph /></button>
156
  </span>
157
  </div>
 
185
  ) : (
186
  <>
187
  <span className="name">{g.name}</span>
188
+ {!open && <span className="count">{g.sessionIds.length}</span>}
189
  <span className="row-actions">
190
  <button className="mini-btn" title="Rename" onClick={(e) => { e.stopPropagation(); startEdit(ref, g.name); }}><PencilGlyph /></button>
191
  <button className="mini-btn" title="Delete group" onClick={(e) => { e.stopPropagation(); onDeleteGroup(g.id); }}><CloseGlyph /></button>
 
276
  title="All agents: digests, states, replies"
277
  >
278
  <span className="status ov-spacer" />
279
+ <span className="ov-tile"><GridGlyph /></span>
280
  <span className="name">overview</span>
281
  {waiting > 0 && <span className="ov-wait">{waiting} waiting</span>}
282
  </div>
web/src/components/icons.tsx CHANGED
@@ -67,6 +67,12 @@ export const CloseGlyph = ({ className }: { className?: string }) => (
67
  </G>
68
  );
69
 
 
 
 
 
 
 
70
  export const StopGlyph = ({ className }: { className?: string }) => (
71
  <svg className={className} viewBox="0 0 16 16" fill="currentColor">
72
  <rect x="4.4" y="4.4" width="7.2" height="7.2" rx="1.4" />
@@ -98,18 +104,27 @@ export const PulseGlyph = ({ className }: { className?: string }) => (
98
  </G>
99
  );
100
 
 
 
 
 
 
 
 
 
 
 
101
  export const PlusGlyph = ({ className }: { className?: string }) => (
102
  <G className={className}>
103
  <path d="M8 3.2v9.6M3.2 8h9.6" />
104
  </G>
105
  );
106
 
107
- // The AM monogram: rectangular A (two verticals, top bar, crossbar) and
108
- // M (three verticals joined at the top). One 4-unit stroke, 4-unit counters.
109
  export const AmMark = ({ className }: { className?: string }) => (
110
- <svg className={className} viewBox="0 0 38 24" fill="currentColor" aria-label="Agent Manager">
111
- <path fillRule="evenodd" d="M0 0H12V24H8V14H4V24H0ZM4 4H8V10H4Z" />
112
- <path d="M18 0H38V24H34V4H30V24H26V4H22V24H18Z" />
113
  </svg>
114
  );
115
 
 
67
  </G>
68
  );
69
 
70
+ export const PlayGlyph = ({ className }: { className?: string }) => (
71
+ <G className={className}>
72
+ <path d="M5.6 3.9v8.2L12.4 8z" />
73
+ </G>
74
+ );
75
+
76
  export const StopGlyph = ({ className }: { className?: string }) => (
77
  <svg className={className} viewBox="0 0 16 16" fill="currentColor">
78
  <rect x="4.4" y="4.4" width="7.2" height="7.2" rx="1.4" />
 
104
  </G>
105
  );
106
 
107
+ // Overview: four panes at a glance — what the page literally is.
108
+ export const GridGlyph = ({ className }: { className?: string }) => (
109
+ <G className={className}>
110
+ <rect x="2.2" y="2.2" width="4.8" height="4.8" rx="0.8" />
111
+ <rect x="9" y="2.2" width="4.8" height="4.8" rx="0.8" />
112
+ <rect x="2.2" y="9" width="4.8" height="4.8" rx="0.8" />
113
+ <rect x="9" y="9" width="4.8" height="4.8" rx="0.8" />
114
+ </G>
115
+ );
116
+
117
  export const PlusGlyph = ({ className }: { className?: string }) => (
118
  <G className={className}>
119
  <path d="M8 3.2v9.6M3.2 8h9.6" />
120
  </G>
121
  );
122
 
123
+ // The AM ligature: rectangular A and M sharing their middle stroke under one
124
+ // continuous roof. One 4-unit stroke, 4-unit counters.
125
  export const AmMark = ({ className }: { className?: string }) => (
126
+ <svg className={className} viewBox="0 0 28 24" fill="currentColor" aria-label="Agent Manager">
127
+ <path fillRule="evenodd" d="M0 0H28V24H24V4H20V24H16V4H12V24H8V14H4V24H0ZM4 4H8V10H4Z" />
 
128
  </svg>
129
  );
130
 
web/src/styles.css CHANGED
@@ -87,7 +87,7 @@ body {
87
  .brand h1 { font-size: 14px; margin: 0; letter-spacing: -0.01em; white-space: nowrap; }
88
  .brand .brand-actions { display: flex; gap: 4px; flex: none; }
89
  /* AM monogram — the brand mark */
90
- .am-mark { width: 21px; height: 13px; color: var(--accent); flex: none; display: block; }
91
  .icon-btn.add-btn { color: var(--accent); }
92
  .icon-btn.add-btn:hover, .icon-btn.add-btn.on { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); color: var(--accent); }
93
  .icon-btn { background: transparent; border: 1px solid var(--border); color: var(--muted); border-radius: var(--r-md); width: 32px; height: 30px; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
@@ -308,7 +308,10 @@ body {
308
  .row.group-head .name { flex: initial; font-size: 11.5px; font-weight: 400; color: var(--text); }
309
  .row.group-head:hover .name { color: var(--accent); }
310
  .row.group-head .rename { width: 130px; flex: none; }
311
- .row.group-head .row-actions { position: static; transform: none; background: var(--panel); }
 
 
 
312
  .row.group-head:hover .count { display: none; }
313
  /* per-group + on the frame line, revealed on hover */
314
  .g-add { position: absolute; top: -9px; right: 8px; background: var(--panel); border: none; color: var(--muted); padding: 0 4px; cursor: pointer; opacity: 0; transition: opacity 0.12s; z-index: 1; }
@@ -326,8 +329,12 @@ body {
326
  .status.stopped { background: transparent; border: 1.5px solid var(--muted); opacity: 0.5; }
327
 
328
  /* quick-add utilities (shell / files) pinned above the legend */
329
- .quick-add { display: flex; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--border); }
330
- .quick-add .btn-ghost { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 7px; padding: 6px 8px; font-size: 12.5px; }
 
 
 
 
331
 
332
  .legend { display: flex; flex-wrap: wrap; gap: 6px 12px; padding: 10px 16px; border-top: 1px solid var(--border); font-size: 10.5px; color: var(--muted); }
333
  .legend span { display: inline-flex; align-items: center; gap: 5px; }
@@ -486,9 +493,9 @@ a.btn-ghost { text-decoration: none; }
486
  .s-help { color: var(--muted); font-size: 12.5px; line-height: 1.5; margin: 2px 0 0; }
487
  .s-muted { color: var(--muted); }
488
  /* agents: one hairline row per CLI — dot · logo · name · version · state */
489
- /* no overflow clip: the (i) setup hint pops outside the row */
490
- .agent-rows { display: flex; flex-direction: column; background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-lg); margin-top: 8px; }
491
- .agent-row { display: flex; align-items: center; gap: 10px; padding: 9px 14px; font-size: 13px; }
492
  .agent-row + .agent-row { border-top: 1px solid var(--border); }
493
  .agent-row .spacer { flex: 1; }
494
  .ar-name { white-space: nowrap; font-weight: 500; }
@@ -513,8 +520,8 @@ a.btn-ghost { text-decoration: none; }
513
  transition: opacity 0.12s ease, transform 0.12s ease;
514
  }
515
  .tip:hover::after, .tip:focus-visible::after { opacity: 1; transform: none; }
516
- .kv { display: flex; flex-direction: column; background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-xl); overflow: hidden; margin-top: 8px; }
517
- .kv > div { display: flex; justify-content: space-between; gap: 16px; padding: 11px 16px; border-bottom: 1px solid var(--border); font-size: 13px; }
518
  .kv > div:last-child { border-bottom: none; }
519
  .kv span { color: var(--muted); }
520
  .kv b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 65%; }
 
87
  .brand h1 { font-size: 14px; margin: 0; letter-spacing: -0.01em; white-space: nowrap; }
88
  .brand .brand-actions { display: flex; gap: 4px; flex: none; }
89
  /* AM monogram — the brand mark */
90
+ .am-mark { width: 16px; height: 13.7px; color: var(--accent); flex: none; display: block; }
91
  .icon-btn.add-btn { color: var(--accent); }
92
  .icon-btn.add-btn:hover, .icon-btn.add-btn.on { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); color: var(--accent); }
93
  .icon-btn { background: transparent; border: 1px solid var(--border); color: var(--muted); border-radius: var(--r-md); width: 32px; height: 30px; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
 
308
  .row.group-head .name { flex: initial; font-size: 11.5px; font-weight: 400; color: var(--text); }
309
  .row.group-head:hover .name { color: var(--accent); }
310
  .row.group-head .rename { width: 130px; flex: none; }
311
+ /* actions must not reserve space when hidden — an invisible-but-present span
312
+ would stretch the label's frame punch-out and leave a gap in the border */
313
+ .row.group-head .row-actions { position: static; transform: none; background: var(--panel); display: none; opacity: 1; pointer-events: auto; }
314
+ .row.group-head:hover .row-actions, .row.group-head:focus-within .row-actions { display: flex; }
315
  .row.group-head:hover .count { display: none; }
316
  /* per-group + on the frame line, revealed on hover */
317
  .g-add { position: absolute; top: -9px; right: 8px; background: var(--panel); border: none; color: var(--muted); padding: 0 4px; cursor: pointer; opacity: 0; transition: opacity 0.12s; z-index: 1; }
 
329
  .status.stopped { background: transparent; border: 1.5px solid var(--muted); opacity: 0.5; }
330
 
331
  /* quick-add utilities (shell / files) pinned above the legend */
332
+ .quick-add { display: flex; gap: 6px; padding: 10px 10px; border-top: 1px solid var(--border); }
333
+ .quick-add .btn-ghost { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 7px; padding: 5.5px 8px; font-family: var(--font-mono); font-size: 12px; font-weight: 500; border-radius: var(--r-sm); }
334
+ /* the create panel speaks the same dense mono voice as the rows */
335
+ .controls .btn-primary, .controls .btn-ghost { font-family: var(--font-mono); font-size: 12px; font-weight: 500; padding: 6px 10px; border-radius: var(--r-sm); }
336
+ .controls .widget input, .controls .widget select, .controls .agent-pick, .controls .fp-current { font-size: 12.5px; }
337
+ .controls .seg button { font-family: var(--font-mono); }
338
 
339
  .legend { display: flex; flex-wrap: wrap; gap: 6px 12px; padding: 10px 16px; border-top: 1px solid var(--border); font-size: 10.5px; color: var(--muted); }
340
  .legend span { display: inline-flex; align-items: center; gap: 5px; }
 
493
  .s-help { color: var(--muted); font-size: 12.5px; line-height: 1.5; margin: 2px 0 0; }
494
  .s-muted { color: var(--muted); }
495
  /* agents: one hairline row per CLI — dot · logo · name · version · state */
496
+ /* plain hairline rows no box (sidebar voice: boundaries only where they mean something) */
497
+ .agent-rows { display: flex; flex-direction: column; margin-top: 4px; }
498
+ .agent-row { display: flex; align-items: center; gap: 10px; padding: 9px 2px; font-size: 13px; }
499
  .agent-row + .agent-row { border-top: 1px solid var(--border); }
500
  .agent-row .spacer { flex: 1; }
501
  .ar-name { white-space: nowrap; font-weight: 500; }
 
520
  transition: opacity 0.12s ease, transform 0.12s ease;
521
  }
522
  .tip:hover::after, .tip:focus-visible::after { opacity: 1; transform: none; }
523
+ .kv { display: flex; flex-direction: column; margin-top: 4px; }
524
+ .kv > div { display: flex; justify-content: space-between; gap: 16px; padding: 10px 2px; border-bottom: 1px solid var(--border); font-size: 13px; }
525
  .kv > div:last-child { border-bottom: none; }
526
  .kv span { color: var(--muted); }
527
  .kv b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 65%; }