@workerdeck/ui 0.20.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +3 -2
  2. package/build/{SessionPanel-CnU_IJ3-.d.mts → SessionPanel-13l25ubU.d.mts} +55 -7
  3. package/build/{SessionPanel-CHktI2CF.mjs → SessionPanel-DgwjH4Ve.mjs} +642 -231
  4. package/build/SessionPanel-DgwjH4Ve.mjs.map +1 -0
  5. package/build/index.d.mts +309 -53
  6. package/build/index.mjs +534 -397
  7. package/build/index.mjs.map +1 -1
  8. package/build/scoped.css +3547 -0
  9. package/build/workspace.d.mts +10 -1
  10. package/build/workspace.mjs +4 -2
  11. package/build/workspace.mjs.map +1 -1
  12. package/package.json +15 -7
  13. package/src/components/agent/Composer.tsx +10 -10
  14. package/src/components/agent/ContextDialog.tsx +3 -2
  15. package/src/components/agent/Conversation.tsx +1 -1
  16. package/src/components/agent/McpDialog.tsx +3 -1
  17. package/src/components/agent/Scrubber.tsx +248 -0
  18. package/src/components/agent/SessionBrowser.tsx +113 -293
  19. package/src/components/agent/SessionItem.tsx +538 -0
  20. package/src/components/agent/SessionList.tsx +3 -1
  21. package/src/components/agent/SessionPanel.tsx +112 -21
  22. package/src/components/agent/SessionStatusIcon.tsx +43 -0
  23. package/src/components/agent/SessionSteps.tsx +118 -61
  24. package/src/components/agent/SessionWorkspace.tsx +11 -0
  25. package/src/components/agent/SkillsDialog.tsx +3 -2
  26. package/src/components/agent/StatusBar.tsx +1 -1
  27. package/src/components/agent/Transcript.tsx +147 -73
  28. package/src/components/agent/UsageDialog.tsx +3 -1
  29. package/src/components/agent/scrubber-marks.ts +277 -0
  30. package/src/components/terminal/PermissionPrompt.tsx +3 -0
  31. package/src/components/terminal/QuestionPrompt.tsx +3 -0
  32. package/src/components/terminal/StatusLine.tsx +3 -1
  33. package/src/components/ui/AlertDialog.tsx +23 -20
  34. package/src/components/ui/Dialog.tsx +26 -23
  35. package/src/components/ui/Menu.tsx +20 -17
  36. package/src/components/ui/PortalScope.tsx +27 -0
  37. package/src/components/ui/Select.tsx +19 -16
  38. package/src/components/ui/Tooltip.tsx +13 -10
  39. package/src/index.ts +5 -1
  40. package/src/styles/scoped.entry.css +16 -0
  41. package/src/styles/terminal.css +1 -1
  42. package/src/styles/theme.css +223 -8
  43. package/build/SessionPanel-CHktI2CF.mjs.map +0 -1
@@ -30,14 +30,48 @@
30
30
  --bg-code: #f5f5f5;
31
31
  --bg-elevated: #ffffffcc;
32
32
 
33
- /* A list row's hover and selected fills. **Alpha, not a flat colour**, because
34
- a row sits on whatever its host paints — `bg-sidebar` in the dashboard,
35
- `--vscode-sideBar-background` in the extension and a flat value tuned for
36
- one of those is invisible on the others. `--bg-surface-hover` was exactly
37
- that mistake: on the dark sidebar (#131313) it lands on #141414, one step
38
- of 255 away, so the hover state did not exist. */
39
- --row-hover: rgb(0 0 0 / 0.05);
33
+ /* A list row's fills.
34
+
35
+ `--row-hover` is the **flat** value the design specifies (VS Code's
36
+ `list.hoverBackground`), not the alpha it used to be. The alpha existed to
37
+ survive an unknown host surface, and it bought that at the cost of a hover
38
+ that read differently on every one of them; the design draws one hover, so
39
+ this is one colour. The hazard the alpha was guarding against is real and
40
+ has a name — `--bg-surface-hover` on the dark sidebar landed one step of
41
+ 255 from the sidebar itself, so the state did not exist — and the guard
42
+ against it now is that both flat values are picked against the sidebar
43
+ fills we actually ship (`--sidebar`), and that the extension repoints all
44
+ three at `--vscode-list-*` rather than inheriting them.
45
+
46
+ `--row-active` stays alpha on purpose: it is the *other three* sidebars'
47
+ selected fill, and those still wear the accent-bar shape `rowShapeClass`
48
+ draws, where the fill is a tint under a bar and not the selection itself.
49
+
50
+ `--row-selected` is new and is the session list's own: a filled card, the
51
+ shape the design gives selection there. Light is a tint carrying dark text;
52
+ dark is VS Code's `list.activeSelectionBackground` carrying light text.
53
+
54
+ `--row-selected-weak` is the **secondary** selection — "this card holds what
55
+ you are looking at, but the thing you are looking at is one row inside it".
56
+ It exists because a session card and its sub-agents are two selections at
57
+ two grains, and the blue can only mean one of them: when a sub-agent is
58
+ open, the blue belongs to that step and the card drops to this. It is VS
59
+ Code's `list.inactiveSelectionBackground`, which is the same idea one
60
+ surface over — selected, but not the thing with focus. Distinct from
61
+ `--row-hover` on purpose: a card that answered the pointer and a card
62
+ holding the open agent are different claims, and a list that painted them
63
+ the same colour would be lying about one of them. */
64
+ --row-hover: #e8e8e8;
40
65
  --row-active: rgb(0 0 0 / 0.08);
