Skip to content

Pause hidden status glyph animations and remove reduced-motion polling - #48

Merged
WaylandYang merged 2 commits into
deeplethe:devfrom
Floating-Y:fix/status-glyph-animation
Oct 15, 2026
Merged

WaylandYang merged 2 commits into
deeplethe:devfrom
Floating-Y:fix/status-glyph-animation

Conversation

@Floating-Y

Copy link
Copy Markdown
Contributor

Why

StatusGlyph keeps updating its SVG after leaving the viewport, and reduced-motion mode redraws the same pose every 250 ms. Pages with multiple glyphs therefore perform animation work that the reader cannot see.

What changes

  • Schedule animation frames only while the glyph intersects the viewport, the document is visible, and reduced motion is disabled. Reuse the existing pending frame when properties or unchanged visibility notifications arrive.
  • Replace reduced-motion polling with static-pose updates on property, motion-preference, and visibility changes.
  • Preserve the original animation clock and 450 ms figure transitions.
  • Cancel the pending frame, disconnect and drain the observer, and remove listeners on unmount.

Only src/components/ui/status-glyph.tsx changes. The public API, figure definitions, and dependencies are unchanged.

How it was checked

  • npm run typecheck passed.
  • Direct production build passed: node node_modules/vite/bin/vite.js build --logLevel error.
  • 26 assertions passed in a temporary local headless Chrome harness, covering StrictMode, offscreen and clipped glyphs, display: none recovery, reduced-motion changes, static-pose updates, frame reuse, transitions, and cleanup. The new property-update scheduling assertion failed against the previous implementation and passed against this version; it compares the pending frame ID and request/cancellation counts, not just the number of pending frames. The harness is local validation, not a committed test suite.
  • /dev/examples mounted 389/389 examples with 0 failures and no uncaught page errors in both dark and light themes at 1440 × 1000. StatusGlyph and TurnStatus examples and activity switching were also checked. Existing Input/Base UI console warnings remain.
  • Documentation and registry generation passed with the temporary Windows adapter described below. The generated registry's component source matches the current file; registry.json has no content changes.
  • git diff --check passed.

Windows build limitation

Unmodified npm run build does not pass on this Windows checkout (Node 22.20.0): the existing documentation parser fails at scripts/build-docs.mjs:140 with TypeError: object null is not iterable when reading CRLF Markdown. It fails before Vite runs.

For local validation, a temporary adapter normalized MDX line endings and Windows path separators in memory and invoked the installed shadcn CLI through Node instead of execFileSync("npx", ...). It was used only to generate documentation and the registry, then type checking and the direct Vite build ran normally. No adapter or build-script changes are included in this PR; this is not a claim that the standard build passed locally. The normal Linux CI pipeline remains to be verified on GitHub.

IntersectionObserver measures geometric intersection, not every form of visual occlusion. Firefox/Safari, low-end device FPS, and power consumption were not measured.

Before review

  • Every commit is signed off (git commit -s).
  • npm run typecheck passes.
  • Standard npm run build passes locally (blocked by the existing Windows limitation above).
  • /dev/examples reports 0 failed in both themes.
  • The affected examples and activity switching were checked in both themes.

@WaylandYang
WaylandYang merged commit 98fd358 into deeplethe:dev Oct 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants