Skip to content

Runtime status spinner ignores reduced motion and keeps rendering offscreen #3921

Description

@mteam88

Summary

With macOS Reduce Motion enabled, a running thread's sidebar status icon still uses the spin animation. Collapsing the sidebar moves that spinner offscreen but leaves it mounted and running; in a live thread this accounted for about 12.8% of one renderer core while offscreen. I expected reduced motion to make the status glyph static and the collapsed sidebar not to keep scheduling animation work.

Versions and environment

  • bb 0.43.0 (607df4039), self-hosted web app opened in Chrome/PWA
  • macOS 27.2 build 26B5086k on an M4 Pro MacBook Pro
  • Chrome 153.0.8010.50
  • macOS defaults read com.apple.universalaccess reduceMotion returns 1
  • Web app/server reached over Tailscale; the provider is not relevant to the rendering path
  • Current main inspected at 7c5fc63b4e5a9c15aab3ced0cd6439a5251d8d34

Steps to reproduce

  1. Enable System Settings → Accessibility → Display → Reduce motion.
  2. Open bb in Chrome and start a thread, or open a parent thread that has a running child.
  3. Confirm in the page that matchMedia("(prefers-reduced-motion: reduce)").matches is true.
  4. Inspect the runtime status SVG. Its computed style still has animation-name: spin, animation-duration: 1s, and animation-play-state: running.
  5. Collapse the bb sidebar.
  6. Inspect the same SVG again. It remains mounted and running offscreen (in my repro its bounding rect started at x = -73.48px).

The smallest repro is one visible or hidden runtime status glyph. Navigating to Settings, where this thread-list animation is not mounted, did not reproduce the renderer load.

Expected vs actual

Expected:
- prefers-reduced-motion: reduce makes the runtime status glyph static.
- Collapsing the sidebar does not leave an offscreen status animation consuming renderer time.

Actual:
- matchMedia reduce: true
- animationName: spin
- animationDuration: 1s
- animationPlayState: running
- willChange: auto
- hidden-sidebar rect.x: -73.48px

Chrome Performance.getMetrics over 8 seconds, sidebar hidden:
- TaskDuration: 1.023229 s (~12.8% of one core)
- ScriptDuration: 0.012228 s
- RecalcStyleDuration: 0.096859 s
- LayoutDuration: 0 s

Over 8 seconds, sidebar visible:
- TaskDuration: 1.615215 s (~20.2% of one core)
- ScriptDuration: 0.006387 s
- RecalcStyleDuration: 0.106363 s
- LayoutDuration: 0 s

Evidence

  • Investigation thread: https://powerspec-g728.tailb55536.ts.net:8443/projects/proj_personal/threads/thr_392smeb7sx
  • Tested prototype commit: mteam88@457ca1f
  • On current main, the runtime case applies animate-spin without a reduced-motion variant:
    case "runtime":
    return (
    <Icon
    name="Loading"
    className={cn(
    "animate-spin",
    SIDEBAR_WORKING_STATUS_COLOR_CLASS,
    iconSizeClass,
    )}
    aria-label={getThreadListIndicatorLabel(kind) ?? undefined}
    />
    );
  • I measured renderer work with Chrome DevTools Protocol Performance.getMetrics before and after an 8-second interval. I separately inspected computed CSS and the glyph's bounding rectangle in the page.
  • A local fix adds motion-reduce:animate-none to this glyph and a regression assertion. The targeted ThreadRow suite passes 80/80, as do app lint, typecheck, formatting, and a production build.

What I ruled out

  • The working shimmer is not the cause under Reduce Motion: its computed animation-name is none, consistent with Stop the working shimmer from repainting on the main thread every frame #3906.
  • This is not JavaScript or layout churn in the measured interval; script and layout times were negligible compared with total renderer task time.
  • Collapsing the sidebar is not a workaround because the spinner remains mounted offscreen and running.
  • Searches for spinner, reduced motion, prefers-reduced-motion, animate-spin, and battery CPU found no matching open issue or PR.
  • The same missing reduced-motion variant remains in current main at 7c5fc63b4e5a9c15aab3ced0cd6439a5251d8d34; I measured performance on the latest release rather than a main dev server.

Suggested priority and effort

Medium priority, low effort: this affects battery use for reduced-motion users whenever a runtime status spinner is mounted. There is no sidebar-collapse workaround, but no data is lost.

AGENT GENERATED

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-reproBug reproduced again from a clean trusted checkout; see linked reportperfuiApp shell, sidebar, composer, rendering

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions