Skip to content

Add reduced motion override feature#17

Merged
tyl3r-ch merged 2 commits intomainfrom
v623
Apr 15, 2026
Merged

Add reduced motion override feature#17
tyl3r-ch merged 2 commits intomainfrom
v623

Conversation

@tyl3r-ch
Copy link
Copy Markdown
Contributor

@tyl3r-ch tyl3r-ch commented Apr 15, 2026

Summary by CodeRabbit

  • New Features

    • Added a Dashboard "Reduced Motion" setting with three options: Browser setting (labeled “Browser Einstellung” in German), Always, or Never; preference persists and is applied app-wide.
  • Bug Fixes

    • Consistent reduced-motion behavior across dialogs, tooltips, toasts, cards, reveals, charts, and after reload, reset, import/export, and backups.
  • Tests

    • Added targeted frontend, API, integration, and E2E tests validating the new motion setting, persistence, reset, and import/export roundtrips.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dd7c01a2-f75e-433e-a491-e8345eef14e3

📥 Commits

Reviewing files that changed from the base of the PR and between c14876e and ec8d83c.

📒 Files selected for processing (5)
  • src/lib/motion.tsx
  • src/locales/de/common.json
  • tests/frontend/motion-accessibility.test.tsx
  • tests/frontend/settings-modal.test.tsx
  • tests/unit/api.test.ts
✅ Files skipped from review due to trivial changes (1)
  • src/locales/de/common.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/unit/api.test.ts

📝 Walkthrough

Walkthrough

Adds a persisted app-wide "Reduced Motion" preference (system|always|never), centralizes motion handling via a new AppMotionProvider, flows the setting through bootstrap, API, import/export, reset, and settings UI, and updates tests and i18n to cover the behavior.

Changes

Cohort / File(s) Summary
Type System & API
src/types/index.ts, src/lib/api.ts
New ReducedMotionPreference type; AppSettings and UpdateSettingsRequest extended to include reducedMotionPreference.
Backend Settings & Persistence
server.js
Added reducedMotionPreference: 'system' to defaults and normalization (normalizeReducedMotionPreference) integrated into settings normalization and updates.
App-level Motion Provider
src/lib/motion.tsx, src/lib/motion.ts
Introduced AppMotionProvider, useShouldReduceMotion, system matchMedia detection, and getMotionAwareClasses; removed old src/lib/motion.ts.
App Settings & Normalization
src/lib/app-settings.ts
Added reducedMotionPreference to DEFAULT_APP_SETTINGS and normalizeAppSettings; added normalizeReducedMotionPreference.
App Root & Motion Wiring
src/App.tsx
Replaced global MotionConfig with AppSettingsMotionProvider that seeds settings from react-query and passes preference into AppMotionProvider.
Settings UI & Plumbing
src/components/Dashboard.tsx, src/components/features/settings/SettingsModal.tsx
Dashboard passes reducedMotionPreference into SettingsModal; SettingsModal gained prop, draft state, reset behavior, save payload, and 3-button control (system/always/never).
Hooks & Controller
src/hooks/use-app-settings.ts, src/hooks/use-dashboard-controller.ts
Added setReducedMotionPreference mutation; controller includes field in save/export/import payloads and internal handlers.
Localization
src/locales/en/common.json, src/locales/de/common.json
Added dashboard settings titles/descriptions and reduced-motion option labels (system/always/never).
Tests
tests/e2e/dashboard.spec.ts, tests/frontend/motion-accessibility.test.tsx, tests/frontend/settings-modal.test.tsx, tests/integration/server.test.ts, tests/unit/api.test.ts
Updated/added E2E, frontend, integration, and unit tests to exercise preference normalization, UI, persistence, import/export, reset, and motion behavior under all modes.
Changelog
CHANGELOG.md
Documented new 6.2.3 release and behavior, test coverage notes, and German label clarification.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App as App.tsx
    participant Query as ReactQuery
    participant API as /api/settings
    participant Motion as AppMotionProvider
    participant UI as Components (Dialogs/Charts/Modal)

    User->>App: Load app
    App->>Query: fetchSettings()
    Query->>API: GET /api/settings
    API-->>Query: { reducedMotionPreference: "system" }
    Query-->>App: settings
    App->>Motion: Provide preference="system"
    Motion->>UI: Provide shouldReduceMotion via context
    UI-->>User: Render (animations on/off)

    User->>UI: Open Settings Modal
    User->>UI: Select "always"
    UI->>Query: mutate PATCH /api/settings { reducedMotionPreference: "always" }
    Query->>API: PATCH /api/settings
    API-->>Query: Updated settings
    Query-->>App: Updated settings
    App->>Motion: Provide preference="always"
    Motion->>UI: Update shouldReduceMotion (force reduce)
    UI-->>User: Animations disabled
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I twitch my whiskers, soft and slow,
A setting lets the bunnies know.
System, always, never—hop with care,
Less spin, more calm, a gentle air. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.15% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add reduced motion override feature' accurately summarizes the main change—introducing a user-configurable reduced motion setting in dashboard settings that overrides the browser/OS preference signal.

