Skip to main content

4 posts tagged with "window"

View All Tags

Window Titlebar Mechanics Update (March 2026)

· 2 min read

@wonderlandlabs-pixi-ux/window now uses a simpler and more explicit titlebar mechanics model.

Counter-scale is now an explicit inner layer

CounterScalingTitlebar no longer rewrites the titlebarContentRenderer(...) contract.

Instead, it creates a first child inside the titlebar contentContainer labeled counter-scale.

  • contentContainer remains the public renderer input.
  • Renderers that want zoom-independent titlebar content should resolve contentContainer.getChildByLabel('counter-scale').
  • Standard titlebar content can still render directly into contentContainer.

This keeps TickerForest responsibilities unchanged and avoids "magic" callback geometry.

Stock titlebar renderers follow the same rule

The built-in stock titlebar renderer now checks for the counter-scale child and writes into it when present.

That means:

  • default titlebars still work with no extra setup
  • counter-scaled titlebars keep text and controls visually stable under zoom
  • custom renderers can opt into the same behavior explicitly

Hover titlebars now use a shared over/out stream

onHover titlebars no longer rely on independent body/titlebar timers.

The current behavior is:

  • pointerover on either the body or the titlebar shows the titlebar immediately
  • pointerout from either region starts a delayed unhover
  • a new pointerover from either region cancels the pending unhover

This gives a single hover session across both regions, which makes it much easier to move from body to titlebar without flicker.

What did not change

This update does not include the larger layout refactor discussed later for treating the body rect as the canonical window rect and rendering the titlebar upward from the window origin.

The changes in this update are limited to:

  • explicit counter-scale layering
  • stock renderer alignment with that layering
  • shared hover mechanics for hover-only titlebars

Practical renderer pattern

titlebarContentRenderer: ({ contentContainer }) => {
const counterScale = contentContainer.getChildByLabel('counter-scale') as Container | null;
const target = counterScale ?? contentContainer;

// upsert titlebar controls into target
}

That pattern keeps the renderer honest: the renderer chooses the layer it wants to write into instead of receiving altered layout inputs.

Forestry Pixi UX 1.2 Release Notes

· 2 min read

1.2.x standardizes drag behavior across the package set by moving to @wonderlandlabs-pixi-ux/observe-drag. 1.2.1 follows with a ticker compatibility fix and coordinated package version bumps.

Highlights

  • Added dragObserverFactory in @wonderlandlabs-pixi-ux/observe-drag with:
    • module-level singleton pointer lock by default
    • optional custom activePointer$ injection at factory creation
    • configurable inactivity failsafe (abortTime, 0 disables)
    • optional drag render throttle via renderThrottleMs (default 30ms)
  • Migrated window dragging to observer-based drag subscriptions coordinated through WindowsManager.
  • Kept compatibility aliases where needed (observeDrag, dragTargetDecorator) while moving new usage toward dragObserverFactory + dragDecorator.

Deprecations

  • @wonderlandlabs-pixi-ux/drag is now deprecated for 1.2.x.
    • Migration target: @wonderlandlabs-pixi-ux/observe-drag.
  • trackDrag is no longer exported from @wonderlandlabs-pixi-ux/resizer.
    • Legacy implementation remains under _deprecated internally, but public API consumers should migrate to observer-based drag flows.

Migration Direction

For direct container dragging, use dragDecorator() with dragObserverFactory.

Prefer:

import dragObserverFactory, {dragDecorator} from '@wonderlandlabs-pixi-ux/observe-drag';

const observeDown = dragObserverFactory({
stage: app.stage,
app,
renderThrottleMs: 30,
});

const subscription = observeDown(target, dragDecorator(), {
dragTarget: container,
abortTime: 1000,
});

Over legacy DragStore or trackDrag entrypoint usage.

More advanced side effects can be managed with custom hooks: { onStart, onMove, onUp, onBlocked, onError }.

1.2.1 Patch

1.2.1 includes a ticker-forest fix for environments that provide minimal ticker mocks (for example, tests with addOnce/remove but without add/remove):

  • Scale observer binding now validates ticker capabilities before subscribing.
  • This prevents unhandled binding.ticker.add is not a function errors.

To keep dependency metadata aligned, the primary ticker consumers were also bumped to 1.2.1:

  • @wonderlandlabs-pixi-ux/button
  • @wonderlandlabs-pixi-ux/caption
  • @wonderlandlabs-pixi-ux/grid
  • @wonderlandlabs-pixi-ux/resizer
  • @wonderlandlabs-pixi-ux/toolbar
  • @wonderlandlabs-pixi-ux/window

Window State-First Content Renderers (March 2026)

· One min read

@wonderlandlabs-pixi-ux/window now documents a clear state-first pattern for runtime content updates in windows and titlebars.

For dynamic content (toolbar actions, async updates, external events), use this flow:

  1. Mutate window/titlebar state (including custom fields).
  2. Request refresh by calling dirty() on the relevant store.
  3. Upsert display objects from windowContentRenderer and/or titlebarContentRenderer.

Why this matters

  • Avoids Pixi artifacts from direct display-list mutation outside the refresh/ticker path.
  • Coalesces multiple state changes between ticks into one final render snapshot.
  • Prevents unnecessary add/remove churn when intermediate states cancel out before render.

Refresh-cycle timing

  • windowContentRenderer runs during WindowStore.resolve() via content refresh.
  • titlebarContentRenderer runs during TitlebarStore.resolve().

This keeps content generation deterministic and aligned with the rest of the monorepo rendering model.

Window Drag/Resize + Validator Source Fixes (March 2026)

· One min read

Today we addressed a group of related issues across drag, resizer, window, and the package-validator app:

  • Fixed zoom/scaling delta mismatches for drag + resize interactions by moving pointer-delta math into the correct local coordinate space.
  • Updated resizer drag flow so drag-phase transforms/snapping are committed to current rect state during drag, which keeps handles aligned with snapped geometry before release.
  • Updated window-to-resizer syncing so handle positions follow full window rect changes (x, y, width, height) and use the current window rect for external repositioning.
  • Added validator heartbeat coverage for:
    • scaled drag behavior
    • drag-phase snapping behavior
    • window handle updates during snap drag and external window movement
  • Fixed validator source separation so published mode does not accidentally resolve nested imports back to workspace packages.

Result: published and workspace routes now show meaningful behavioral differences when package versions differ, and interaction fidelity under zoom/scale is consistent.