Skip to content

fix(web): stop animating an idle sidebar thread list - #9502

Open
ylcn91 wants to merge 2 commits into
pingdotgg:mainfrom
ylcn91:fix/sidebar-auto-animate-idle-cpu
Open

fix(web): stop animating an idle sidebar thread list#9502
ylcn91 wants to merge 2 commits into
pingdotgg:mainfrom
ylcn91:fix/sidebar-auto-animate-idle-cpu

Conversation

@ylcn91

@ylcn91 ylcn91 commented Sep 3, 2026

Copy link
Copy Markdown

What Changed

apps/web/src/components/Sidebar.tsx and apps/web/src/components/LegacySidebar.tsx: the sidebar lists attach @formkit/auto-animate only while the Motion setting is active (Settings → Appearance → Motion above 0 ms, and no prefers-reduced-motion), the same rule the panels already follow through usePanelAnimationSettings. The row slide keeps its previous cap (150 ms in the default sidebar, 180 ms in the legacy one), bounded by the slider. The ref callbacks now return a cleanup that destroys the controller, so a detached or remounted list stops polling instead of leaving its timers behind; the legacy sidebar's two WeakSet-guarded callbacks become one.

docs/user/thread-sidebar.md: the Panel motion section says thread rows follow the same setting.

This is a visible change at the default setting: thread rows no longer slide when they appear, move between sections, or leave. They snap, as the panels already do at 0 ms. Turning Motion up brings the slide back.

Why

Fixes #4693.

auto-animate 0.9.0 polls the position of the container and every direct child for as long as it is attached (index.mjs, poll): a 2 s setInterval per element, and every tick schedules an idle callback, a duration-long timer, a forced layout read and a freshly constructed IntersectionObserver. The thread list has hundreds of rows, so an idle app ran on the order of a hundred polls a second. The reporter measured 26% CPU idle and 2.3% with reduced motion forced, which is exactly the flag that makes the library skip poll. The old ref callbacks also never destroyed a controller, so each remount of the list (toggling thread search, for instance) added another full set of pollers.

The panels already define the product's motion model: immediate by default, one slider to add motion. The list animation bypassed that model and paid for itself even while nothing on screen was moving. Following the same setting removes the idle cost for every default install, gives an in-app switch instead of the OS-level workaround, and keeps the animation for people who asked for motion. While Motion is on the library still polls; dropping it entirely would be a separate decision.

Verified with web lint and typecheck. No CPU measurement was taken in a running app; the numbers above are the reporter's.

Model and harness: Claude Fable 5.1 in Claude Code.


Note

Low Risk
UI/performance change in sidebar list mounting only; default behavior becomes instant row updates with no animation until Motion is enabled.

Overview
Fixes idle CPU use from @formkit/auto-animate continuously polling large sidebar lists (#4693).

Sidebar and LegacySidebar now attach auto-animate only when Settings → Appearance → Motion panel duration is above 0 ms and reduced motion is off—the same usePanelAnimationSettings rule panels already use. At the default 0 ms, thread (and legacy project) rows snap instead of sliding; raising the slider restores list motion, capped at the existing per-sidebar durations (150 ms / 180 ms).

Ref callbacks destroy the auto-animate controller on detach so remounts (e.g. thread search) do not stack pollers; legacy sidebar merges its two WeakSet-guarded attach helpers into one shared callback.

User docs in thread-sidebar.md note that thread rows follow the panel motion setting.

Reviewed by Cursor Bugbot for commit 84e2cd1. Configure here.

Note

Stop sidebar thread list animation when panel motion is inactive

  • Makes thread and project list auto-animate conditional on the panel animation setting in both Sidebar and LegacySidebar
  • Caps list animation duration at the configured panel duration (previously fixed values like 150 ms)
  • Adds cleanup callbacks that destroy the auto-animation controller when list refs are detached
  • Updates thread-sidebar.md to document that thread rows follow the panel animation setting
  • Behavioral Change: lists now render without sliding animation when panel motion is off or under reduced motion; previously they animated regardless of the setting

Macroscope summarized 9a1553a.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Sep 3, 2026
Comment thread docs/user/thread-sidebar.md Outdated
@macroscopeapp

macroscopeapp Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This production UI change makes sidebar rows snap instead of animate under the existing default motion setting, while retaining opt-in animations and adding cleanup for polling controllers. Because it changes the user-visible product default behavior, human review is required.

You can add or adjust custom eligibility rules. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: @formkit/auto-animate position polling burns ~24% CPU permanently on an idle app

1 participant