Skip to content

Fix browser compatibility: guard requestIdleCallback and startViewTransition#1464

Merged
N2D4 merged 1 commit into
devfrom
devin/1779397733-browser-compat-fixes-v2
May 21, 2026
Merged

Fix browser compatibility: guard requestIdleCallback and startViewTransition#1464
N2D4 merged 1 commit into
devfrom
devin/1779397733-browser-compat-fixes-v2

Conversation

@N2D4
Copy link
Copy Markdown
Contributor

@N2D4 N2D4 commented May 21, 2026

Add feature checks for two browser APIs that aren't universally supported:

  • requestIdleCallback: Falls back to setTimeout on browsers that don't support it (e.g. Safari)
  • document.startViewTransition: Applies the theme change directly when the View Transitions API is unavailable

Link to Devin session: https://app.devin.ai/sessions/c77b612db7834e9aa71c6b5a0fde316b
Requested by: @N2D4


Note

Low Risk
Low risk: adds simple runtime feature-detection with safe fallbacks for unsupported browser APIs, affecting only theme toggling animation and an idle-wait hook.

Overview
Improves dashboard browser compatibility by adding runtime guards and fallbacks for unsupported web APIs.

ThemeToggle now skips the View Transitions path when document.startViewTransition isn’t a function, applying the theme change directly instead. useWaitForIdle now falls back to setTimeout when requestIdleCallback is unavailable, while preserving the existing min/max delay behavior.

Reviewed by Cursor Bugbot for commit b5232a1. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

Bug Fixes

  • Improved browser compatibility for theme switching and idle callback handling by adding fallback mechanisms when modern browser APIs are unavailable.

Review Change Stack

…nsition

Co-Authored-By: Konstantin Wohlwend <n2d4xc@gmail.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stack-auth-hosted-components Ready Ready Preview, Comment May 21, 2026 9:18pm
stack-auth-mcp Ready Ready Preview, Comment May 21, 2026 9:18pm
stack-auth-skills Ready Ready Preview, Comment May 21, 2026 9:18pm
stack-backend Building Building Preview, Comment May 21, 2026 9:18pm
stack-dashboard Building Building Preview, Comment May 21, 2026 9:18pm
stack-demo Building Building Preview, Comment May 21, 2026 9:18pm
stack-docs Ready Ready Preview, Comment May 21, 2026 9:18pm
stack-preview-backend Building Building Preview, Comment May 21, 2026 9:18pm
stack-preview-dashboard Building Building Preview, Comment May 21, 2026 9:18pm

@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f9f0f73f-a8b8-45ff-a821-13d1673b2119

📥 Commits

Reviewing files that changed from the base of the PR and between b8fc04b and b5232a1.

📒 Files selected for processing (2)
  • apps/dashboard/src/components/theme-toggle.tsx
  • apps/dashboard/src/hooks/use-wait-for-idle.tsx

📝 Walkthrough

Walkthrough

This PR adds runtime compatibility checks for two browser APIs in the dashboard. ThemeToggle now guards document.startViewTransition before use, falling back to direct theme setting. useWaitForIdle now guards requestIdleCallback and falls back to setTimeout when unavailable, maintaining the same timeout computation in both paths.

Changes

Browser API Compatibility Guards

Layer / File(s) Summary
View Transition and Idle Callback API guards
apps/dashboard/src/components/theme-toggle.tsx, apps/dashboard/src/hooks/use-wait-for-idle.tsx
ThemeToggle checks whether startViewTransition is a function before initiating a View Transition, falling back to direct setTheme(). useWaitForIdle extracts a cancellation-aware callback and conditionally schedules it via requestIdleCallback when available or setTimeout when unavailable, using the same timeout duration in both cases.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Poem

🐰 A rabbit hops through browser lands,
Where APIs dance and compatibility stands—
With guards in place and fallbacks true,
The theme and timing shine right through! ✨

✨ 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 devin/1779397733-browser-compat-fixes-v2

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.

@N2D4 N2D4 marked this pull request as ready for review May 21, 2026 21:10
Copilot AI review requested due to automatic review settings May 21, 2026 21:10
@N2D4 N2D4 merged commit 3b2e991 into dev May 21, 2026
28 of 35 checks passed
@N2D4 N2D4 deleted the devin/1779397733-browser-compat-fixes-v2 branch May 21, 2026 21:10
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds graceful fallbacks for newer browser APIs (Idle Callback + View Transitions) to improve compatibility across environments.

