@cplieger/web-terminal-ui 5.3.1 → 5.4.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
@@ -425,4 +425,4 @@ This project was built with AI-assisted tooling using [Claude](https://claude.co
425
425
 
426
426
  ## License
427
427
 
428
- GPL-3.0-or-later. See [LICENSE](LICENSE).
428
+ MPL-2.0. See [LICENSE](LICENSE).
package/css/01-scope.css CHANGED
@@ -15,6 +15,16 @@
15
15
  .wt-root.wt-viewport {
16
16
  position: fixed;
17
17
  inset: 0;
18
+ /* Clip like the container mode below, so the two layout modes agree. Inert
19
+ today: the root's box IS the viewport here and page.css already hides
20
+ document overflow, so nothing can currently paint outside it, and
21
+ position:fixed descendants escape a clip regardless. It exists so the
22
+ asymmetry cannot be mistaken for a deliberate difference, and so a future
23
+ transform on .term (see docs/tab-switch-repaint.md) is bounded by a
24
+ declaration rather than by the viewport happening to coincide with the box.
25
+ overflow:clip specifically, not hidden: no scroll container, no block
26
+ formatting context, nothing programmatically scrollable. */
27
+ overflow: clip;
18
28
  }
19
29
 
20
30
  .wt-root.wt-container {
package/css/30-tabs.css CHANGED
@@ -495,9 +495,81 @@
495
495
  }
496
496
  }
497
497
 
