Skip to content

Optimize animations for React Compiler and reduced motion#123

Merged
Gamius00 merged 4 commits into
mainfrom
react-compiler-animation-setup-ready
Jun 19, 2026
Merged

Optimize animations for React Compiler and reduced motion#123
Gamius00 merged 4 commits into
mainfrom
react-compiler-animation-setup-ready

Conversation

@FleetAdmiralJakob

@FleetAdmiralJakob FleetAdmiralJakob commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • adds pnpm check:compiler and confirms Expo's React Compiler setup across the application
  • migrates Reanimated shared values in notifications, bottom navigation, and the drag-to-start slider from direct .value access to get() and set()
  • hoists static notification exit and layout transition builders
  • replaces the analysis loader's nine independently animated native views and JavaScript timers with one SVG, one animated wrapper, and native Reanimated repeat sequences
  • respects the system reduced-motion preference in the quiz transition, analysis loader, and mascot loops
  • keeps gesture declarations natural and avoids manual memoization where React Compiler already provides it

Why

React Compiler can reduce React render work, but it does not reduce UI-thread animation work or the number of native views updated each frame. The previous analysis loader continuously transformed nine separate views and scheduled each cycle from JavaScript. Several Reanimated paths also used direct shared-value property access, which is not the Compiler-aligned API.

This change keeps the existing lightweight interaction architecture while reducing continuous loader work, improving animation cleanup and accessibility, and making shared-value access compatible with React Compiler assumptions.

User impact

  • analysis and generation loading animation performs less per-frame native work
  • notification, navigation, and slider interactions retain their existing behavior
  • continuous decorative motion stops when the device's reduced-motion preference is enabled
  • quiz transitions also respect reduced motion

Validation

  • pnpm lint
  • pnpm typecheck
  • pnpm test - 18 files, 72 tests passed
  • pnpm check:compiler - 94/94 components compiled; no incompatible libraries
  • pnpm format:check
  • pnpm exec expo export --platform android --output-dir .tmp-animation-export - production Android bundle completed successfully with 7,481 modules

Summary by CodeRabbit

  • Chores

    • Added a new developer script to run a React compiler health check.
  • Improvements

    • Enhanced reduced-motion accessibility across animations by stopping and skipping motion when the setting is enabled.
    • Improved gesture-driven and transition animations for the home slider, bottom navigation, and notifications, including smoother exits and more reliable swipe-to-delete behavior.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR systematically updates React Native Reanimated usage across multiple animation components by migrating from deprecated .value property access to the .get()/.set() API, and adding useReducedMotion support to several animation-heavy features. Changes span six files: package.json gains a compiler healthcheck script; Mascot and QuizStep add reduced-motion awareness; DragStartSlider, BottomNav, notifications, and AnalysisOrbitLoader migrate to the new Reanimated API and/or adopt reduced-motion handling.

Changes

Reanimated API migration and reduced-motion accessibility

Layer / File(s) Summary
Compiler healthcheck npm script
package.json
Adds check:compiler script that executes pnpm dlx react-compiler-healthcheck@latest alongside existing check tooling.
Reduced-motion support in simple animation components
src/components/Mascot.tsx, src/features/learning-plans/quiz-step.tsx
Imports useReducedMotion and reworks useEffect animation lifecycles to stop any prior animations, reset animated values, and bypass timing animations when reduced motion is enabled; updates dependency arrays to react to preference changes.
Bottom-nav shared-value API migration
src/components/bottom-nav.tsx
AnimatedTabIcon and BottomNav components migrate focusProgress and indicatorPosition from direct .value reads to .get() reads and .set(withSpring(...)) writes inside useEffect and animated styles.
DragStartSlider gesture worklet API migration
src/app/(app)/home.tsx
Pan gesture worklet updates shared-value handling: uses .set() for resetting and clamping values, .get() for guards and animated reads, and scheduleOnRN for cross-thread callbacks; ensures animations complete before triggering onComplete.
Notification animations refactor: constants, API migration, and swipe gesture
src/app/notifications.tsx
Introduces NOTIFICATION_EXIT and NOTIFICATION_LAYOUT animation constants; migrates category indicator and label animations to .get() reads; refactors swipe-to-delete gesture to guard with isDeleting.get() and animate via .set(); updates delete-background threshold math to use .get() for shared values.
AnalysisOrbitLoader major refactor: imports, constants, animation logic, and SVG rendering
src/features/learning-plans/learning-plan-ui.tsx
Replaces timer-based animation cycle with Reanimated's withRepeat/withSequence/withDelay pattern; computes petal positions via ANALYSIS_ORBIT_PETALS array; adds useReducedMotion handling and explicit animation cancellation on unmount; switches rendered output from Animated.View petals to SVG Circle elements using precomputed coordinates.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Dayova/dayova-mvp#117: Updates to bottom-nav shared values and animation patterns are directly related to prior work on the same components and animation APIs.

Poem