66
+ --row-selected: #cfe4f7;
67
+ --row-selected-weak: #e4e6f1;
68
+
69
+ /* A count badge that is NOT an alert. The unread badge wears `--accent`
70
+ because unread is a call to look; a plain count (how many sub-agents, how
71
+ many tasks) wears this, because a blue pill that means nothing urgent
72
+ spends the accent on noise. VS Code's `badge.background`. */
73
+ --badge: #c4c4c4;
74
+ --badge-fg: #333333;
41
75
 
42
76
  /* ---------- Borders ---------- */
43
77
  --border: #ebebeb;
@@ -117,6 +151,10 @@
117
151
  --shine: #dcdcdc;
118
152
  --frame-shadow: var(--shadow-xs);
119
153
 
154
+ /* The overview rail's bookmark magenta — the app palette has no magenta,
155
+ and every other colour on the rail is already spoken for. */
156
+ --wd-scrub-bookmark: #8b3a8b;
157
+
120
158
  /* ---------- aliases (bridge for the @theme utilities) ---------- */
121
159
  --surface: var(--bg-surface);
122
160
  --sidebar: #f4f4f4;
@@ -138,8 +176,17 @@
138
176
  --bg-code: #141414;
139
177
  --bg-elevated: #0a0a0acc;
140
178
 
141
- --row-hover: rgb(255 255 255 / 0.06);
179
+ /* See the light block for the whole argument. These two are VS Code's own
180
+ `list.hoverBackground` / `list.activeSelectionBackground`, which is what the
181
+ design was drawn against. */
182
+ --row-hover: #2a2d2e;
142
183
  --row-active: rgb(255 255 255 / 0.10);
184
+ --row-selected: #04395e;
185
+ --row-selected-weak: #37373d;
186
+
187
+ /* See the light block. */
188
+ --badge: #616161;
189
+ --badge-fg: #cccccc;
143
190
 
144
191
  /* ---------- Borders ---------- */
145
192
  --border: #1f1f1f;
@@ -191,6 +238,9 @@
191
238
  0 4px 24px rgba(0, 0, 0, 0.55),
192
239
  0 2px 6px rgba(0, 0, 0, 0.45);
193
240
 
241
+ /* See the light block — lifted for the dark ground. */
242
+ --wd-scrub-bookmark: #c586c0;
243
+
194
244
  /* ---------- aliases ---------- */
195
245
  --surface: var(--bg-surface);
196
246
  --sidebar: #131313;
@@ -224,6 +274,12 @@
224
274
  --motion-base: 150ms;
225
275
  --motion-slow: 220ms;
226
276
 
277
+ /* ---------- Geometry (embedder-overridable layout knobs) ---------- */
278
+ --wd-status-bar-height: 38px;
279
+ --wd-composer-padding: 12px;
280
+ --wd-transcript-row-gap: 0px;
281
+ --wd-transcript-max-width: 48rem;
282
+
227
283
  /* Stock-name bridge → raw custom properties (shadcn idiom compatibility). */
228
284
  --primary: var(--accent);
229
285
  --primary-foreground: var(--accent-fg);
@@ -291,6 +347,10 @@
291
347
  --color-surface-hover: var(--bg-surface-hover);
292
348
  --color-row-hover: var(--row-hover);
293
349
  --color-row-active: var(--row-active);
350
+ --color-row-selected: var(--row-selected);
351
+ --color-row-selected-weak: var(--row-selected-weak);
352
+ --color-badge: var(--badge);
353
+ --color-badge-fg: var(--badge-fg);
294
354
  /* Named code-bg (not code) so it can't shadow the --text-code font-size token:
295
355
  with a --color-code defined, `text-code` would resolve to the color namespace
296
356
  and paint text in the code *background* color — invisible in both themes. */
@@ -358,6 +418,14 @@
358
418
  --text-label: 0.75rem;
359
419
  --text-label--line-height: 1rem;
360
420
  --text-label--letter-spacing: 0.02em;
421
+ /* 11px. The step rows under a session card, and nothing else yet — a size
422
+ below `label` exists so a list *inside* a row can be visibly subordinate to
423
+ it without dropping to a weight nobody can read. Tracking goes NEGATIVE
424
+ here where `label` goes positive: `label` is a small-caps-ish UI word that
425
+ wants air, this is a sentence-shaped run that wants to hold together. */
426
+ --text-micro: 0.6875rem;
427
+ --text-micro--line-height: 0.875rem;
428
+ --text-micro--letter-spacing: -0.005em;
361
429
  --text-code: 0.84375rem;
362
430
  --text-code--line-height: 1.375rem;
363
431
 
@@ -556,3 +624,150 @@
556
624
  transition: none !important;
557
625
  }
558
626
  }
627
+
628
+ /* ── Sticky prompt (cards variant) ─────────────────────────────────────────
629
+ *
630
+ * The same lane/head/sentinel mechanism as the terminal theme's pinned prompt
631
+ * (terminal.css scopes its rules under `[data-terminal]`; these key on the
632
+ * lane's own `data-sticky-lane='cards'` value) — but the head's CONTENT is
633
+ * different in kind, and that is the whole design. The terminal head is the
634
+ * row rendered again, clipped to one line — exact, because that theme is a
635
+ * monospace grid. A proportional message card clipped by height is a sliced
636
+ * bubble, so the cards head never renders the Message component at all:
637
+ * `StickyPromptLane` (Transcript.tsx) hands it the prompt as one run of plain
638
+ * text, and these rules only draw a bar. Nothing to flatten, nothing to
639
+ * un-style, nothing to `!important` over.
640
+ *
641
+ * Alignment is by construction, not restatement: the lane sits inside
642
+ * ConversationContent's centred, padded column (`max-w` + `mx-auto` + `px-4`)
643
+ * and spans it edge to edge, so the bar's text starts on the same left edge
644
+ * as the response paragraphs and the ellipsis lands on the column's right
645
+ * edge — no max-width or inline padding repeated here. The bar carries no
646
+ * gap class either (the measured row keeps it): it is not an overlay of the
647
+ * row's first line, so it has no in-flow y to match, and the 1st prompt (no
648
+ * gap) and every later one (pt-4/pt-2) share these rules unchanged. */
649
+ [data-slot='transcript-rows'] > [data-sticky-lane='cards'] {
650
+ z-index: 3;
651
+ pointer-events: none;
652
+ }
653
+
654
+ /* The head's own strip: the full lane, out of flow — see terminal.css for why
655
+ sticky confinement wants the border box, not a cancelled margin box. */
656
+ [data-sticky-lane='cards'] > [data-sticky-headlane] {
657
+ position: absolute;
658
+ inset: 0;
659
+ pointer-events: none;
660
+ }
661
+
662
+ /* The bar: ~28px, one line centred by its own line-height, truncated at the
663
+ column's right edge, on a frosted ground so the rows passing beneath read
664
+ as beneath. Hidden until actually stuck (`data-stuck`, set by the lane's
665
+ sentinel observer): unstuck it sits at the lane's top, over the real
666
+ bubble. */
667
+ [data-sticky-lane='cards'] > [data-sticky-headlane] > [data-sticky-head] {
668
+ position: sticky;
669
+ top: 0;
670
+ height: 1.75rem;
671
+ line-height: 1.75rem;
672
+ overflow: hidden;
673
+ white-space: nowrap;
674
+ text-overflow: ellipsis;
675
+ font-size: var(--text-body-sm);
676
+ color: var(--fg-2);
677
+ background: color-mix(in srgb, var(--bg) 88%, transparent);
678
+ backdrop-filter: blur(12px);
679
+ -webkit-backdrop-filter: blur(12px);
680
+ border-bottom: 1px solid var(--border);
681
+ user-select: none;
682
+ visibility: hidden;
683
+ }
684
+
685
+ [data-sticky-lane='cards'] > [data-sticky-headlane] > [data-sticky-head][data-stuck] {
686
+ visibility: visible;
687
+ }
688
+
689
+ /* ── Overview scrubber (cards variant) ──────────────────────────────────────
690
+ *
691
+ * The proportional rail (`components/agent/Scrubber.tsx`): same geometry as the
692
+ * terminal rail — 12px, two 6px lanes plus full width — and the same palette
693
+ * mapped onto the app tokens. It is an annotation rail, never a scrollbar: the
694
+ * container takes no pointer events, so the native scrollbar keeps working
695
+ * straight through the paint. */
696
+ .wd-scrubber {
697
+ position: absolute;
698
+ top: 0;
699
+ right: 0;
700
+ bottom: 0;
701
+ width: 12px;
702
+ z-index: 10;
703
+ pointer-events: none;
704
+ }
705
+ .wd-scrubber .wd-scrub-mark {
706
+ position: absolute;
707
+ min-height: 2px;
708
+ }
709
+ .wd-scrubber[data-interactive] .wd-scrub-mark {
710
+ pointer-events: auto;
711
+ cursor: pointer;
712
+ }
713
+ .wd-scrubber[data-interactive] .wd-scrub-mark:hover {
714
+ outline: 1px solid color-mix(in srgb, var(--fg-1) 40%, transparent);
715
+ }
716
+ .wd-scrubber .wd-scrub-mark[data-lane='l'] { left: 0; width: 6px; }
717
+ .wd-scrubber .wd-scrub-mark[data-lane='r'] { left: 6px; width: 6px; }
718
+ .wd-scrubber .wd-scrub-mark[data-lane='f'] { left: 0; width: 12px; }
719
+ .wd-scrubber .wd-scrub-mark[data-kind='user'] { background: var(--accent); }
720
+ .wd-scrubber .wd-scrub-mark[data-kind='subagent'] { background: var(--success); }
721
+ .wd-scrubber .wd-scrub-mark[data-kind='turn'] { background: var(--fg-3); }
722
+ .wd-scrubber .wd-scrub-mark[data-kind='turnFailed'] { background: var(--danger); }
723
+ .wd-scrubber .wd-scrub-mark[data-kind='error'] { background: var(--danger); }
724
+ .wd-scrubber .wd-scrub-mark[data-kind='toolFailed'] {
725
+ background: color-mix(in srgb, var(--danger) 55%, transparent);
726
+ }
727
+ .wd-scrubber .wd-scrub-mark[data-kind='bookmark'] { background: var(--wd-scrub-bookmark); }
728
+ .wd-scrubber .wd-scrub-mark[data-kind='approval'] {
729
+ background: var(--warning);
730
+ animation: wd-scrub-pulse 1.2s infinite;
731
+ }
732
+ .wd-scrubber .wd-scrub-mark[data-kind='recap'] {
733
+ background: repeating-linear-gradient(to right, var(--fg-4) 0 3px, transparent 3px 6px)
734
+ left center / 100% 1px no-repeat;
735
+ }
736
+ @keyframes wd-scrub-pulse {
737
+ 50% { opacity: 0.3; }
738
+ }
739
+ @media (prefers-reduced-motion: reduce) {
740
+ .wd-scrubber .wd-scrub-mark[data-kind='approval'] {
741
+ animation: none;
742
+ }
743
+ }
744
+
745
+ .wd-scrubber .wd-scrub-peek {
746
+ position: absolute;
747
+ right: calc(100% + 6px);
748
+ width: 320px;
749
+ max-width: 60vw;
750
+ display: flex;
751
+ flex-direction: column;
752
+ gap: 2px;
753
+ padding: 8px 10px;
754
+ border: 1px solid var(--border-strong);
755
+ border-radius: var(--radius-md, 6px);
756
+ background: var(--bg);
757
+ box-shadow: var(--shadow-md);
758
+ font-family: var(--cw-font-sans);
759
+ font-size: 12px;
760
+ line-height: 1.45;
761
+ color: var(--fg-1);
762
+ pointer-events: none;
763
+ z-index: 11;
764
+ }
765
+ .wd-scrubber .wd-scrub-peek [data-tone='muted'] { color: var(--fg-3); }
766
+ .wd-scrubber .wd-scrub-peek [data-tone='danger'] { color: var(--danger); }
767
+ .wd-scrubber .wd-scrub-ex {
768
+ display: -webkit-box;
769
+ -webkit-line-clamp: 4;
770
+ -webkit-box-orient: vertical;
771
+ overflow: hidden;
772
+ overflow-wrap: anywhere;
773
+ }