@cplieger/web-terminal-ui 4.2.0 → 4.3.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.
package/README.md CHANGED
@@ -137,14 +137,14 @@ are importable from `…/features/<name>` (`clipboard`, `context-menu`,
137
137
 
138
138
  ### Options
139
139
 
140
- | Option | Default | Purpose |
141
- | ----------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
142
- | `features` | _(none — bare kernel)_ | The feature list. Omitted or empty builds only the terminal (no chrome). Use a preset from `./presets` or a hand-picked array. |
143
- | `layout` | `"viewport"` | How the terminal claims space. `"viewport"`: the root becomes a fixed full-viewport box (the full-page product). `"container"`: the root fills your container element, which becomes the styling and positioning boundary (the embedded case). |
144
- | `wsPath` | `"/ws"` | WebSocket endpoint path the engine connects to. |
145
- | `fontReady` | `'14px "MonaspiceNe NFM"'` | CSS font shorthand awaited before the first resize, so the server is sized against the real web font's cell metrics rather than a fallback. |
146
- | `loading` | _(none)_ | A pre-JS loading overlay element (kept in your served HTML so it paints before this module loads); it is faded out and removed once the first frame renders. |
147
- | `theme` | _(none)_ | Theme overrides (CSS custom properties on the terminal root): `--accent`, `--tab-bg`, `--tab-hover-bg`, `--tab-active-bg`, `--tab-active-fg`, `--tab-active-border`. The library ships neutral defaults. |
140
+ | Option | Default | Purpose |
141
+ | ----------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
142
+ | `features` | _(none — bare kernel)_ | The feature list. Omitted or empty builds only the terminal (no chrome). Use a preset from `./presets` or a hand-picked array. |
143
+ | `layout` | `"viewport"` | How the terminal claims space. `"viewport"`: the root becomes a fixed full-viewport box (the full-page product). `"container"`: the root fills your container element, which becomes the styling and positioning boundary (the embedded case). |
144
+ | `wsPath` | `"/ws"` | WebSocket endpoint path the engine connects to. |
145
+ | `fontReady` | `'14px "MonaspiceNe NFM"'` | CSS font shorthand awaited before the first resize, so the server is sized against the real web font's cell metrics rather than a fallback. |
146
+ | `loading` | _(none)_ | A pre-JS loading overlay element (kept in your served HTML so it paints before this module loads); it is faded out and removed once the first frame renders. |
147
+ | `theme` | _(none)_ | Theme overrides (CSS custom properties on the terminal root): `--accent`, `--tab-bg`, `--tab-hover-bg`, `--tab-active-bg`, `--tab-active-fg`, `--tab-active-border`, plus the activity-dot palette `--status-working`, `--status-done`, `--status-input` (the working and input rings derive from their own tokens). The library ships neutral defaults. |
148
148
 
149
149
  `createTerminal()` returns a handle: `focus()` re-focuses the terminal input
150
150
  (and opens the soft keyboard on touch); `send(bytes)` sends bytes to the active
package/css/00-tokens.css CHANGED
@@ -44,6 +44,13 @@
44
44
  var(--text) 25%
45
45
  ); /* subtle edge: the fill lightened + slightly desaturated, matching the inactive chip's faint border rather than a vivid accent outline */
46
46
 
47
+ /* Status-dot palette (the activity vocabulary painted in 30-tabs.css; the
48
+ switcher notification dot reuses the same rules). The working and input
49
+ rings each derive from their own token in 30-tabs.css, so one override
50
+ recolors dot + ring together. */
51
+ --status-working: #d9f99d; /* agent working (pulses): pale lime */
52
+ --status-done: #22c55e; /* turn finished: solid green */
53
+ --status-input: #fb923c; /* action required: solid orange + ring */
47
54
  --radius: 0.75rem;
48
55
  --radius-inner: 0.5rem;
49
56
  /* Small square icon buttons (e.g. the 24px tab-close x): at that size the
package/css/30-tabs.css CHANGED
@@ -376,33 +376,42 @@
376
376
  border: 1.5px solid color-mix(in oklch, var(--text) 45%, transparent);
377
377
  }
378
378
 
379
- /* Agent working: solid pulsing pale lime. Its high lightness keeps it clear on
380
- every tab state, while its yellow-green hue complements the Kiro purple active
381
- tab. Motion is the primary non-hue cue. Server-side this is driven by the OSC
382
- 9;4 progress signal, so it tracks agent activity, not the user typing at the
383
- prompt. */
379
+ /* Agent working: solid pulsing dot (--status-working; pale lime by default —
380
+ its high lightness keeps it clear on every tab state) wearing the same 2px
381
+ ring as input, so the two agent-turn states share one silhouette: a live
382
+ turn pulses (dot + ring together), a turn blocked on the user is that same
383
+ silhouette frozen and recolored (input, below). Motion separates working
384
+ from input; the ring separates both from done's bare disc. Server-side this
385
+ is driven by the OSC 9;4 progress signal, so it tracks agent activity, not
386
+ the user typing at the prompt. */
384
387
  :where(.wt-root) .wt-status-dot[data-status="working"] {
385
- background: #d9f99d;
386
- border-color: #d9f99d;
388
+ background: var(--status-working);
389
+ border-color: var(--status-working);
390
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--status-working) 40%, transparent);
387
391
  animation: wt-pulse 1.2s ease-in-out infinite;
388
392
  }