✏️ 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 v623

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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 (2)
tests/unit/api.test.ts (1)

58-80: Test intent and assertion are slightly misaligned.

Line 58 says “normalizes”, but the fixture at Line 65 already uses a valid value ('never'), so this test verifies pass-through rather than normalization fallback. Consider renaming it or adding an invalid-value case that expects 'system'.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/api.test.ts` around lines 58 - 80, The test name says "normalizes
reduced-motion preferences" but the stubbed response already returns a valid
reducedMotionPreference ('never'), so it only verifies passthrough; update the
test to either rename it to reflect pass-through (change the it(...)
description) or change the stubbed fixture to return an invalid value (e.g.,
'invalid' or null) and assert that fetchSettings() normalizes it to 'system';
target the test case containing the fetch stub and the call to fetchSettings().
src/lib/motion.tsx (1)

74-76: Consider passing enabled to avoid unnecessary subscription.

useSystemReducedMotion() subscribes to media query changes even when the preference is 'always' or 'never', where the system value is unused. Passing the enabled argument would skip the subscription when not needed.

♻️ Optional optimization
-  const systemReducedMotion = useSystemReducedMotion()
+  const systemReducedMotion = useSystemReducedMotion(preference === 'system')
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/motion.tsx` around lines 74 - 76, The code always calls
useSystemReducedMotion() which subscribes to media query changes even when
preference is 'always' or 'never'; change the call to pass an enabled boolean so
the hook only subscribes when needed (i.e., enabled = preference === 'system' or
when preference is neither 'always' nor 'never'), then compute
shouldReduceMotion as before using preference === 'always' ? true : preference
=== 'never' ? false : systemReducedMotion; update references to
useSystemReducedMotion and the shouldReduceMotion assignment accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/locales/de/common.json`:
- Around line 913-919: Translate and naturalize the German strings: change
dashboardSettingsTitle from "Dashboard Settings" to "Dashboard-Einstellungen",
adjust reducedMotionDescription to use German compound wording (e.g., replace
"Browser-Einstellung" with "Browsereinstellung" and prefer native terms like
"Toast-Benachrichtigungen" instead of "Toast-Feedback"), and change
reducedMotionOptions.always from "Ja" to a more natural option like "Immer" or
"Immer aktiv". Locate and update the keys dashboardSettingsTitle,
reducedMotionDescription, and reducedMotionOptions.always in the JSON.

---

Nitpick comments:
In `@src/lib/motion.tsx`:
- Around line 74-76: The code always calls useSystemReducedMotion() which
subscribes to media query changes even when preference is 'always' or 'never';
change the call to pass an enabled boolean so the hook only subscribes when
needed (i.e., enabled = preference === 'system' or when preference is neither
'always' nor 'never'), then compute shouldReduceMotion as before using
preference === 'always' ? true : preference === 'never' ? false :
systemReducedMotion; update references to useSystemReducedMotion and the
shouldReduceMotion assignment accordingly.

In `@tests/unit/api.test.ts`:
- Around line 58-80: The test name says "normalizes reduced-motion preferences"
but the stubbed response already returns a valid reducedMotionPreference
('never'), so it only verifies passthrough; update the test to either rename it
to reflect pass-through (change the it(...) description) or change the stubbed
fixture to return an invalid value (e.g., 'invalid' or null) and assert that
fetchSettings() normalizes it to 'system'; target the test case containing the
fetch stub and the call to fetchSettings().
🪄 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: d8922057-75ee-4e9d-ab54-18f1a7cbeab6

📥 Commits

Reviewing files that changed from the base of the PR and between 6729d92 and c14876e.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • server.js
  • src/App.tsx
  • src/components/Dashboard.tsx
  • src/components/features/settings/SettingsModal.tsx
  • src/hooks/use-app-settings.ts
  • src/hooks/use-dashboard-controller.ts
  • src/lib/api.ts
  • src/lib/app-settings.ts
  • src/lib/motion.ts
  • src/lib/motion.tsx
  • src/locales/de/common.json
  • src/locales/en/common.json
  • src/types/index.ts
  • tests/e2e/dashboard.spec.ts
  • tests/frontend/motion-accessibility.test.tsx
  • tests/frontend/settings-modal.test.tsx
  • tests/integration/server.test.ts
  • tests/unit/api.test.ts
💤 Files with no reviewable changes (1)
  • src/lib/motion.ts

Comment thread src/locales/de/common.json Outdated
@tyl3r-ch tyl3r-ch merged commit 9f48f4b into main Apr 15, 2026
8 checks passed
@tyl3r-ch tyl3r-ch deleted the v623 branch April 20, 2026 20:39
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.

1 participant