498
- /* The tab being dragged (reorder) dims while it moves. */
499
- :where(.wt-root) .wt-tab-dragging {
500
- opacity: 0.5;
498
+ /* ===== Pending drop edge (tabs feature, desktop drag) =====
499
+ The exact boundary the dragged tab will be inserted at, marked while the hold runs
500
+ and filling from nothing to full over the hold's own duration (the tabs feature
501
+ sets the duration inline from REORDER_DWELL_MS, so the bar and the timer cannot
502
+ drift apart).
503
+
504
+ It rides the neighbouring chip: the leading edge of the chip being pushed aside,
505
+ or the trailing edge of the last chip when the tab is heading past the end of the
506
+ strip (.wt-tab-dwell-end). The chip is already position: relative for its progress
507
+ bar, and its overflow clip keeps the rail inside the same rounded padding box.
508
+
509
+ 3px of solid accent rather than a dashed treatment: the dashed vocabulary belongs
510
+ to the SLOT, which is a destination that has been decided. This is a boundary
511
+ still being chosen, so it reads as a caret. inset-block keeps it clear of the
512
+ chip's rounded corners without needing its own radius arithmetic. */
513
+ :where(.wt-root) .wt-tab-dwell {
514
+ position: absolute;
515
+ inset-block: var(--sp-1);
516
+ inset-inline-start: 0;
517
+ width: 3px;
518
+ border-radius: var(--radius-sm);
519
+ background: var(--accent);
520
+ /* Grows upward like a gauge. The feature writes scaleY inline; a transform on this
521
+ element cannot collide with the chip's own animations because it is a separate
522
+ element, which is the whole reason the rail is not a pseudo-element on the chip. */
523
+ transform-origin: bottom;
524
+ pointer-events: none;
525
+ }
526
+
527
+ :where(.wt-root) .wt-tab-dwell-end {
528
+ inset-inline: auto 0;
529
+ }
530
+
531
+ /* ===== Reorder drop slot (tabs feature, desktop drag) =====
532
+ The dragged chip stays in the strip's flow for the whole gesture and renders as
533
+ the SLOT it will land in: an empty dashed outline in the accent over a faint
534
+ accent wash. It used to be a dimmed copy of the tab, and with a solid drag
535
+ image already following the pointer that put three tab-shaped things on screen
536
+ at once — the slot it left, the chip it hovered, and the copy under the
537
+ pointer — none of which read as the answer to "where will this land". One
538
+ solid thing under the pointer, one hollow thing where it will land.
539
+
540
+ Staying in the flow is what keeps the geometry honest: the slot IS the gap,
541
+ exactly one chip wide, so nothing has to synthesise a placeholder box or agree
542
+ with the chip about how wide a tab is. It is also what lets the reorder animate
543
+ at all — the strip's other chips slide around a real box (index.ts, commitSlot).
544
+
545
+ The outline is the chip's OWN reserved border switched to `dashed`: every tab
546
+ carries a transparent 1px border for exactly this kind of toggle (see .wt-tab),
547
+ so the treatment costs no layout and lands on the same --radius-inner corners
548
+ as every other chip state.
549
+
550
+ Scoped through .wt-tab-scroll on purpose, and it is not decoration. A drag
551
+ reorder exists only inside the desktop scroller, and the extra compound is what
552
+ carries the rule past the two rungs it has to out-rank without any of the usual
553
+ tricks: the press rung (.wt-tab:not(.wt-tab-active):active, which a mousedown
554
+ that starts a drag leaves applied for the whole gesture in Blink, so the slot
555
+ would otherwise paint as a pressed tab under the dashes), and the per-status
556
+ dot rules far below, which would otherwise keep the status dot lit inside an
557
+ outline that is meant to be empty. */
558
+ :where(.wt-root) .wt-tab-scroll .wt-tab.wt-tab-dragging {
559
+ background: color-mix(in oklch, var(--accent) 12%, transparent);
560
+ border-color: color-mix(in oklch, var(--accent) 60%, transparent);
561
+ border-style: dashed;
562
+ }
563
+
564
+ /* Nothing inside the slot: the outline is the whole message, and the tab's
565
+ identity is already in the drag image under the pointer. Fading the CONTENT
566
+ rather than the chip is what keeps the dashes at full strength — an opacity on
567
+ the chip dimmed the outline along with everything else, which is exactly how
568
+ the old treatment ended up reading as a faded tab rather than as a gap. The dot
569
+ is included by inheritance: opacity multiplies onto its glow and ripple
570
+ pseudo-elements, so one declaration silences the whole dot. */
571
+ :where(.wt-root) .wt-tab-scroll .wt-tab.wt-tab-dragging > * {
572
+ opacity: 0;
501
573
  }
502
574
 
503
575
  /* ===== Inline rename (tabs feature) =====
@@ -27,15 +27,48 @@
27
27
  display var(--dur-standard) allow-discrete;
28
28
  }
29
29
 
30
- /* Tab chrome micro-transitions (hover/active color shifts). */
30
+ /* Tab chrome micro-transitions (hover/active colour shifts, and a chip's hand-off
31
+ into the reorder drop slot). border-color rides along because the slot IS a
32
+ border-colour change plus a dashed style (30-tabs.css): without it the chip
33
+ snapped from tab to outline in a single frame, which is the same instant
34
+ rearrangement the reorder preview exists to remove. The dash pattern itself still
35
+ appears at once — border-style does not interpolate — so the slot reads as an
36
+ outline drawing itself in rather than as a tab bleaching out. */
31
37
  :where(.wt-root.wt-animate) .wt-tab,
32
38
  :where(.wt-root.wt-animate) .wt-tab-close,
33
39
  :where(.wt-root.wt-animate) .wt-tab-new {
34
40
  transition:
35
41
  background-color var(--dur-micro) var(--ease-standard),
42
+ border-color var(--dur-micro) var(--ease-standard),
36
43
  color var(--dur-micro) var(--ease-standard);
37
44
  }
38
45
 
46
+ /* The chip's content dissolves as it becomes the drop slot, and comes back when the
47
+ drag ends (30-tabs.css fades every child to nothing). One rule on the children,
48
+ not four per-part rules: the label, the status dot, the progress bar and the close
49
+ all leave together, because they leave for one reason. */
50
+ :where(.wt-root.wt-animate) .wt-tab > * {
51
+ transition: opacity var(--dur-micro) var(--ease-standard);
52
+ }
53
+
54
+ /* The drop slot fades in at each position the reorder preview commits it to
55
+ (index.ts, flashSlot). The chips it displaces SLIDE there — a JS FLIP, because the
56
+ distance is only known at commit time — while the slot itself deliberately does
57
+ not travel: a hole crossing the strip alongside the solid drag image the pointer
58
+ is already carrying is two things moving at once, which is what made the old
59
+ instant reorder unreadable. It appears where the strip has just opened, which is
60
+ the frame that says the reorder took. */
61
+ :where(.wt-root.wt-animate) .wt-tab-slotted {
62
+ animation: wt-slot-in var(--dur-enter) var(--ease-enter);
63
+ }
64
+
65
+ @keyframes wt-slot-in {
66
+ from {
67
+ opacity: 0;
68
+ transform: scale(0.97);
69
+ }
70
+ }
71
+
39
72
  /* New tab enters with a fade + scale-in. Only runtime-added tabs get
40
73
  .wt-tab-enter (the tabs feature's `started` gate). A closing tab is removed
41
74
  immediately with no exit animation, so the strip reflows in one frame (a
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@cplieger/web-terminal-ui",
3
- "version": "5.3.1",
3
+ "version": "5.4.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
- "license": "GPL-3.0-or-later",
6
+ "license": "MPL-2.0",
7
7
  "exports": {
8
8
  ".": "./src/index.ts",
9
9
  "./startup-copy": "./src/kernel/startup-copy.ts",
@@ -40,7 +40,7 @@
40
40
  "verify": "bash scripts/verify.sh"
41
41
  },
42
42
  "peerDependencies": {
43
- "@cplieger/web-terminal-engine": "^3.7.0"
43
+ "@cplieger/web-terminal-engine": "^3.10.0"
44
44
  },
45
45
  "overrides": {
46
46
  "qs": "^6.15.2"