fix(ui-kit): respect prefers-reduced-motion on Skeleton's pulse animation#7025
Conversation
…tion Every other animated ui-kit primitive (Spinner, button, tabs) pairs its animation with motion-reduce:animate-none; Skeleton was the one loading-state component in that family that didn't, despite state-views.tsx's own doc comment claiming the whole family respects prefers-reduced-motion.
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-17 18:34:32 UTC
Review summary Nits — 2 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. 🟩 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-kit/src/components/skeleton.tsx'sSkeletonusedanimate-pulsewith nomotion-reduce:animate-nonecompanion class, unlike every other animated primitive in the kit (Spinner,button.tsx,tabs.tsx).state-views.tsx's own doc comment claims "All animations respect prefers-reduced-motion" for the loading-state family, and directs callers toSkeletonfor content-shaped placeholders — makingSkeletonthe one component that didn't actually honor that claim.motion-reduce:animate-nonetoSkeleton's className, matching the existing convention exactly. No change to base styling or prop passthrough.Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Closes #7016
Validation
git diff --checknpm run actionlint(backend-only check; this PR only touchespackages/loopover-ui-kit+ a test inapps/loopover-ui)npm run typecheck(vianpm run ui:typecheck, the UI-scoped equivalent — includes theui:kit:buildstep)npm run test:coverage(backend-only;packages/loopover-ui-kithas no standalone test runner — see Notes)npm run test:workers/npm run build:mcp/npm run test:mcp-pack(not applicable to this UI-kit-only change)npm run ui:openapi:check(no API/schema changes)npm run ui:lint— 0 errorsnpm run ui:typecheck— cleannpm --workspace @loopover/ui run test src/components/site/skeleton-reduced-motion.test.tsx— 2/2 passingnpm audit --audit-level=moderate(no dependency changes)If any required check was skipped, explain why:
packages/loopover-ui-kithas notestscript or vitest config of its own (confirmed via itspackage.json), so ui-kit components are exercised throughapps/loopover-ui's test runner, importing directly from@loopover/ui-kit/components/...— the new regression test follows that same pattern (mirrors howstate-views.tsx's ported components are consumed/tested).npm run test:workers, the MCP packaging checks, andactionlinthave no surface to exercise for a one-class CSS change to a shared UI primitive.Safety
UI Evidencesection below with JPG/JPEG or PNG screenshots. (N/A —prefers-reduced-motiononly changes animation behavior under a media-query condition a static screenshot can't show; the new test asserts the actual class is present, which is the relevant, verifiable evidence for this kind of change.)Notes
packages/loopover-ui-kit/dist/is gitignored and rebuilt locally vianpm run build --workspace @loopover/ui-kit(also theui:kit:buildstep insideui:typecheck) — no generated artifact needs committing for this change.