Changes:

  • Add requestIdleCallback feature detection with a setTimeout fallback in useWaitForIdle
  • Add document.startViewTransition feature detection with a direct setTheme fallback in ThemeToggle

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
apps/dashboard/src/hooks/use-wait-for-idle.tsx Adds fallback scheduling when requestIdleCallback isn’t available
apps/dashboard/src/components/theme-toggle.tsx Avoids calling View Transitions API when unsupported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 5 to 19
useEffect(() => {
let cancelled = false;
setTimeout(() => {
requestIdleCallback(() => {
const cb = () => {
if (cancelled) return;
setHasWaited(true);
}, { timeout: max - min });
};
if (typeof requestIdleCallback === "function") {
requestIdleCallback(cb, { timeout: max - min });
} else {
setTimeout(cb, max - min);
}
}, min);
return () => {
cancelled = true;
Comment on lines +12 to +16
if (typeof requestIdleCallback === "function") {
requestIdleCallback(cb, { timeout: max - min });
} else {
setTimeout(cb, max - min);
}
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b5232a1. Configure here.

if (typeof document.startViewTransition !== "function") {
setTheme(nextTheme);
return;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant startViewTransition check duplicates existing guard

Low Severity

The new typeof document.startViewTransition !== "function" check on lines 25-28 is redundant dead code. The existing supportsViewTransitions() function (line 8-10) already checks "startViewTransition" in document, and the early return on line 20 ensures execution only reaches line 25 when that property exists. In all real browser implementations, when "startViewTransition" in document is true, the property is always a function, making this second guard unreachable.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b5232a1. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 21, 2026

Greptile Summary

This PR adds browser compatibility guards for two APIs that are not universally supported: requestIdleCallback (absent in older Safari) and document.startViewTransition (absent in Firefox and older browsers).

  • use-wait-for-idle.tsx: Extracts the idle callback into a named cb variable and wraps requestIdleCallback with a typeof check, falling back to setTimeout(cb, max - min) so the total wait stays bounded at max ms on unsupported browsers.
  • theme-toggle.tsx: Adds a typeof document.startViewTransition !== \"function\" early-return guard, though this check is effectively dead code because the pre-existing supportsViewTransitions() helper already returns false (and exits) before this point when the API is absent.

Confidence Score: 4/5

Safe to merge — both changes are defensive guards that improve cross-browser compatibility without altering the happy path.

The use-wait-for-idle fix is clean and correct. The theme-toggle fix adds a guard that is redundant with the already-present supportsViewTransitions() check, making the new block unreachable dead code rather than a functional improvement.

The redundant guard in theme-toggle.tsx (lines 25-28) is worth cleaning up, but poses no runtime risk.

Important Files Changed

Filename Overview
apps/dashboard/src/components/theme-toggle.tsx Added a typeof document.startViewTransition !== "function" guard that is redundant with the pre-existing supportsViewTransitions() check, making the new block dead code in all real browsers.
apps/dashboard/src/hooks/use-wait-for-idle.tsx Clean requestIdleCallback polyfill: wraps the callback, checks for API availability, and falls back to setTimeout(cb, max - min) so the total wait remains bounded at max ms. Cancellation logic via the cancelled flag is preserved correctly in both branches.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[handleToggle called] --> B{prefersReducedMotion or !supportsViewTransitions?}
    B -- Yes --> C[setTheme directly]
    B -- No --> D{typeof startViewTransition === function?}
    D -- No --> C
    D -- Yes --> E[startViewTransition callback]
    E --> F[setTheme inside transition]
    E --> G[Animate old/new views]

    H[useWaitForIdle hook] --> I[outer setTimeout min ms]
    I --> J{typeof requestIdleCallback === function?}
    J -- Yes --> K[requestIdleCallback cb timeout: max-min ms]
    J -- No --> L[setTimeout cb max-min ms]
    K --> M[setHasWaited true]
    L --> M
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/dashboard/src/components/theme-toggle.tsx:25-28
**Redundant guard — already covered by `supportsViewTransitions()`**

The new `typeof document.startViewTransition !== "function"` check is unreachable in practice. The existing `supportsViewTransitions()` call on line 20 uses `"startViewTransition" in document`, which already returns `false` whenever the API is absent, causing an early return before this block is ever evaluated. The only case where this new guard would fire is if `startViewTransition` is present on `document` but isn't a function — a scenario that doesn't exist in any real browser. Consider either updating `supportsViewTransitions()` to use `typeof document.startViewTransition === "function"` and removing this guard, or simply removing this redundant block.

Reviews (1): Last reviewed commit: "Fix browser compatibility: guard request..." | Re-trigger Greptile

Comment on lines +25 to +28
if (typeof document.startViewTransition !== "function") {
setTheme(nextTheme);
return;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Redundant guard — already covered by supportsViewTransitions()

The new typeof document.startViewTransition !== "function" check is unreachable in practice. The existing supportsViewTransitions() call on line 20 uses "startViewTransition" in document, which already returns false whenever the API is absent, causing an early return before this block is ever evaluated. The only case where this new guard would fire is if startViewTransition is present on document but isn't a function — a scenario that doesn't exist in any real browser. Consider either updating supportsViewTransitions() to use typeof document.startViewTransition === "function" and removing this guard, or simply removing this redundant block.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/dashboard/src/components/theme-toggle.tsx
Line: 25-28

Comment:
**Redundant guard — already covered by `supportsViewTransitions()`**

The new `typeof document.startViewTransition !== "function"` check is unreachable in practice. The existing `supportsViewTransitions()` call on line 20 uses `"startViewTransition" in document`, which already returns `false` whenever the API is absent, causing an early return before this block is ever evaluated. The only case where this new guard would fire is if `startViewTransition` is present on `document` but isn't a function — a scenario that doesn't exist in any real browser. Consider either updating `supportsViewTransitions()` to use `typeof document.startViewTransition === "function"` and removing this guard, or simply removing this redundant block.

How can I resolve this? If you propose a fix, please make it concise.

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