fix(ui-kit): respect prefers-reduced-motion across animated ui-kit and miner-ui components - #8360
Conversation
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
…d miner-ui components 13 ui-kit components (accordion, alert-dialog, context-menu, dialog, dropdown-menu, hover-card, input-otp, menubar, navigation-menu, popover, select, sheet, tooltip) and 2 miner-ui components (streaming-text, chat/typing-indicator) animated unconditionally, so a user with the OS reduce-motion preference still got full fade/zoom/slide/bounce/blink/caret motion. Pairs each animate-* utility with motion-reduce:animate-none, the same guard skeleton.tsx/state-views.tsx/button.tsx/tabs.tsx already apply, inline at each call site (no new abstraction). Adds regression tests asserting the guard on a Radix content component (AccordionContent) and on TypingIndicator, plus a class-list assertion on StreamingText's caret. Closes JSONbored#8303
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-24 11:08:13 UTC
Review summary Nits — 5 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. Visual preview
Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy. Scroll preview
A short scroll-through clip (desktop) — click either thumbnail to open the full animation. Evidence for scroll-linked behavior a single screenshot can't show. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|



Summary
packages/loopover-ui-kitcomponents (accordion,alert-dialog,context-menu[2 call sites],dialog,dropdown-menu[2],hover-card,input-otp,menubar[2],navigation-menu[3],popover,select,sheet,tooltip) and 2apps/loopover-miner-uicomponents (streaming-text,chat/typing-indicator[3 dots]) paired theiranimate-*utilities (Radixdata-[state=…]:animate-in/animate-out,animate-accordion-up/down,animate-caret-blink,animate-pulse,animate-bounce) with nomotion-reduce:variant — so a user with the OS "reduce motion" preference still got full fade/zoom/slide/bounce/blink/caret animation from every menu, dialog, tooltip, popover, and chat affordance.motion-reduce:animate-noneat each of those 25 call sites — the exact guardskeleton.tsx(animate-pulse motion-reduce:animate-none, Skeleton's animate-pulse doesn't respect prefers-reduced-motion, unlike every other animated ui-kit primitive #7016),state-views.tsx(Spinner'sanimate-spin motion-reduce:animate-none), andapps/loopover-ui's ownsite-header.tsx(animate-in … motion-reduce:animate-none) already use — applied inline at each call site, with no new shared "animated" wrapper/abstraction and no non-motion class touched.AccordionContent, whoseanimate-accordion-*utilities the issue calls out) and onTypingIndicator's three dots (newtyping-indicator.test.tsx), plus amotion-reduce:animate-noneassertion added toStreamingText's existing caret test — following the class-list-assertion conventionstate-views.test.tsx/theme-toggle.test.tsxuse.Closes #8303
Scope
type(scope): short summaryConventional Commit format, for examplefix(api): restore profile access checks.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Closes #123) — a linked open issue is required for every contributor PR.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coveragelocally;codecov/patchrequires ≥99% coverage of the lines AND branches you changed (aim for 100% on your diff so CI variance does not fail near the threshold). Global coverage is a non-blocking trend with a loose 90% backstop, not the gate.npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderateIf any required check was skipped, explain why:
packages/loopover-ui-kit/**andapps/loopover-miner-ui/**(class-list additions + tests).packages/loopover-ui-kitis not in the rootvitest.config.tscoverage.includeand is not Codecov-gated, andapps/loopover-miner-uiis Codecov-ignored (codecov.ymlignore: - "apps/**") but has its own local vitest coverage floor (85/85/75/85). So roottest:coverage/codecov/patch,actionlint,test:workers,build:mcp/test:mcp-pack,ui:openapi:check, andnpm auditare not exercised by this change. Verified locally:packages/loopover-ui-kitnpm test(incl. newaccordion.test.tsx),apps/loopover-miner-uinpm testunder its coverage floor (newtyping-indicator.test.tsxadds coverage for a previously-untested component; the pre-existingchat-rail.test.tsxmobile-sheet case that depends on a jsdommatchMediamobile match is unrelated to and untouched by this diff), plustsc --noEmitandprettier --checkon every touched file.Safety
UI Evidencesection below with JPG/JPEG or PNG screenshots arranged as organized, captioned, clickable thumbnails. SVG screenshots are not used as review evidence. Review-only screenshots or recordings are not committed to the repository.UI Evidence
This is an accessibility fix with no at-rest visual difference — the rendered output under the default (
no-preference) motion setting is byte-for-byte unchanged. The only behavioral change appears under the OS "reduce motion" preference (@media (prefers-reduced-motion: reduce)):motion-reduce:animate-none), while the default-motion experience is completely unchanged.Because the difference is gated entirely behind a
prefers-reduced-motionmedia query and produces no default-state pixel change, the machine-checkable evidence is the class-list regression tests in this PR (accordion.test.tsxfor a Radix content component,typing-indicator.test.tsxfor the chat dots, and the added assertion instreaming-text.test.tsx), each asserting themotion-reduce:animate-noneguard now sits alongside the animation utility — the same class-list-assertion evidence conventionstate-views.test.tsx/theme-toggle.test.tsxuse, and the same shape the sibling accessibility fixes #7015/#7016 were verified with.Notes
motion-reduce:animate-noneis applied verbatim per the issue's required pattern ("do not invent a different mechanism") — the identical utilityskeleton.tsx/state-views.tsxandsite-header.tsxalready ship — inline at every call site, never as a new wrapper. Every one of the 15 files listed in the issue is touched.