@bivy/bivy 0.17.1-staging.1 → 0.17.1-staging.10
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.
- package/dist/apps/styles.css +125 -94
- package/dist/apps/tokens.css +13 -12
- package/dist/session/event-log.js +8 -0
- package/package.json +1 -1
package/dist/apps/styles.css
CHANGED
|
@@ -169,6 +169,8 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
169
169
|
.badge[data-variant="soft"][data-tone="ok"] { background: color-mix(in srgb, var(--ok) 16%, var(--surface)); color: var(--ok); }
|
|
170
170
|
.badge[data-variant="soft"][data-tone="warn"] { background: var(--warn-soft); color: var(--warn); }
|
|
171
171
|
.badge[data-variant="soft"][data-tone="danger"] { background: var(--danger-soft); color: var(--danger); }
|
|
172
|
+
.badge[data-variant="soft"][data-tone="merged"] { background: color-mix(in srgb, var(--merged) 16%, var(--surface)); color: var(--merged); }
|
|
173
|
+
.badge[data-variant="soft"]:not([data-tone]) { background: var(--surface-3); color: var(--muted); }
|
|
172
174
|
.badge[data-variant="solid"] { border-color: transparent; color: var(--accent-contrast); }
|
|
173
175
|
.badge[data-variant="solid"][data-tone="accent"] { background: var(--accent); }
|
|
174
176
|
.badge[data-variant="solid"][data-tone="ok"] { background: var(--ok); }
|
|
@@ -211,29 +213,39 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
211
213
|
}
|
|
212
214
|
.sidebar-head {
|
|
213
215
|
display: flex; align-items: center; justify-content: space-between;
|
|
214
|
-
|
|
216
|
+
min-height: 56px; padding: var(--space-2) var(--space-2) var(--space-1) var(--space-4);
|
|
215
217
|
/* As a fixed drawer on mobile the sidebar starts at the very top of the
|
|
216
218
|
screen, so its header must clear the status bar / notch the same way the
|
|
217
|
-
main .topbar does — otherwise
|
|
218
|
-
padding-top: max(
|
|
219
|
+
main .topbar does — otherwise the wordmark sits under the clock. */
|
|
220
|
+
padding-top: max(var(--space-2), env(safe-area-inset-top));
|
|
219
221
|
}
|
|
220
|
-
.sidebar-head-actions { display: flex; align-items: center; gap:
|
|
221
|
-
.brand { font-family: var(--font-serif); font-weight: 500; font-size:
|
|
222
|
+
.sidebar-head-actions { display: flex; align-items: center; gap: var(--space-2); }
|
|
223
|
+
.brand { font-family: var(--font-serif); font-weight: 500; font-size: var(--text-xl); letter-spacing: 0; }
|
|
222
224
|
/* Primary destinations sit above the session stream. Keeping Automations here
|
|
223
225
|
makes it discoverable without competing with the quieter Settings footer. */
|
|
224
|
-
.sidebar-nav {
|
|
226
|
+
.sidebar-nav { display: flex; flex-direction: column; gap: 2px; padding: 0 0 var(--space-3); }
|
|
225
227
|
.sidebar-nav-item {
|
|
226
|
-
display: flex; align-items: center; gap:
|
|
227
|
-
padding:
|
|
228
|
-
background: transparent; color: var(--ink); font: inherit; font-size: var(--text-
|
|
228
|
+
display: flex; align-items: center; gap: var(--space-3); width: 100%; min-height: 40px;
|
|
229
|
+
padding: var(--space-2); border: 0; border-radius: var(--radius-md);
|
|
230
|
+
background: transparent; color: var(--ink); font: inherit; font-size: var(--text-md); font-weight: var(--weight-normal);
|
|
229
231
|
text-align: left; cursor: pointer; transition: color var(--dur) var(--ease-standard), background var(--dur) var(--ease-standard);
|
|
230
232
|
}
|
|
231
|
-
.sidebar-nav-item svg { color: var(--
|
|
232
|
-
.sidebar-nav-item:hover { background: var(--surface-2); }
|
|
233
|
-
.sidebar-nav-item
|
|
234
|
-
.sidebar-nav-item.active
|
|
235
|
-
|
|
236
|
-
|
|
233
|
+
.sidebar-nav-item svg { color: var(--ink); flex: none; }
|
|
234
|
+
.sidebar-nav-item:hover:not(:disabled) { background: var(--surface-2); }
|
|
235
|
+
.sidebar-nav-item:disabled { opacity: 0.45; cursor: default; }
|
|
236
|
+
.sidebar-nav-item.active { background: var(--surface-2); }
|
|
237
|
+
/* Foot: the single primary action (New session) + the Settings gear. No rule
|
|
238
|
+
above it — the list simply scrolls underneath. */
|
|
239
|
+
.sidebar-foot {
|
|
240
|
+
margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
|
|
241
|
+
padding: var(--space-3) var(--space-3) max(var(--space-3), env(safe-area-inset-bottom));
|
|
242
|
+
background: var(--surface);
|
|
243
|
+
}
|
|
244
|
+
.btn.new-session-btn {
|
|
245
|
+
display: inline-flex; align-items: center; gap: var(--space-2); min-height: 44px;
|
|
246
|
+
padding: 0 var(--space-5) 0 var(--space-4); border-radius: var(--radius-full);
|
|
247
|
+
font-size: var(--text-md); font-weight: var(--weight-semibold);
|
|
248
|
+
}
|
|
237
249
|
/* Red dot on the mobile ☰ burger when something needs the user that they
|
|
238
250
|
haven't seen (an agent blocked on approval/question, an unseen finished run,
|
|
239
251
|
a provider needing auth). Replaces the old separate inbox surface — the
|
|
@@ -281,15 +293,18 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
281
293
|
.session-list { display: flex; flex-direction: column; min-height: 0; flex: 1; overflow-y: auto; overflow-x: hidden; padding: 8px; }
|
|
282
294
|
.session-list-heading { display: flex; align-items: baseline; justify-content: space-between; padding: var(--space-3) var(--space-2) var(--space-2); color: var(--ink); font-size: var(--text-md); font-weight: var(--weight-semibold); }
|
|
283
295
|
.session-list-count { color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-normal); font-variant-numeric: tabular-nums; }
|
|
284
|
-
|
|
285
|
-
.session-
|
|
296
|
+
/* Search (the canonical .field, with a leading glyph) + a quiet filter icon. */
|
|
297
|
+
.session-list-tools { display: flex; align-items: center; gap: var(--space-1); margin-bottom: var(--space-2); }
|
|
298
|
+
.session-search-wrap { position: relative; flex: 1; min-width: 0; display: flex; color: var(--muted); }
|
|
299
|
+
.session-search-wrap > svg { position: absolute; left: var(--space-3); top: 50%; transform: translateY(-50%); pointer-events: none; }
|
|
300
|
+
.session-search { flex: 1; min-width: 0; padding-left: calc(var(--space-3) + 17px + var(--space-2)); }
|
|
286
301
|
.session-filter { position: relative; flex: none; }
|
|
287
302
|
.session-filter-btn {
|
|
288
303
|
position: relative; display: inline-flex; align-items: center; justify-content: center;
|
|
289
|
-
width:
|
|
290
|
-
background:
|
|
304
|
+
width: 32px; height: 32px; border: 0; border-radius: var(--radius-full);
|
|
305
|
+
background: transparent; color: var(--muted); font-size: 20px; line-height: 1;
|
|
291
306
|
}
|
|
292
|
-
.session-filter-btn:hover, .session-filter-btn.active, .session-filter-btn[aria-expanded="true"] { color: var(--ink);
|
|
307
|
+
.session-filter-btn:hover, .session-filter-btn.active, .session-filter-btn[aria-expanded="true"] { color: var(--ink); background: var(--surface-3); }
|
|
293
308
|
.session-filter-count { position: absolute; right: -5px; top: -5px; min-width: 17px; height: 17px; padding: 0 var(--space-1); }
|
|
294
309
|
.session-filter-menu {
|
|
295
310
|
position: absolute; right: 0; top: calc(100% + 6px); width: min(280px, calc(100vw - 24px)); z-index: var(--z-dropdown);
|
|
@@ -305,36 +320,30 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
305
320
|
.session-filter-clear { flex: none; border: 0; background: transparent; color: var(--accent); padding: 2px 0; font-size: 12px; }
|
|
306
321
|
.session-list ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
307
322
|
.session-group-label {
|
|
308
|
-
padding:
|
|
309
|
-
font-
|
|
323
|
+
padding: var(--space-4) var(--space-2) var(--space-1); color: var(--muted);
|
|
324
|
+
font-size: var(--text-xs); line-height: var(--lh-xs); font-weight: var(--weight-semibold);
|
|
310
325
|
}
|
|
311
|
-
.session-group-label:first-child { padding-top:
|
|
326
|
+
.session-group-label:first-child { padding-top: var(--space-2); }
|
|
312
327
|
.session-item {
|
|
313
|
-
position: relative; display: flex; align-items: center; gap:
|
|
314
|
-
padding:
|
|
328
|
+
position: relative; display: flex; align-items: center; gap: var(--space-2); width: 100%; text-align: left;
|
|
329
|
+
padding: var(--space-2); border: 0; border-radius: var(--radius-md); background: transparent; color: var(--ink);
|
|
315
330
|
}
|
|
316
331
|
.session-item:hover { background: var(--surface-2); }
|
|
317
|
-
.session-item.active, .session-item[aria-current="page"] {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
.session-item.active::before, .session-item[aria-current="page"]::before {
|
|
321
|
-
content: ""; position: absolute; inset: 0 auto 0 0; width: 2px;
|
|
322
|
-
background: var(--accent);
|
|
323
|
-
}
|
|
324
|
-
/* Column wrapper for the two-line row (title row + meta row) so the dot can
|
|
325
|
-
stay a single flex sibling, vertically centered across both lines. */
|
|
332
|
+
.session-item.active, .session-item[aria-current="page"] { background: var(--surface-2); }
|
|
333
|
+
/* Two single-line rows: title (+ status dot, PR mark, age) over a quiet meta
|
|
334
|
+
line. A dot appears only for states that want attention (see RowMark). */
|
|
326
335
|
.session-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
327
|
-
.session-title-row { display: flex; align-items:
|
|
336
|
+
.session-title-row { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
|
|
337
|
+
.row-status { flex: none; display: inline-flex; }
|
|
328
338
|
.session-name {
|
|
329
|
-
flex: 1; min-width: 0; overflow: hidden;
|
|
330
|
-
|
|
339
|
+
flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
340
|
+
font-size: var(--text-base); line-height: var(--lh-base); font-weight: var(--weight-medium);
|
|
331
341
|
}
|
|
332
342
|
/* Relative age, pinned to the row's trailing edge; flex:none so it never
|
|
333
343
|
shrinks or forces the row to scroll sideways. */
|
|
334
|
-
.session-age { flex: none; font-size:
|
|
335
|
-
/* Agent /
|
|
336
|
-
|
|
337
|
-
.session-meta { font-size: 12px; line-height: 1.25; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
344
|
+
.session-age { flex: none; font-size: var(--text-xs); color: var(--muted); font-variant-numeric: tabular-nums; line-height: var(--lh-xs); }
|
|
345
|
+
/* Agent / repo / branch descriptor line, below the title. */
|
|
346
|
+
.session-meta { font-size: var(--text-xs); line-height: var(--lh-xs); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
338
347
|
@keyframes dot-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }
|
|
339
348
|
.session-row { position: relative; display: flex; align-items: center; }
|
|
340
349
|
.session-row .session-item { flex: 1; min-width: 0; }
|
|
@@ -396,6 +405,12 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
396
405
|
the composer no longer moves it. margin-bottom stays auto so a tall pane keeps
|
|
397
406
|
it in the upper-middle rather than pinned hard to the top. */
|
|
398
407
|
.chat-empty { margin: calc(var(--app-h, 100dvh) * 0.22) auto auto; color: var(--muted); max-width: 320px; padding: 0 20px; text-align: center; }
|
|
408
|
+
.chat-greeting { margin: auto; padding: var(--space-6) var(--space-4); text-align: center; }
|
|
409
|
+
.chat-greeting h2 {
|
|
410
|
+
margin: 0; font-family: var(--font-serif); font-weight: var(--weight-normal);
|
|
411
|
+
font-size: var(--text-3xl); line-height: var(--lh-3xl); color: var(--ink); text-wrap: balance;
|
|
412
|
+
}
|
|
413
|
+
@media (max-width: 720px) { .chat-greeting h2 { font-size: var(--text-2xl); line-height: var(--lh-2xl); } }
|
|
399
414
|
.chat-empty-title { margin: 0 0 6px; font-size: 16px; font-weight: 600; color: var(--ink); }
|
|
400
415
|
.chat-empty-sub { margin: 0; font-size: 13px; line-height: 1.5; }
|
|
401
416
|
.chat-empty-sub b { color: var(--ink); font-weight: 600; }
|
|
@@ -571,19 +586,27 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
571
586
|
discoverability pattern as .row-menu-btn — and a touch-friendly baseline
|
|
572
587
|
opacity on devices with no hover. */
|
|
573
588
|
.assistant-row { align-self: stretch; width: 100%; max-width: 680px; }
|
|
574
|
-
.msg-actions { display: flex; align-items: center; gap: 2px; margin-top:
|
|
589
|
+
.msg-actions { display: flex; align-items: center; gap: 2px; margin-top: var(--space-1); margin-left: -6px; }
|
|
575
590
|
.msg-copy-btn, .msg-speak-btn {
|
|
576
591
|
border: 0; background: transparent; color: var(--muted);
|
|
577
592
|
display: inline-flex; align-items: center; justify-content: center;
|
|
578
|
-
width:
|
|
579
|
-
cursor: pointer; transition: opacity
|
|
593
|
+
width: 32px; height: 32px; padding: 0; border-radius: var(--radius-sm);
|
|
594
|
+
cursor: pointer; transition: opacity var(--dur-fast) ease, color var(--dur-fast) ease;
|
|
580
595
|
}
|
|
581
|
-
.assistant-row:hover .msg-copy-btn, .assistant-row:hover .msg-speak-btn,
|
|
582
|
-
.msg-copy-btn:focus-visible, .msg-speak-btn:focus-visible { opacity: 1; }
|
|
583
596
|
.msg-copy-btn:hover, .msg-speak-btn:hover { background: var(--surface-2); color: var(--ink); }
|
|
584
|
-
.msg-copy-btn.copied { color: var(--ok);
|
|
585
|
-
.msg-speak-btn.speaking { color: var(--accent);
|
|
586
|
-
|
|
597
|
+
.msg-copy-btn.copied { color: var(--ok); }
|
|
598
|
+
.msg-speak-btn.speaking { color: var(--accent); }
|
|
599
|
+
/* Actions belong to the answer: only a turn's final reply carries them. An
|
|
600
|
+
interim reply ("Let me look at…") drops them on touch, and on a wide pointer
|
|
601
|
+
screen keeps them one hover (or Tab) away in the column's right gutter. */
|
|
602
|
+
.turn-response-body > .assistant-row:has(~ .assistant-row) > .msg-actions { display: none; }
|
|
603
|
+
@media (hover: hover) and (min-width: 1100px) {
|
|
604
|
+
.turn-response-body > .assistant-row:has(~ .assistant-row) { position: relative; }
|
|
605
|
+
.turn-response-body > .assistant-row:has(~ .assistant-row) > .msg-actions {
|
|
606
|
+
display: flex; position: absolute; top: 0; left: 100%; margin: 0 0 0 var(--space-2); opacity: 0;
|
|
607
|
+
}
|
|
608
|
+
.turn-response-body > .assistant-row:has(~ .assistant-row):is(:hover, :focus-within) > .msg-actions { opacity: 1; }
|
|
609
|
+
}
|
|
587
610
|
|
|
588
611
|
/* ---- Tool activity (grouped summary line -> bottom sheet detail + diff) ---- */
|
|
589
612
|
.tool-group { align-self: stretch; width: 100%; max-width: 680px; }
|
|
@@ -711,14 +734,13 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
711
734
|
.github-pill .gh-icon { width: 14px; height: 14px; }
|
|
712
735
|
.github-pill .gh-text { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
713
736
|
|
|
714
|
-
/* Compact PR
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
.session-pr
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
.session-pr-text { white-space: nowrap; position: relative; top: 0.5px; }
|
|
737
|
+
/* Compact PR mark (open/merged/closed): a soft tinted chip whose glyph shape
|
|
738
|
+
names the state, plus a count when there's more than one. Non-interactive —
|
|
739
|
+
it sits inside a row/pill <button>. */
|
|
740
|
+
.session-pr { flex: none; gap: 3px; padding: 0 var(--space-1); height: 18px; font-size: 11px; line-height: 1; font-variant-numeric: tabular-nums; }
|
|
741
|
+
.session-pr:not(:has(.session-pr-text)) { width: 18px; padding: 0; justify-content: center; }
|
|
742
|
+
.session-pr .pr-glyph { width: 12px; height: 12px; flex: none; }
|
|
743
|
+
.session-pr-text { white-space: nowrap; font-weight: var(--weight-semibold); }
|
|
722
744
|
|
|
723
745
|
/* ---- Source marks & run pill (see sessionSource.ts / SourceMark.tsx) ----
|
|
724
746
|
Source identity is carried by the glyph alone: every mark renders a quiet
|
|
@@ -746,6 +768,9 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
746
768
|
.source-mark svg { width: 17px; height: 17px; display: block; }
|
|
747
769
|
.source-mark.sm { width: 22px; height: 22px; border-radius: var(--radius-sm); }
|
|
748
770
|
.source-mark.sm svg { width: 13px; height: 13px; }
|
|
771
|
+
/* Inline in a row's meta line, sized to the text. */
|
|
772
|
+
.source-mark.xs { width: 16px; height: 16px; border-radius: calc(var(--radius-sm) / 2); margin-right: var(--space-1); vertical-align: -3px; }
|
|
773
|
+
.source-mark.xs svg { width: 10px; height: 10px; }
|
|
749
774
|
.source-mark.has-status { position: relative; }
|
|
750
775
|
.source-mark.has-status .status-dot {
|
|
751
776
|
position: absolute; right: -3px; bottom: -3px;
|
|
@@ -757,26 +782,20 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
757
782
|
/* In-session run pill (App.tsx composer band): supersedes the GitHub pill for a
|
|
758
783
|
triggered session. Source glyph + short label + a status segment. */
|
|
759
784
|
.run-pill {
|
|
760
|
-
display: inline-flex; align-items: center; gap:
|
|
761
|
-
border:
|
|
762
|
-
border-radius: var(--radius-full); padding:
|
|
785
|
+
display: inline-flex; align-items: center; gap: var(--space-2); flex: 0 1 auto; min-width: 0; min-height: 32px;
|
|
786
|
+
border: 0; background: var(--surface-2); color: var(--ink);
|
|
787
|
+
border-radius: var(--radius-full); padding: var(--space-1) var(--space-3);
|
|
788
|
+
font-size: var(--text-sm); font-weight: var(--weight-medium);
|
|
763
789
|
}
|
|
764
|
-
.run-pill:
|
|
790
|
+
.run-pill:has(> .source-mark) { padding-left: var(--space-1); }
|
|
791
|
+
.run-pill:hover { background: var(--surface-3); }
|
|
765
792
|
.run-pill-label { flex: none; }
|
|
766
793
|
.run-pill-stat {
|
|
767
|
-
display: inline-flex; align-items: center; gap:
|
|
768
|
-
padding-left: 8px; border-left: 1px solid var(--line); color: var(--muted);
|
|
794
|
+
display: inline-flex; align-items: center; gap: 6px; min-width: 0; color: var(--muted);
|
|
769
795
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
770
796
|
}
|
|
771
797
|
/* Session-level file edit count — replaces the bulky ChangesCard above the composer. */
|
|
772
|
-
.run-pill-files {
|
|
773
|
-
flex: none;
|
|
774
|
-
padding-left: 8px;
|
|
775
|
-
border-left: 1px solid var(--line);
|
|
776
|
-
color: var(--muted);
|
|
777
|
-
font-weight: 600;
|
|
778
|
-
white-space: nowrap;
|
|
779
|
-
}
|
|
798
|
+
.run-pill-files { flex: none; color: var(--muted); white-space: nowrap; }
|
|
780
799
|
.run-pill.working .run-pill-stat { color: var(--accent); }
|
|
781
800
|
.run-pill.needs-action .run-pill-stat, .run-pill.failed .run-pill-stat { color: var(--danger); }
|
|
782
801
|
|
|
@@ -800,9 +819,10 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
800
819
|
/* Run-pill sheet outcome: the run evidence (checks, attempts, duration,
|
|
801
820
|
branch/commit, agent) joined from the account queue — see runEvidence.ts. */
|
|
802
821
|
.run-sheet-failure { padding: 11px 16px; border-bottom: 1px solid var(--line); color: var(--danger); font-size: 13px; line-height: 1.4; }
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
.run-sheet-
|
|
822
|
+
/* Key/value facts read as one quiet group: no rule between rows, one rule
|
|
823
|
+
between groups (and before the action rows that follow). */
|
|
824
|
+
.run-sheet-rows { display: flex; flex-direction: column; padding: var(--space-2) 0; border-bottom: 1px solid var(--line); }
|
|
825
|
+
.run-sheet-row { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); padding: 6px var(--space-4); font-size: var(--text-sm); }
|
|
806
826
|
.run-sheet-row .k { flex: none; color: var(--muted); }
|
|
807
827
|
.run-sheet-row .v { min-width: 0; display: flex; flex-wrap: wrap; gap: 4px 8px; justify-content: flex-end; align-items: center; color: var(--ink); font-weight: 600; text-align: right; }
|
|
808
828
|
.run-sheet-row code { font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; padding: 1px 5px; border-radius: var(--radius-sm); border: 1px solid var(--line); background: var(--surface-2); }
|
|
@@ -836,7 +856,10 @@ button.sheet-action:last-child { border-bottom: 0; }
|
|
|
836
856
|
/* GitHub pills parked in a band just above the composer: the repo picker on a
|
|
837
857
|
draft (.composer-lead) and the issue/PR context pill on an active session
|
|
838
858
|
(.composer-gh). .composer-gh collapses out of flow when there's no context. */
|
|
839
|
-
|
|
859
|
+
/* The band and the composer share the transcript's centred column, so on a wide
|
|
860
|
+
screen the input sits under the conversation rather than spanning the pane. */
|
|
861
|
+
.composer-gh, .composer-lead, .composer { align-self: center; width: min(100%, 800px); box-sizing: border-box; }
|
|
862
|
+
.composer-gh, .composer-lead { display: flex; padding: var(--space-2) var(--space-3) 0; }
|
|
840
863
|
.composer-gh { align-items: center; gap: 6px; }
|
|
841
864
|
/* The draft lead row carries more than one pick (repo + sandbox), so space them
|
|
842
865
|
and let them wrap on a narrow phone instead of squashing. */
|
|
@@ -862,14 +885,14 @@ button.sheet-action:last-child { border-bottom: 0; }
|
|
|
862
885
|
|
|
863
886
|
/* ---- Composer ---- */
|
|
864
887
|
.composer {
|
|
865
|
-
display: flex; padding:
|
|
866
|
-
padding-bottom: max(
|
|
888
|
+
display: flex; padding: var(--space-2) var(--space-3);
|
|
889
|
+
padding-bottom: max(var(--space-2), env(safe-area-inset-bottom));
|
|
867
890
|
}
|
|
868
891
|
.composer-card {
|
|
869
892
|
position: relative;
|
|
870
|
-
flex: 1; min-width: 0; display: flex; flex-direction: column; gap:
|
|
871
|
-
border: 1px solid var(--line
|
|
872
|
-
padding:
|
|
893
|
+
flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-1);
|
|
894
|
+
border: 1px solid var(--line); border-radius: var(--radius-xl); background: var(--surface-2);
|
|
895
|
+
padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
|
|
873
896
|
}
|
|
874
897
|
/* Slash-command autocomplete: a popover floating just above the composer. */
|
|
875
898
|
.slash-menu {
|
|
@@ -880,7 +903,7 @@ button.sheet-action:last-child { border-bottom: 0; }
|
|
|
880
903
|
.slash-empty { padding: 10px 12px; color: var(--muted); font-size: 13px; }
|
|
881
904
|
.slash-name { font-weight: 600; font-size: 14px; flex: none; min-width: 74px; }
|
|
882
905
|
.slash-desc { color: var(--muted); font-size: 13px; }
|
|
883
|
-
.composer-card:focus-within { border-color: var(--accent);
|
|
906
|
+
.composer-card:focus-within { border-color: var(--accent); }
|
|
884
907
|
/* Keep two readable lines even when autosize runs inside the hidden onboarding shell. */
|
|
885
908
|
.composer-input {
|
|
886
909
|
min-height: calc(2 * var(--lh-lg) + 2 * var(--space-1)); flex-shrink: 0;
|
|
@@ -896,11 +919,12 @@ button.sheet-action:last-child { border-bottom: 0; }
|
|
|
896
919
|
flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px; overflow: hidden;
|
|
897
920
|
}
|
|
898
921
|
.composer-meta > .btn {
|
|
899
|
-
gap:
|
|
922
|
+
gap: 6px; min-width: 0; flex: 0 1 auto; color: var(--muted); font-weight: var(--weight-medium);
|
|
900
923
|
}
|
|
924
|
+
.composer-meta > .btn:hover { color: var(--ink); }
|
|
901
925
|
/* Keep the startup action readable beside a long agent name on phones. */
|
|
902
926
|
.composer-meta:has([data-pending-model]) { flex-wrap: wrap; }
|
|
903
|
-
.pill-glyph { color:
|
|
927
|
+
.pill-glyph { color: inherit; flex: none; display: inline-flex; align-items: center; }
|
|
904
928
|
.pill-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
905
929
|
/* Glyph-only / short controls keep their natural width; only the long
|
|
906
930
|
agent + model labels give way when space is tight. */
|
|
@@ -914,7 +938,9 @@ button.sheet-action:last-child { border-bottom: 0; }
|
|
|
914
938
|
.composer-btn.send:not(:disabled):hover { background: var(--accent-hover); }
|
|
915
939
|
.composer-btn.send:not(:disabled):active { transform: scale(0.92); }
|
|
916
940
|
.composer-btn.send:disabled { opacity: 0.35; cursor: default; }
|
|
917
|
-
|
|
941
|
+
/* Stop is a neutral, high-contrast square — the most important control while a
|
|
942
|
+
turn runs, without borrowing the danger colour for an ordinary action. */
|
|
943
|
+
.composer-btn.stop { background: var(--ink); color: var(--bg); }
|
|
918
944
|
.composer-btn.stop.is-stopping { width: auto; border-radius: var(--radius-full); padding-inline: var(--space-3); display: inline-flex; gap: var(--space-2); }
|
|
919
945
|
.composer-btn.stop:active { transform: scale(0.92); }
|
|
920
946
|
/* "Steer current turn": an explicit interrupt, distinct from the default Send
|
|
@@ -927,7 +953,7 @@ button.sheet-action:last-child { border-bottom: 0; }
|
|
|
927
953
|
.attach-pill { padding: 4px 8px; }
|
|
928
954
|
|
|
929
955
|
/* Voice-input trigger: a circular icon button seated just left of Send. */
|
|
930
|
-
.composer-btn.mic { background:
|
|
956
|
+
.composer-btn.mic { background: transparent; color: var(--muted); }
|
|
931
957
|
.composer-btn.mic:not(:disabled):hover { color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--surface-3)); }
|
|
932
958
|
.composer-btn.mic:not(:disabled):active { transform: scale(0.92); }
|
|
933
959
|
.composer-btn.mic:disabled { opacity: 0.4; cursor: default; }
|
|
@@ -2193,6 +2219,13 @@ a.queue-item:hover { border-color: var(--line-strong); background: var(--surface
|
|
|
2193
2219
|
/* Keep both selected values visible. Long agent/model names share the
|
|
2194
2220
|
available row and use the composer's standard ellipsis behavior. */
|
|
2195
2221
|
.composer-meta { gap: 2px; }
|
|
2222
|
+
/* Phone width can't hold both full names beside two 44px buttons: the
|
|
2223
|
+
(already compacted) model keeps its label, the agent name gives way first,
|
|
2224
|
+
and the agent's decorative glyph goes so its name keeps more letters. */
|
|
2225
|
+
.composer-meta > .btn { padding-inline: 6px; }
|
|
2226
|
+
.composer-meta > .model-pill { flex-shrink: 0; max-width: 50%; }
|
|
2227
|
+
.agent-pill .pill-glyph { display: none; }
|
|
2228
|
+
.composer-actions { gap: var(--space-1); }
|
|
2196
2229
|
.automations-view-head { align-items: center; padding-bottom: 8px; }
|
|
2197
2230
|
.automations-view-head-text { min-width: 0; }
|
|
2198
2231
|
.automations-view-sub { display: none; }
|
|
@@ -2629,15 +2662,13 @@ textarea.picker-search { resize: vertical; font-family: ui-monospace, monospace;
|
|
|
2629
2662
|
.btn.lg { padding: 11px 18px; font-size: var(--text-md); }
|
|
2630
2663
|
.btn.icon { padding: var(--space-1); min-width: var(--space-7); min-height: var(--space-7); font-size: var(--text-xl); line-height: 1; }
|
|
2631
2664
|
.btn[aria-busy="true"] { cursor: wait; }
|
|
2632
|
-
/* ---- Sidebar settings gear (
|
|
2633
|
-
.settings-gear {
|
|
2634
|
-
display: inline-flex; align-items: center; justify-content:
|
|
2635
|
-
width:
|
|
2636
|
-
|
|
2637
|
-
}
|
|
2638
|
-
.settings-gear:hover { background: var(--surface-
|
|
2639
|
-
.settings-gear svg { flex: none; color: var(--muted); }
|
|
2640
|
-
.settings-gear:hover svg { color: var(--ink); }
|
|
2665
|
+
/* ---- Sidebar settings gear (round companion to New session, ChatGPT-style) ---- */
|
|
2666
|
+
.btn.icon.settings-gear {
|
|
2667
|
+
display: inline-flex; align-items: center; justify-content: center; flex: none;
|
|
2668
|
+
width: 44px; height: 44px; padding: 0; border: 0; border-radius: var(--radius-full);
|
|
2669
|
+
background: var(--surface-2); color: var(--ink);
|
|
2670
|
+
}
|
|
2671
|
+
.btn.icon.settings-gear:hover { background: var(--surface-3); }
|
|
2641
2672
|
|
|
2642
2673
|
/* ---- Usage bar ---- */
|
|
2643
2674
|
|
package/dist/apps/tokens.css
CHANGED
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
* hex or px. `pnpm run check:design` enforces that no other stylesheet redeclares
|
|
13
13
|
* a palette token. See packages/web/CLAUDE.md for the design rules agents follow.
|
|
14
14
|
*
|
|
15
|
-
* Palette: high-contrast
|
|
16
|
-
*
|
|
15
|
+
* Palette: high-contrast light + dark themes whose neutrals carry a faint cool
|
|
16
|
+
* tint (the accent's hue) so surfaces and the accent read as one family; dark
|
|
17
|
+
* sits on true black. Color is reserved for actions and status. Toggle dark with <html data-theme="dark">; with no attribute it
|
|
17
18
|
* follows the OS. prefers-reduced-motion collapses the motion tokens.
|
|
18
19
|
*
|
|
19
20
|
* Naming: the canonical vocabulary is --bg / --surface* / --ink / --muted /
|
|
@@ -29,12 +30,12 @@
|
|
|
29
30
|
/* ---- Core surfaces & text (neutral) ---- */
|
|
30
31
|
--bg: #ffffff;
|
|
31
32
|
--surface: #ffffff;
|
|
32
|
-
--surface-2: #
|
|
33
|
-
--surface-3: #
|
|
34
|
-
--ink: #
|
|
35
|
-
--muted: #
|
|
36
|
-
--line: #
|
|
37
|
-
--line-strong: #
|
|
33
|
+
--surface-2: #f3f5f7;
|
|
34
|
+
--surface-3: #e8ecef;
|
|
35
|
+
--ink: #0f1215;
|
|
36
|
+
--muted: #5f6a73;
|
|
37
|
+
--line: #e3e7ea;
|
|
38
|
+
--line-strong: #cdd4d9;
|
|
38
39
|
--overlay: rgba(0, 0, 0, 0.46);
|
|
39
40
|
--overlay-strong: rgba(0, 0, 0, 0.8);
|
|
40
41
|
|
|
@@ -156,8 +157,8 @@
|
|
|
156
157
|
|
|
157
158
|
:root[data-theme="dark"] {
|
|
158
159
|
color-scheme: dark;
|
|
159
|
-
--bg: #
|
|
160
|
-
--ink: #
|
|
160
|
+
--bg: #000000; --surface: #000000; --surface-2: #15181b; --surface-3: #22272b;
|
|
161
|
+
--ink: #f3f5f7; --muted: #99a2aa; --line: #1f2327; --line-strong: #353b41;
|
|
161
162
|
--overlay: rgba(0, 0, 0, 0.7); --overlay-strong: rgba(0, 0, 0, 0.8);
|
|
162
163
|
--accent: #8fb6cd; --accent-contrast: #0a0a0a; --accent-hover: #a7cadd;
|
|
163
164
|
--danger: #c08a83; --danger-soft: #3a2420; --danger-contrast: #0a0a0a; --ok: #86a99f; --merged: #a99bc4;
|
|
@@ -178,8 +179,8 @@
|
|
|
178
179
|
@media (prefers-color-scheme: dark) {
|
|
179
180
|
:root:not([data-theme]) {
|
|
180
181
|
color-scheme: dark;
|
|
181
|
-
--bg: #
|
|
182
|
-
--ink: #
|
|
182
|
+
--bg: #000000; --surface: #000000; --surface-2: #15181b; --surface-3: #22272b;
|
|
183
|
+
--ink: #f3f5f7; --muted: #99a2aa; --line: #1f2327; --line-strong: #353b41;
|
|
183
184
|
--overlay: rgba(0, 0, 0, 0.7); --overlay-strong: rgba(0, 0, 0, 0.8);
|
|
184
185
|
--accent: #8fb6cd; --accent-contrast: #0a0a0a; --accent-hover: #a7cadd;
|
|
185
186
|
--danger: #c08a83; --danger-soft: #3a2420; --danger-contrast: #0a0a0a; --ok: #86a99f; --merged: #a99bc4;
|
|
@@ -71,6 +71,14 @@ export function messageContentAtoms(message) {
|
|
|
71
71
|
}
|
|
72
72
|
else if (type === "text")
|
|
73
73
|
pushText(b.text);
|
|
74
|
+
// Reasoning is an atom too: Claude streams each thinking block as its own
|
|
75
|
+
// assistant message, and without this a reloaded thinking-only message had
|
|
76
|
+
// no atoms, read as "opaque", and was re-appended after the final answer.
|
|
77
|
+
else if (type === "thinking" || type === "reasoning") {
|
|
78
|
+
const text = thinkingTextFromContent([b]).trim();
|
|
79
|
+
if (text)
|
|
80
|
+
texts.push(`thinking#${text}`);
|
|
81
|
+
}
|
|
74
82
|
}
|
|
75
83
|
}
|
|
76
84
|
return { toolIds, texts };
|
package/package.json
CHANGED