@celestia-island/hikari 0.55.70 → 0.55.71

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@celestia-island/hikari",
3
- "version": "0.55.70",
3
+ "version": "0.55.71",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Hikari Vue 3 component library — production-grade UI components based on shittim-chest design system",
@@ -441,10 +441,9 @@
441
441
  }
442
442
 
443
443
  // ── Navigation motion (2026-09-23 user directive, round 16) ──────────
444
- // The stepper never hard-cuts: status colors crossfade, the full-mode
445
- // active halo slides between step nodes, and the window-mode cells wipe
446
- // in from the navigation side. All of it rides the family's standard
447
- // duration/ease and collapses under reduced motion.
444
+ // The stepper never hard-cuts: status colors crossfade and the window-mode
445
+ // cells wipe in from the navigation side. All of it rides the family's
446
+ // standard duration/ease and collapses under reduced motion.
448
447
 
449
448
  .hk-timeline {
450
449
  --hk-timeline-motion: 0.3s;
@@ -462,41 +461,17 @@
462
461
  border-color var(--hk-timeline-motion) var(--hk-timeline-motion-ease);
463
462
  }
464
463
 
465
- // Full mode: the active halo — a measured pill behind the active step
466
- // (the component positions it via transform/size), sliding between
467
- // nodes with the same clock. The first placement is instant (data-placed
468
- // gates the transition) so opening the sheet does not animate it.
464
+ // The full-mode active halo was removed here (2026-09-24 user directive):
465
+ // a measured pill behind the active step, sliding between nodes, which
466
+ // read as an unexplained primary blob in every wide multi-step flow and
467
+ // duplicated what the filled indicator and the label weight already say.
468
+ // Window mode never had one. The containing-block rule below stays — it is
469
+ // the timeline's anchor for any absolutely positioned consumer content, and
470
+ // the vertical rail anchors to the step rather than to this box.
469
471
  .hk-timeline[data-mode="full"]:not(.hk-scroll-pin) {
470
472
  position: relative;
471
473
  }
472
474
 
473
- .hk-timeline-halo {
474
- position: absolute;
475
- left: 0;
476
- top: 50%;
477
- translate: 0 -50%;
478
- border-radius: 999px;
479
- background: color-mix(in srgb, var(--hi-color-primary) 10%, transparent);
480
- pointer-events: none;
481
- height: 100%;
482
- box-sizing: border-box;
483
- }
484
-
485
- .hk-timeline[data-orientation="vertical"] .hk-timeline-halo {
486
- top: 0;
487
- left: 50%;
488
- translate: -50% 0;
489
- width: 100%;
490
- height: auto;
491
- }
492
-
493
- .hk-timeline-halo[data-placed] {
494
- transition:
495
- transform var(--hk-timeline-motion) var(--hk-timeline-motion-ease),
496
- width var(--hk-timeline-motion) var(--hk-timeline-motion-ease),
497
- height var(--hk-timeline-motion) var(--hk-timeline-motion-ease);
498
- }
499
-
500
475
  // Window mode: each cell's step content is keyed by its step key, so a
501
476
  // navigation remounts it — wipe in from the navigation side. data-dir is
502
477
  // absent on the very first render, so opening does not animate.
@@ -562,8 +537,4 @@ html[data-css-animations="0"] .hk-timeline[data-mode="window"][data-dir] .hk-tim
562
537
  .hk-timeline[data-mode="window"][data-dir] .hk-timeline-step {
563
538
  animation: none;
564
539
  }
565
-
566
- .hk-timeline-halo[data-placed] {
567
- transition: none;
568
- }
569
540
  }
@@ -424,36 +424,20 @@ describe("HkTimeline navigation motion (round 16)", () => {
424
424
  return { container, current };
425
425
  }
426
426
 
427
- it("positions the full-mode halo on the active step and slides it on navigation", async () => {
428
- const { container, current } = mountTimeline(4, "s1");
429
- // happy-dom has no layout engine: give the step nodes deterministic
430
- // offsets so the halo's measured transform is observable.
431
- const steps = () =>
432
- Array.from(container.querySelectorAll<HTMLElement>(".hk-timeline-step"));
433
- for (const [i, step] of steps().entries()) {
434
- Object.defineProperty(step, "offsetLeft", {
435
- configurable: true,
436
- get: () => i * 100,
437
- });
438
- Object.defineProperty(step, "offsetWidth", {
439
- configurable: true,
440
- get: () => 80,
441
- });
442
- }
443
- await nextTick();
444
- await nextTick();
445
- const halo = container.querySelector<HTMLElement>(".hk-timeline-halo");
446
- expect(halo).not.toBeNull();
447
- // Active = s1 (second node): translateX(100 - pad).
448
- expect(halo!.style.transform).toBe("translateX(94px)");
449
- expect(halo!.style.width).toBe("92px");
450
- expect(halo!.hasAttribute("data-placed")).toBe(true);
451
-
452
- current.value = "s3";
427
+ it("renders no full-mode halo behind the active step", async () => {
428
+ // The measured pill that used to slide behind the active step is gone
429
+ // (2026-09-24 user directive): in a wide multi-step flow it read as an
430
+ // unexplained primary blob, and the filled indicator plus the label
431
+ // weight already carry the active step. Pinned so a later "highlight"
432
+ // refactor cannot quietly reintroduce it.
433
+ const { container } = mountTimeline(4, "s1");
453
434
  await nextTick();
454
435
  await nextTick();
455
- // Slid to the fourth node.
456
- expect(halo!.style.transform).toBe("translateX(294px)");
436
+ expect(container.querySelector(".hk-timeline-halo")).toBeNull();
437
+ // The overlay the window mode owns is a different element and stays a
438
+ // window-mode concern — full mode draws its connectors inline.
439
+ expect(container.querySelector(".hk-timeline[data-mode='full']")).not.toBeNull();
440
+ expect(container.querySelector(".hk-timeline-links")).toBeNull();
457
441
  });
458
442
 
459
443
  it("marks the navigation direction for the window-mode wipe", async () => {
@@ -178,9 +178,8 @@ export default defineComponent({
178
178
 
179
179
  // ── Navigation motion (2026-09-23 user directive, round 16) ──────
180
180
  // The stepper must not hard-cut between steps: the status colors
181
- // crossfade (stylesheet), the window-mode cells wipe in from the
182
- // navigation side (keyed remount + data-dir), and the full-mode
183
- // active halo slides between step nodes (measured transform).
181
+ // crossfade (stylesheet) and the window-mode cells wipe in from the
182
+ // navigation side (keyed remount + data-dir).
184
183
  let prevIndex = currentIndex.value;
185
184
  /** Set once the first navigation revealed a direction; drives the
186
185
  * window-mode wipe's side via the host attribute. */
@@ -192,37 +191,11 @@ export default defineComponent({
192
191
  prevIndex = idx;
193
192
  });
194
193
 
195
- /** The sliding full-mode highlight. */
196
- const halo = ref<HTMLElement | null>(null);
197
- function positionHalo(): void {
198
- const hostEl = host.value;
199
- const haloEl = halo.value;
200
- if (!hostEl || !haloEl) return;
201
- const step = hostEl.querySelector<HTMLElement>(
202
- '.hk-timeline-step[data-status="active"]',
203
- );
204
- if (!step) return;
205
- const vertical = props.orientation === "vertical";
206
- const pad = 6;
207
- if (vertical) {
208
- haloEl.style.transform = `translateY(${Math.max(0, step.offsetTop - pad)}px)`;
209
- haloEl.style.width = "";
210
- haloEl.style.height = `${step.offsetHeight + pad * 2}px`;
211
- } else {
212
- haloEl.style.transform = `translateX(${Math.max(0, step.offsetLeft - pad)}px)`;
213
- haloEl.style.height = "";
214
- haloEl.style.width = `${step.offsetWidth + pad * 2}px`;
215
- }
216
- // The very first placement must not animate from nothing — only
217
- // subsequent moves ride the CSS transition.
218
- haloEl.setAttribute("data-placed", "");
219
- }
220
- watch(
221
- () => [props.currentKey, props.orientation] as const,
222
- () => {
223
- void nextTick(positionHalo);
224
- },
225
- );
194
+ // The sliding full-mode highlight is gone (2026-09-24 user directive).
195
+ // It read as an unexplained primary blob behind the active step in every
196
+ // multi-step flow that is wide enough to show all of them, and the
197
+ // active step is already carried by its filled indicator plus the label
198
+ // weight. Window mode never had one, so nothing replaces it there.
226
199
 
227
200
  function statusOf(idx: number): TimelineStepStatus {
228
201
  return idx < currentIndex.value
@@ -262,13 +235,11 @@ export default defineComponent({
262
235
  if (typeof ResizeObserver !== "undefined") {
263
236
  observer = new ResizeObserver(() => {
264
237
  measure();
265
- positionHalo();
266
238
  });
267
239
  if (host.value) observer.observe(host.value);
268
240
  }
269
241
  void nextTick(() => {
270
242
  measure();
271
- positionHalo();
272
243
  });
273
244
  });
274
245
 
@@ -428,7 +399,6 @@ export default defineComponent({
428
399
  data-mode="full"
429
400
  data-dir={navDir.value ?? undefined}
430
401
  >
431
- <div ref={halo} class="hk-timeline-halo" aria-hidden="true" />
432
402
  {props.steps.map((_step, idx) => {
433
403
  const isLast = idx === props.steps.length - 1;
434
404
  return renderStep(idx, { connector: !isLast, last: isLast });