389
393
 
390
- /* Agent done / ready: solid saturated green, matching Kiro IDE's "Ready"
391
- (#22c55e), no motion. Keeping it darker and more saturated than working's
392
- pale lime makes the two states distinct by lightness as well as motion. */
394
+ /* Agent done / ready: solid disc (--status-done), no motion. The default green
395
+ matches Kiro IDE's "Ready" (#22c55e), darker and more saturated than
396
+ working's default pale lime so the two states differ by lightness as well as
397
+ motion. */
393
398
  :where(.wt-root) .wt-status-dot[data-status="done"] {
394
- background: #22c55e;
395
- border-color: #22c55e;
396
- }
397
-
398
- /* User action required (permission / approval): solid orange (#fb923c), shifted
399
- away from the old amber so it is clearly separated from both pale-lime working
400
- and green done, plus a matching ring so it reads as "needs you" via shape as
401
- well as hue. It persists until you act on or switch into the tab. */
399
+ background: var(--status-done);
400
+ border-color: var(--status-done);
401
+ }
402
+
403
+ /* User action required (permission / approval): working's exact silhouette —
404
+ solid dot + 2px ring — frozen and recolored (--status-input; the default
405
+ orange is shifted away from the old amber so it separates from both
406
+ default-lime working and green done). The stillness is the message: the
407
+ agent's turn is mid-flight but blocked on you. The ring keeps it distinct
408
+ from done's bare disc without leaning on hue; it derives from the same token
409
+ at 40% alpha, so a theme override recolors dot + ring together. It persists
410
+ until you act on or switch into the tab. */
402
411
  :where(.wt-root) .wt-status-dot[data-status="input"] {
403
- background: #fb923c;
404
- border-color: #fb923c;
405
- box-shadow: 0 0 0 2px rgb(251 146 60 / 40%);
412
+ background: var(--status-input);
413
+ border-color: var(--status-input);
414
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--status-input) 40%, transparent);
406
415
  }
407
416
 
408
417
  /* Exited: a dim hollow dot, static; distinct from idle by its lower opacity. */
@@ -417,15 +426,18 @@
417
426
  100% {
418
427
  /* Pin the animated layer's paint as well as its opacity. When working begins
419
428
  in the same frame that input/done ends, an opacity-only animation can
420
- pulse the previously rasterized orange/green dot. */
421
- background-color: #d9f99d;
422
- border-color: #d9f99d;
429
+ pulse the previously rasterized input/done paint (the input ring
430
+ included, hence the box-shadow pin). */
431
+ background-color: var(--status-working);
432
+ border-color: var(--status-working);
433
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--status-working) 40%, transparent);
423
434
  opacity: 1;
424
435
  }
425
436
 
426
437
  50% {
427
- background-color: #d9f99d;
428
- border-color: #d9f99d;
438
+ background-color: var(--status-working);
439
+ border-color: var(--status-working);
440
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--status-working) 40%, transparent);
429
441
  opacity: 0.4;
430
442
  }
431
443
  }
@@ -434,10 +446,13 @@
434
446
  @media (prefers-reduced-motion: reduce) {
435
447
  :where(.wt-root) .wt-status-dot[data-status="working"] {
436
448
  animation: none;
437
- /* The pulse is working's ONLY non-hue cue; with motion removed,
438
- add a static shape cue (an inner hole -> a ring) so working differs
439
- from done (a solid green disc) by shape, not hue alone (WCAG 1.4.1). */
440
- box-shadow: inset 0 0 0 2px var(--bg);
449
+ /* The pulse is what separates working from input's frozen silhouette; with
450
+ motion removed, punch an inner hole (dot -> donut) so working differs
451
+ from input (solid ringed disc) and done (bare disc) by shape, not hue
452
+ alone (WCAG 1.4.1). The outer ring stays. */
453
+ box-shadow:
454
+ inset 0 0 0 2px var(--bg),
455
+ 0 0 0 2px color-mix(in srgb, var(--status-working) 40%, transparent);
441
456
  }
442
457
  }
443
458
 
@@ -280,10 +280,11 @@
280
280
  }
281
281
 
282
282
  /* Latest-wins background-tab notification dot on the switch button — the moved
283
- attention cue. Amber = a background terminal needs input, green = a background
284
- turn finished. Reuses the exact .wt-status-dot colours (30-tabs.css) so it
285
- matches the per-tab dots. Hidden until the tabs feature sets data-status;
286
- cleared when the list opens (expandSwitcher). */
283
+ attention cue: the input colour when a background terminal needs input, the
284
+ done colour when a background turn finished. Reuses the exact .wt-status-dot
285
+ rules (30-tabs.css, --status-* tokens) so it matches the per-tab dots. Hidden
286
+ until the tabs feature sets data-status; cleared when the list opens
287
+ (expandSwitcher). */
287
288
  :where(.wt-root) .wt-switcher-switch-dot {
288
289
  position: absolute;
289
290
  top: 6px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cplieger/web-terminal-ui",
3
- "version": "4.2.0",
3
+ "version": "4.3.0",
4
4
  "type": "module",
5
5
  "description": "Reference touch-first browser UI for @cplieger/web-terminal-engine: a composable kernel + feature modules (tabs, activity monitor, mobile toolbar, context menu, IME, predictive echo, viewport handling) and CSS. One createTerminal() call.",
6
6
  "license": "GPL-3.0-or-later",