🐰 With bounces smooth and motions kind,
We migrated .value from our mind!
Get and set now pave the way,
No more jitter, hip hooray!
Reduced motion? We respect your choice—
Accessible animations rejoice! 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objectives of the pull request—optimizing animations for React Compiler compatibility and implementing reduced motion support—which are reflected across all file changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch react-compiler-animation-setup-ready

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
package.json (1)

28-28: ⚡ Quick win

Pin react-compiler-healthcheck to a specific version instead of @latest.

Using @latest creates a floating dependency that can introduce non-deterministic behavior in CI/CD and make it difficult to reproduce issues. All other dependencies in this file use pinned or constrained semver ranges (exact, ^, or ~). For a tool that verifies compiler compatibility—where consistency is critical—pinning to a specific version ensures reproducible builds and prevents unexpected breaking changes.

Consider replacing @latest with a pinned version (e.g., react-compiler-healthcheck@0.0.1) or at least a tighter range like ^0.0.1.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 28, The react-compiler-healthcheck dependency in the
check:compiler script uses `@latest` which creates a floating dependency, causing
non-deterministic behavior and making CI/CD builds non-reproducible. Replace
`@latest` with either a pinned version (e.g., `@0.0.1`) or a constrained semver
range (e.g., @^0.0.1) to match the pattern used by other dependencies in the
file and ensure consistency and reproducibility in builds.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package.json`:
- Line 28: The check:compiler script references the deprecated
react-compiler-healthcheck@latest tool which is no longer available on npm and
has been removed from official React documentation. Remove the check:compiler
script from package.json entirely, as the modern approach uses
eslint-plugin-react-compiler for analysis in the editor and verification through
React DevTools or build output inspection, rather than a dedicated CLI
healthcheck tool. If you want to keep static analysis, install and configure
eslint-plugin-react-compiler in your ESLint configuration instead.

---

Nitpick comments:
In `@package.json`:
- Line 28: The react-compiler-healthcheck dependency in the check:compiler
script uses `@latest` which creates a floating dependency, causing
non-deterministic behavior and making CI/CD builds non-reproducible. Replace
`@latest` with either a pinned version (e.g., `@0.0.1`) or a constrained semver
range (e.g., @^0.0.1) to match the pattern used by other dependencies in the
file and ensure consistency and reproducibility in builds.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cc61e177-dae6-4a6e-b24a-110c09f4541c

📥 Commits

Reviewing files that changed from the base of the PR and between 8113567 and a71ff44.

📒 Files selected for processing (2)
  • package.json
  • src/features/learning-plans/quiz-step.tsx

Comment thread package.json
@FleetAdmiralJakob
FleetAdmiralJakob force-pushed the react-compiler-animation-setup-ready branch from e8ad935 to a71ff44 Compare June 14, 2026 16:50
@FleetAdmiralJakob FleetAdmiralJakob changed the title Improve compiler-aware animation setup Support reduced motion in quiz animations and add compiler healthcheck Jun 14, 2026

Copy link
Copy Markdown
Collaborator Author

Verified the review findings. Updated the PR title. Kept the healthcheck command because it remains documented for Expo, is available on npm, and the repo already has compiler lint rules configured. Kept @latest because this is a manual diagnostic, not CI. Skipped docstrings as unrelated noise. No code changes were needed.

@FleetAdmiralJakob FleetAdmiralJakob changed the title Support reduced motion in quiz animations and add compiler healthcheck Optimize animations for React Compiler and reduced motion Jun 15, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/notifications.tsx`:
- Around line 68-71: Animations are currently applied unconditionally without
respecting the user's reduced-motion preferences. Add the `useReducedMotion()`
hook at the top of the component to detect when reduced motion is enabled, then
conditionally gate all animation transitions. For the `NOTIFICATION_EXIT` fade
animation and `NOTIFICATION_LAYOUT` spring animation constants, apply them only
when reduced motion is disabled (when the hook returns false). Similarly, update
all `withTiming` and `withSpring` animation calls in the tab timing and swipe
delete handlers to skip animations when reduced motion is enabled, snapping to
the final state immediately instead. Finally, conditionally apply the `exiting`
and `layout` props on `Animated.View` only when reduced motion is not enabled,
ensuring a seamless experience for all users.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dca9fd92-f0ca-4f58-afe2-69bcb2cb5444

📥 Commits

Reviewing files that changed from the base of the PR and between a71ff44 and 8e14c90.

📒 Files selected for processing (5)
  • src/app/(app)/home.tsx
  • src/app/notifications.tsx
  • src/components/Mascot.tsx
  • src/components/bottom-nav.tsx
  • src/features/learning-plans/learning-plan-ui.tsx

Comment thread src/app/notifications.tsx
@FleetAdmiralJakob

Copy link
Copy Markdown
Collaborator Author

@Gamius00 Ready to merge

@Gamius00
Gamius00 merged commit cc6f077 into main Jun 19, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants