Skip to content

13 ui-kit + 2 miner-ui animated components don't respect prefers-reduced-motion, unlike Skeleton/Button/StateBoundary/Tabs #8303

Description

@JSONbored

Context

packages/loopover-ui-kit and apps/loopover-miner-ui already have an established, working convention for respecting prefers-reduced-motion: button.tsx (motion-reduce:transition-none motion-reduce:active:scale-100), skeleton.tsx (animate-pulse ... motion-reduce:animate-none, fixed in #7016), state-views.tsx (animate-spin ... motion-reduce:animate-none, explicitly documented as "All animations respect prefers-reduced-motion"), and tabs.tsx (motion-reduce:transition-none) all pair their animation utility with a motion-reduce: variant that disables it.

A large batch of other animated components never got the same treatment and still animate unconditionally for a user with the OS-level "reduce motion" preference set:

packages/loopover-ui-kit/src/components/ (Radix data-[state=open]:animate-in / data-[state=closed]:animate-out transition families, plus two standalone animations):

  • accordion.tsxdata-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down
  • alert-dialog.tsx — overlay fade + content zoom/fade
  • context-menu.tsx — content zoom/fade/slide (2 call sites: ContextMenuContent, ContextMenuSubContent)
  • dialog.tsx — overlay fade + content zoom/fade
  • dropdown-menu.tsx — content zoom/fade/slide (2 call sites: DropdownMenuContent, DropdownMenuSubContent)
  • hover-card.tsx — content zoom/fade/slide
  • input-otp.tsxanimate-caret-blink on the fake caret
  • menubar.tsx — content zoom/fade/slide (2 call sites: MenubarContent, MenubarSubContent)
  • navigation-menu.tsx — viewport + indicator + content transitions (3 call sites)
  • popover.tsx — content zoom/fade/slide
  • select.tsx — content zoom/fade/slide
  • sheet.tsx — overlay fade + content slide
  • tooltip.tsx — content zoom/fade/slide

apps/loopover-miner-ui/src/components/:

  • streaming-text.tsx — the trailing cursor's animate-pulse
  • chat/typing-indicator.tsx — the three animate-bounce dots

None of these 15 files pair their animate-* utility with a motion-reduce: variant, so a user who has set "reduce motion" at the OS level still gets full fade/zoom/slide/bounce/blink/caret animation from every menu, dialog, tooltip, popover, and chat affordance in this app — exactly the class of bug #7016 already fixed for Skeleton and #7015 fixed for AccordionTrigger's missing focus ring (same "unlike every other X in ui-kit" shape).

Requirements

  • For every animate-in / animate-out / animate-accordion-up / animate-accordion-down / animate-caret-blink / animate-pulse / animate-bounce class list identified above, add the matching motion-reduce: variant that disables the animation (motion-reduce:animate-none for a plain animation utility; for the Radix animate-in/animate-out compound utility, disable it the same way skeleton.tsx/state-views.tsx already do — do not invent a different mechanism).
  • Do not change any non-motion-related class (color, spacing, sizing) on these lines — this is a targeted motion-reduce: addition only, not a restyle.
  • Do not add a new shared "animated" wrapper/abstraction — apply the fix inline at each call site, mirroring skeleton.tsx/button.tsx/tabs.tsx's existing pattern exactly.
  • Every file listed above must be touched; a PR that fixes only a subset of the 15 files does not resolve this issue.

Deliverables

  • motion-reduce: variants added to all 13 packages/loopover-ui-kit/src/components/*.tsx files listed in Context
  • motion-reduce: variants added to apps/loopover-miner-ui/src/components/streaming-text.tsx and apps/loopover-miner-ui/src/components/chat/typing-indicator.tsx
  • A regression test (or a small set of them) asserting at least one previously-unguarded animation utility now carries its motion-reduce: counterpart — e.g. a class-list assertion on rendered output for one Radix content component and for TypingIndicator, following the pattern state-views.test.tsx or theme-toggle.test.tsx already use for class-list assertions

Test Coverage Requirements

packages/loopover-ui-kit is not in the root vitest.config.ts's coverage.include and is not Codecov-gated (see packages/loopover-ui-kit/vitest.config.ts's own comment: "the acceptance signal is that this suite runs and passes, not a percentage") — add tests there, but Codecov's patch gate will not enforce them.

apps/loopover-miner-ui is excluded from the root Codecov config (codecov.yml's ignore: - "apps/**") but has its own local vitest coverage floor enforced via apps/loopover-miner-ui/vitest.config.ts's coverage.thresholds (currently 85% statements / 85% branches / 75% functions / 85% lines, checked by npm test in that workspace) — a PR touching streaming-text.tsx / typing-indicator.tsx must not regress that local floor, and should add assertions for the new motion-reduce: classes to streaming-text.test.tsx / a typing-indicator.test.tsx (new file — none exists today for this component).

Expected Outcome

Every animated ui-kit/miner-ui component listed above stops animating when the OS "reduce motion" preference is set, matching the accessibility guarantee state-views.tsx already documents for its own animations and that skeleton.tsx/button.tsx/tabs.tsx already provide.

Links & Resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is neededvisualUI/web visual work — owner-led, NOT for Gittensor contributors (extensions excepted)

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions