typebulb 0.14.5 → 0.14.7
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/agents/claude/client.js +122 -122
- package/dist/agents/claude/styles.css +128 -75
- package/dist/index.js +185 -184
- package/package.json +1 -1
|
@@ -155,6 +155,28 @@ body {
|
|
|
155
155
|
cluster spaces evenly regardless of which pills are present. */
|
|
156
156
|
.token-wrap:empty, .sid-wrap:empty, .servers-wrap:empty { display: none; }
|
|
157
157
|
.picker, .servers-pop {
|
|
158
|
+
--menu-h: 428px; /* one height for both statusbar menus — they sit side by side, so a
|
|
159
|
+
mismatched cap reads as a glitch; .picker grows to it, .servers-pop
|
|
160
|
+
too (the drilled-in console is the one fixed-height exception, see
|
|
161
|
+
.log-mode). Sized to show exactly 12 rows
|
|
162
|
+
(12 × --menu-row-h + 11 gaps + filter + padding) — recognition fades
|
|
163
|
+
past ~12 and search owns the tail. Plain px: desktop-only surface,
|
|
164
|
+
every desktop window fits it. 428, not 427: at 427 the two menus land
|
|
165
|
+
on different device-pixel roundings, a 1px sibling mismatch — the
|
|
166
|
+
lesser evil is 1px off the ideal height. */
|
|
167
|
+
--menu-row-h: 29px; /* one row height for both menus' lists — rows must match pitch exactly
|
|
168
|
+
or the side-by-side menus read as two designs. Whole px, eyeball-tuned;
|
|
169
|
+
the row paddings are kept below it so this floor is what governs. */
|
|
170
|
+
/* ONE geometry contract for both menus — sizing policy, padding, stacking. Stating it twice is
|
|
171
|
+
how every sibling discrepancy of June '26 happened (row pitch, gaps, fixed-vs-grow). max-height,
|
|
172
|
+
not height: a menu hugs its content and caps at the 12 rows above — a fixed height left a
|
|
173
|
+
1-bulb project with a row floating atop a 400px void. Per-menu rules keep only width. */
|
|
174
|
+
max-height: var(--menu-h);
|
|
175
|
+
overflow: hidden;
|
|
176
|
+
padding: .35rem;
|
|
177
|
+
display: flex;
|
|
178
|
+
flex-direction: column;
|
|
179
|
+
gap: .15rem;
|
|
158
180
|
position: absolute;
|
|
159
181
|
bottom: calc(100% + .35rem);
|
|
160
182
|
right: 0;
|
|
@@ -165,56 +187,78 @@ body {
|
|
|
165
187
|
box-shadow: 0 8px 30px rgba(0, 0, 0, .45);
|
|
166
188
|
}
|
|
167
189
|
|
|
190
|
+
/* ---- Shimmer — the one "working" cue. One gradient, one keyframes, composed via class, never
|
|
191
|
+
re-pasted (paste-drift is how each new shimmer kept landing at its own speed). `.shimmer` sweeps
|
|
192
|
+
the element's background; `.shimmer-text` clips the sweep to the glyphs alone. Knobs, set by the
|
|
193
|
+
using rule: --shimmer-base (the gradient's resting color — transparent for see-through chrome, an
|
|
194
|
+
opaque surface for pills that must cover content) and --shimmer-mix (accent strength). Pick the
|
|
195
|
+
cadence by the band's LINEAR speed, which is what reads consistent: travel is proportional to
|
|
196
|
+
element width (background-size 250%), and ~2rem/s is the calibrated pace — so narrow chrome
|
|
197
|
+
(a 1.7rem play button) takes the 2.2s default and anything text-width or wider takes
|
|
198
|
+
`.shimmer-slow` (7s). A fast sweep reads as urgency, not progress. */
|
|
199
|
+
/* The state longhands are !important: this class composes onto elements whose resting rules set a
|
|
200
|
+
`background:` shorthand at arbitrary specificity (button resets, .overlay-pill, :hover tints) —
|
|
201
|
+
any of which would silently kill the gradient (the bug that ate the play button's shimmer). A
|
|
202
|
+
working cue must win while it's on; resting background-color still shows beneath the sweep. */
|
|
203
|
+
.shimmer, .shimmer-text { background-size: 250% 100% !important; animation: bulb-shimmer var(--shimmer-speed, 2.2s) linear infinite !important; }
|
|
204
|
+
.shimmer {
|
|
205
|
+
background-image: linear-gradient(100deg, var(--shimmer-base, transparent) 30%, color-mix(in srgb, var(--accent) var(--shimmer-mix, 35%), var(--shimmer-base, transparent)) 50%, var(--shimmer-base, transparent) 70%) !important;
|
|
206
|
+
background-color: var(--shimmer-base, transparent);
|
|
207
|
+
}
|
|
208
|
+
.shimmer-text {
|
|
209
|
+
/* Shrink-to-fit, so the sweep paces the text's own length, not the container's — on a full-width
|
|
210
|
+
box the band spends most of its run off-glyph (same move as typebulb.com's shimmer.ts). */
|
|
211
|
+
display: inline-block;
|
|
212
|
+
background-image: linear-gradient(100deg, currentColor 35%, var(--accent) 50%, currentColor 65%) !important;
|
|
213
|
+
-webkit-background-clip: text;
|
|
214
|
+
background-clip: text;
|
|
215
|
+
-webkit-text-fill-color: transparent;
|
|
216
|
+
}
|
|
217
|
+
.shimmer-slow { --shimmer-speed: 7s; }
|
|
218
|
+
@keyframes bulb-shimmer { from { background-position: 250% 0; } to { background-position: -250% 0; } }
|
|
219
|
+
@media (prefers-reduced-motion: reduce) {
|
|
220
|
+
.shimmer { animation: none !important; background: color-mix(in srgb, var(--accent) 15%, var(--shimmer-base, transparent)) !important; }
|
|
221
|
+
.shimmer-text { animation: none !important; background: none !important; -webkit-text-fill-color: currentColor; }
|
|
222
|
+
}
|
|
223
|
+
|
|
168
224
|
/* CC mid-turn: the token pill doubles as the working indicator — an accent shimmer
|
|
169
225
|
over the chip, the count frozen until the turn flushes. Passive — driven by the
|
|
170
226
|
live-chain leaf, not a live token stream (the JSONL is flushed in batches, so this
|
|
171
|
-
can sit lit through a multi-minute buffering window). The sweep
|
|
172
|
-
--panel, not transparent like
|
|
173
|
-
the message text the strip lets through. */
|
|
174
|
-
.token.busy {
|
|
175
|
-
border-color: var(--accent);
|
|
176
|
-
background: linear-gradient(100deg, var(--panel) 30%, color-mix(in srgb, var(--accent) 25%, var(--panel)) 50%, var(--panel) 70%);
|
|
177
|
-
background-size: 250% 100%;
|
|
178
|
-
/* Much slower than .launching's sweep: that one paces a ~2s wait, this can sit lit for
|
|
179
|
-
minutes — at that dwell a fast sweep reads as urgency, not progress. */
|
|
180
|
-
animation: bulb-shimmer 7s linear infinite;
|
|
181
|
-
}
|
|
182
|
-
@media (prefers-reduced-motion: reduce) {
|
|
183
|
-
.token.busy { animation: none; background: color-mix(in srgb, var(--accent) 15%, var(--panel)); }
|
|
184
|
-
}
|
|
227
|
+
can sit lit through a multi-minute buffering window — hence shimmer-slow). The sweep
|
|
228
|
+
blends with --panel, not transparent like the launch buttons': statusbar pills must
|
|
229
|
+
stay opaque over the message text the strip lets through. */
|
|
230
|
+
.token.busy { border-color: var(--accent); --shimmer-base: var(--panel); --shimmer-mix: 25%; }
|
|
185
231
|
|
|
186
232
|
/* Session list — shares the popover chrome (.picker above); these are
|
|
187
233
|
just its own dimensions. */
|
|
188
|
-
.picker {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
padding: .35rem;
|
|
193
|
-
display: flex;
|
|
194
|
-
flex-direction: column;
|
|
195
|
-
gap: .15rem;
|
|
196
|
-
}
|
|
197
|
-
/* The filter (.bulb-filter-control) pins at the top; the row list scrolls inside the capped box —
|
|
198
|
-
same shape as the launcher's .servers-pop / .bulb-list. */
|
|
234
|
+
.picker { width: min(440px, calc(100vw - 2rem)); }
|
|
235
|
+
/* The filter (.bulb-filter-control) pins at the bottom — the popover's anchored edge, so it never
|
|
236
|
+
jumps as the filtered list changes height; the row list scrolls inside the capped box, resting at
|
|
237
|
+
its end (newest-at-bottom) — same shape as the launcher's .servers-pop / .bulb-list. */
|
|
199
238
|
.picker-list { display: flex; flex-direction: column; gap: .15rem; flex: 1; min-height: 0; overflow-y: auto; padding-right: 4px; }
|
|
200
239
|
.picker-empty { padding: .8rem; color: var(--muted); font-size: .85rem; text-align: center; }
|
|
201
240
|
.picker-row {
|
|
202
241
|
display: flex;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
242
|
+
flex-direction: column;
|
|
243
|
+
/* flex:none — the explicit min-height below replaces flexbox's implicit min-height:auto floor,
|
|
244
|
+
which would otherwise let an overflowing list squash rows below their content (snippet rows
|
|
245
|
+
rendered as overlapping text). The list scrolls; rows never compress. */
|
|
246
|
+
flex: none;
|
|
247
|
+
gap: .2rem;
|
|
248
|
+
/* min-height, not height: a full-text result row grows for its snippet line. */
|
|
249
|
+
padding: .35rem .55rem;
|
|
250
|
+
min-height: var(--menu-row-h);
|
|
251
|
+
box-sizing: border-box;
|
|
252
|
+
justify-content: center;
|
|
206
253
|
border-radius: 6px;
|
|
207
254
|
cursor: pointer;
|
|
208
|
-
border: 1px solid transparent;
|
|
209
255
|
font-size: .85rem;
|
|
210
256
|
}
|
|
257
|
+
.picker-row-main { display: flex; gap: .6rem; align-items: baseline; }
|
|
211
258
|
.picker:focus { outline: none; } /* the list owns its own highlight; no focus ring */
|
|
212
259
|
.picker-row:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
|
|
213
|
-
/* Keyboard cursor (arrow keys / hover) —
|
|
214
|
-
.picker-row.active {
|
|
215
|
-
background: color-mix(in srgb, var(--accent) 18%, transparent);
|
|
216
|
-
border-color: color-mix(in srgb, var(--accent) 40%, transparent);
|
|
217
|
-
}
|
|
260
|
+
/* Keyboard cursor (arrow keys / hover) — same borderless tint as the launcher's .server-row.active. */
|
|
261
|
+
.picker-row.active { background: color-mix(in srgb, var(--accent) 16%, transparent); }
|
|
218
262
|
/* The attached session — a leading accent dot in its own gutter slot, reserved (transparent) on
|
|
219
263
|
every row so titles align whether or not it's shown, and filled only on the attached row so it
|
|
220
264
|
reads as "you are here" even when the cursor has moved off. */
|
|
@@ -237,24 +281,28 @@ body {
|
|
|
237
281
|
font-size: .72rem;
|
|
238
282
|
min-width: 2.6rem; text-align: right;
|
|
239
283
|
}
|
|
284
|
+
.picker-hits { color: var(--muted); font-size: .72rem; white-space: nowrap; }
|
|
285
|
+
/* Full-text result context: first matching turn, indented past the dot gutter into the title column. */
|
|
286
|
+
.picker-snippet {
|
|
287
|
+
color: var(--muted);
|
|
288
|
+
font-size: .78rem;
|
|
289
|
+
line-height: 1.4;
|
|
290
|
+
margin-left: calc(7px + .6rem);
|
|
291
|
+
overflow-wrap: anywhere;
|
|
292
|
+
}
|
|
293
|
+
.picker-mark {
|
|
294
|
+
background: color-mix(in srgb, var(--accent) 30%, transparent);
|
|
295
|
+
border-radius: 2px;
|
|
296
|
+
color: var(--fg);
|
|
297
|
+
}
|
|
240
298
|
|
|
241
299
|
/* Running-breakouts list — shares the popover chrome (.servers-pop above); its own dimensions +
|
|
242
300
|
per-row layout: the play/stop button + name read together on the left (▶/■ Title, name flex:1),
|
|
243
301
|
and the metadata/controls form a right-aligned cluster of fixed-width columns (logs · trust ·
|
|
244
302
|
time/port) that line up row-to-row — right-anchored, so the rightmost (time/port) always aligns and
|
|
245
303
|
the rest stack inward (logs and time/port share a width; trust is wider, to fit "restricted"). The
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
scrolls inside (see .bulb-list). */
|
|
249
|
-
.servers-pop {
|
|
250
|
-
width: min(560px, calc(100vw - 2rem));
|
|
251
|
-
height: min(66vh, 560px);
|
|
252
|
-
overflow: hidden;
|
|
253
|
-
padding: .35rem;
|
|
254
|
-
display: flex;
|
|
255
|
-
flex-direction: column;
|
|
256
|
-
gap: .15rem;
|
|
257
|
-
}
|
|
304
|
+
filter pins at the bottom and the list scrolls inside (see .bulb-list). */
|
|
305
|
+
.servers-pop { width: min(560px, calc(100vw - 2rem)); }
|
|
258
306
|
.server-row {
|
|
259
307
|
/* Subgrid: all rows share ONE set of column tracks (defined on .bulb-list). A per-row grid sizes
|
|
260
308
|
its columns independently — which is exactly what broke alignment (a stopped row with no
|
|
@@ -271,7 +319,8 @@ body {
|
|
|
271
319
|
the left, an asymmetry). Text gets its breathing room inside the highlight via end-item margins
|
|
272
320
|
(.server-stop/.bulb-launch on the left, .server-port/.bulb-time on the right) rather than row
|
|
273
321
|
padding, which would shift the subgrid tracks and break alignment. */
|
|
274
|
-
padding: .
|
|
322
|
+
padding: .05rem 0;
|
|
323
|
+
min-height: var(--menu-row-h);
|
|
275
324
|
border-radius: 6px;
|
|
276
325
|
font-size: .85rem;
|
|
277
326
|
}
|
|
@@ -294,7 +343,7 @@ a.server-port:hover { text-decoration: underline; }
|
|
|
294
343
|
/* Launcher filter box — pinned above the list; type to narrow (matches name + path). The control
|
|
295
344
|
wrapper pins to the top and anchors the clear (×) at the far right (position:relative + the
|
|
296
345
|
input's right padding reserves its room). */
|
|
297
|
-
.bulb-filter-control { position: relative; flex: none; margin-
|
|
346
|
+
.bulb-filter-control { position: relative; flex: none; margin-top: .35rem; }
|
|
298
347
|
.bulb-filter {
|
|
299
348
|
font: inherit;
|
|
300
349
|
font-size: .82rem;
|
|
@@ -315,11 +364,29 @@ a.server-port:hover { text-decoration: underline; }
|
|
|
315
364
|
color: var(--muted); font-size: 1.05rem; line-height: 1; padding: 0 .3rem; border-radius: 4px;
|
|
316
365
|
}
|
|
317
366
|
.bulb-filter-clear:hover { color: var(--accent); }
|
|
367
|
+
/* Filter-mode toggle (full-text search) — inset at the input's right edge; the clear × shifts
|
|
368
|
+
inward beside it. Only rendered when the host passes a trailing control (the session picker). */
|
|
369
|
+
.bulb-filter-control.has-trailing .bulb-filter { padding-right: 3.8rem; }
|
|
370
|
+
.bulb-filter-control.has-trailing .bulb-filter-clear { right: 2.5rem; }
|
|
371
|
+
.bulb-filter-mode {
|
|
372
|
+
/* Stretches flush to the input's top/right/bottom, inside its 1px border; the right corners
|
|
373
|
+
match the input's 6px radius so the latched fill reads as part of the box. */
|
|
374
|
+
position: absolute; right: 1px; top: 1px; bottom: 1px;
|
|
375
|
+
appearance: none; border: none; background: transparent; cursor: pointer;
|
|
376
|
+
font-size: .8rem; line-height: 1; padding: 0 .45rem;
|
|
377
|
+
border-radius: 0 5px 5px 0;
|
|
378
|
+
}
|
|
379
|
+
/* Same state cue as the prose pill's glyph: the emoji can't take currentColor, so it goes
|
|
380
|
+
grayscale at rest, color while hovered or on — filtered on the inner span, never the button. */
|
|
381
|
+
.bulb-filter-mode .glyph-img { filter: grayscale(1); opacity: .75; }
|
|
382
|
+
.bulb-filter-mode:hover .glyph-img, .bulb-filter-mode.on .glyph-img { filter: none; opacity: 1; }
|
|
383
|
+
/* Latched: a --panel fill — the popover's own surface, one step off the input's --bg. */
|
|
384
|
+
.bulb-filter-mode.on { background: var(--panel); }
|
|
318
385
|
/* Scrolls within the fixed-height popover so the filter stays put and the box never grows. */
|
|
319
386
|
/* The shared grid for the launcher rows: each .server-row is a subgrid spanning these tracks, so
|
|
320
387
|
columns line up row-to-row. auto cols size to their widest content (tight, no slack); 1fr is the
|
|
321
388
|
name. A small right padding keeps the selected-row highlight off the scrollbar. */
|
|
322
|
-
.bulb-list { display: grid; grid-template-columns: auto 1fr auto auto auto; column-gap: .6rem; row-gap: .
|
|
389
|
+
.bulb-list { display: grid; grid-template-columns: auto 1fr auto auto auto; column-gap: .6rem; row-gap: .15rem; align-items: center; align-content: start; padding-right: 4px; flex: 1; min-height: 0; overflow-y: auto; }
|
|
323
390
|
/* A stopped bulb's name isn't a link (no running URL), so it stays plain foreground. */
|
|
324
391
|
.server-name.stopped { color: var(--fg); }
|
|
325
392
|
.bulb-time { color: var(--muted); font-size: .72rem; font-variant-numeric: tabular-nums; text-align: right; margin-right: .4rem; }
|
|
@@ -331,7 +398,9 @@ a.server-port:hover { text-decoration: underline; }
|
|
|
331
398
|
background: transparent; border: 1px solid var(--border); border-radius: 5px;
|
|
332
399
|
height: 1.7rem; display: inline-flex; align-items: center; justify-content: center;
|
|
333
400
|
}
|
|
334
|
-
|
|
401
|
+
/* Shorter than the icon buttons: a bordered text pill at full row height reads as cramped, where
|
|
402
|
+
the round play/stop icons are meant to fill it. */
|
|
403
|
+
.trust-toggle { font-size: .76rem; height: 1.45rem; padding: 0 .5rem; color: var(--muted); justify-self: center; }
|
|
335
404
|
.trust-toggle:hover, .trust-toggle.on { color: var(--accent); border-color: var(--accent); }
|
|
336
405
|
.server-stop, .bulb-launch { width: 1.7rem; padding: 0; border-radius: 50%; margin-left: .4rem; }
|
|
337
406
|
.btn-icon { display: block; }
|
|
@@ -344,18 +413,7 @@ a.server-port:hover { text-decoration: underline; }
|
|
|
344
413
|
/* Launching: stays visible (hover-independent) and shimmers until the row flips to a stop button,
|
|
345
414
|
so the ~2s wait reads as "working" rather than a dead click. Transient — driven by the in-memory
|
|
346
415
|
launching set, never persisted. */
|
|
347
|
-
.bulb-launch.launching {
|
|
348
|
-
visibility: visible; border-color: var(--accent);
|
|
349
|
-
background: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--accent) 35%, transparent) 50%, transparent 70%);
|
|
350
|
-
background-size: 250% 100%;
|
|
351
|
-
/* One full pass per ~2s wait — slow enough to stay calm, fast enough that the band
|
|
352
|
-
is guaranteed to cross while the user is actually watching. */
|
|
353
|
-
animation: bulb-shimmer 2.2s linear infinite;
|
|
354
|
-
}
|
|
355
|
-
@keyframes bulb-shimmer { from { background-position: 250% 0; } to { background-position: -250% 0; } }
|
|
356
|
-
@media (prefers-reduced-motion: reduce) {
|
|
357
|
-
.bulb-launch.launching { animation: none; background: color-mix(in srgb, var(--accent) 18%, transparent); }
|
|
358
|
-
}
|
|
416
|
+
.bulb-launch.launching { visibility: visible; border-color: var(--accent); }
|
|
359
417
|
.server-stop { color: var(--muted); }
|
|
360
418
|
.server-stop:hover { color: var(--err); border-color: var(--err); }
|
|
361
419
|
/* Elevation prompt (VS-Code-Workspace-Trust style) — a modal over the whole view, since a
|
|
@@ -392,7 +450,10 @@ a.server-port:hover { text-decoration: underline; }
|
|
|
392
450
|
body fills the popover's height. overflow:hidden lets the rounded popover border clip the
|
|
393
451
|
square head/body; the body scrolls internally. */
|
|
394
452
|
.servers-pop.log-mode {
|
|
395
|
-
padding: 0;
|
|
453
|
+
padding: 0;
|
|
454
|
+
/* The one fixed-height surface: a console wants its full frame regardless of how little it has
|
|
455
|
+
logged yet — a height that tracked the log would grow line by line. */
|
|
456
|
+
height: var(--menu-h);
|
|
396
457
|
}
|
|
397
458
|
.servers-pop.log-mode:focus { outline: none; }
|
|
398
459
|
.bulb-log-head {
|
|
@@ -789,18 +850,10 @@ a.server-port:hover { text-decoration: underline; }
|
|
|
789
850
|
.md .bulb-embed:hover .bulb-controls .overlay-pill,
|
|
790
851
|
.md .bulb-controls .overlay-pill:focus-visible { opacity: 1; }
|
|
791
852
|
.md .bulb-breakout:disabled { cursor: default; opacity: 1; }
|
|
792
|
-
/* Breakout in flight:
|
|
793
|
-
rather than dead —
|
|
794
|
-
|
|
795
|
-
.md .bulb-breakout.launching {
|
|
796
|
-
color: var(--accent); border-color: var(--accent);
|
|
797
|
-
background: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--accent) 35%, transparent) 50%, transparent 70%);
|
|
798
|
-
background-size: 250% 100%;
|
|
799
|
-
animation: bulb-shimmer 2.2s linear infinite;
|
|
800
|
-
}
|
|
801
|
-
@media (prefers-reduced-motion: reduce) {
|
|
802
|
-
.md .bulb-breakout.launching { animation: none; background: color-mix(in srgb, var(--accent) 18%, transparent); }
|
|
803
|
-
}
|
|
853
|
+
/* Breakout in flight: shimmers through the ~2s write+spawn wait so the click reads as "working"
|
|
854
|
+
rather than dead — same treatment as the launcher's play button (.bulb-launch.launching).
|
|
855
|
+
:disabled already keeps it visible if the pointer leaves. */
|
|
856
|
+
.md .bulb-breakout.launching { color: var(--accent); border-color: var(--accent); }
|
|
804
857
|
/* Copy pill "copied" flash — mirrors the message .copy.done accent cue, scoped to the
|
|
805
858
|
embed control so it doesn't pick up the bubble-hover reveal. */
|
|
806
859
|
.md .bulb-copy.done { color: var(--accent); border-color: var(--accent); }
|