Skip to content

fix(theme-provider): callback deps, inline script, and onThemeChange#760

Merged
paanSinghCoder merged 7 commits intomainfrom
fix/theme-provider-callbacks-and-script
May 5, 2026
Merged

fix(theme-provider): callback deps, inline script, and onThemeChange#760
paanSinghCoder merged 7 commits intomainfrom
fix/theme-provider-callbacks-and-script

Conversation

@paanSinghCoder
Copy link
Copy Markdown
Contributor

@paanSinghCoder paanSinghCoder commented Apr 29, 2026

Description

Addresses items 2, 3, and 5 from #646.

  • Callback depssetTheme now tracks storageKey (was forcedTheme, unused). handleMediaQuery now includes enableSystem and applyTheme. Both fix latent stale-closure bugs that surface only when those props change at runtime.
  • Inline-script fixupdateDOM no longer emits c.add(x[e]|| ''). The literal path is gated with if(${val}) so a missing value-map entry doesn't reach classList.add('') (throws) or setAttribute(n, '') (junk attr).
  • onThemeChange callback — fires on actual theme/resolvedTheme changes, skips initial mount. Held via ref so consumer render churn doesn't over-fire and the callback never goes stale.

Type of Change

  • Bug fix
  • New feature
  • Improvement

How Has This Been Tested?

Manual repro on main vs branch for each fix. Tests TODO — leaving as draft until theme-provider.test.tsx is extended.

Related Issues

Refs #646 (items 2, 3, 5).

🤖 Generated with Claude Code

…646)

- Correct setTheme deps to track storageKey instead of unused forcedTheme.
- Add missing enableSystem and applyTheme to handleMediaQuery deps.
- Fix inline-script generation in updateDOM: drop the `name + "|| ''"` concat
  that produced classList.add('') (throws) or setAttribute(n, '') (junk
  attribute) when a value-map lookup missed; guard the literal path with
  if(${val}) so the DOM call only runs when the lookup is truthy.
- Add onThemeChange prop. Fires on actual theme/resolvedTheme changes,
  skipping the initial mount. Uses a ref so the callback identity is read
  at fire time, decoupling effect cadence from consumer render churn.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 29, 2026

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

Project Deployment Actions Updated (UTC)
apsara Ready Ready Preview, Comment May 5, 2026 6:43am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 29, 2026

Warning

Rate limit exceeded

@paanSinghCoder has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 7 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 020960e5-d0d3-4eb5-a2d4-f50f647e0d9d

📥 Commits

Reviewing files that changed from the base of the PR and between 4f58c0c and 417cedd.

📒 Files selected for processing (2)
  • packages/raystack/components/theme-provider/theme.tsx
  • packages/raystack/components/theme-provider/types.ts
📝 Walkthrough

Walkthrough

Adds an optional onThemeChange callback to the ThemeProvider and invokes it (only after the initial mount) when theme or resolvedTheme changes, passing both the raw theme and the resolved light/dark theme. Updates useCallback dependency arrays for setTheme and handleMediaQuery to include storageKey and relevant flags/functions. Adjusts ThemeScript generation for literal values by removing the empty-string fallback and wrapping literal-mode DOM updates with conditional guards.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant ThemeProvider
  participant Storage as localStorage
  participant MediaQuery as SystemPref
  participant DOM as ThemeScript/DOM
  participant Consumer as onThemeChange

  User->>ThemeProvider: set theme / toggle
  ThemeProvider->>Storage: persist theme (storageKey)
  ThemeProvider->>MediaQuery: query/observe system preference (if enabled)
  MediaQuery-->>ThemeProvider: resolved (light/dark)
  ThemeProvider->>DOM: apply theme (attribute/class or data-theme)
  ThemeProvider->>Consumer: (after mount) onThemeChange(theme, resolved)
Loading

Possibly related issues

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the three main changes: callback dependency fixes, inline script improvements, and the new onThemeChange callback feature.
Description check ✅ Passed The description comprehensively relates to the changeset, detailing the callback dependency fixes, inline-script fix, and onThemeChange callback implementation with clear explanations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.


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.

@paanSinghCoder paanSinghCoder self-assigned this Apr 29, 2026
@paanSinghCoder paanSinghCoder marked this pull request as ready for review May 1, 2026 04:24
Copy link
Copy Markdown
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/raystack/components/theme-provider/theme.tsx`:
- Around line 183-193: The effect handling theme changes currently flips
themeChangeMounted.current on the first run even when theme === 'system' and
resolvedTheme is still undefined, causing onThemeChangeRef.current to fire when
resolvedTheme later populates; update the useEffect (the block referencing
themeChangeMounted, onThemeChangeRef, theme, resolvedTheme) to only treat the
initial run as "mounted" when a stable resolved value exists (i.e., if theme ===
'system' require resolvedTheme to be non-null before setting
themeChangeMounted.current = true), so the callback is not invoked on initial
mount, and add a unit test that renders with defaultTheme="system" and empty
storage asserting onThemeChange is not called on mount but is called on
subsequent user-initiated theme changes.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: edf4cd10-e5af-479a-ae27-6f4572d173b6

📥 Commits

Reviewing files that changed from the base of the PR and between fddcf49 and 4d02562.

📒 Files selected for processing (2)
  • packages/raystack/components/theme-provider/theme.tsx
  • packages/raystack/components/theme-provider/types.ts

Comment thread packages/raystack/components/theme-provider/theme.tsx Outdated
Comment thread packages/raystack/components/theme-provider/theme.tsx
Comment thread packages/raystack/components/theme-provider/theme.tsx Outdated
Comment thread packages/raystack/components/theme-provider/theme.tsx
Copy link
Copy Markdown
Contributor

@rohanchkrabrty rohanchkrabrty left a comment

Choose a reason for hiding this comment

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

Also let's update the docs in theme/overview with the new props

Comment thread packages/raystack/components/theme-provider/theme.tsx Outdated
Comment thread packages/raystack/components/theme-provider/theme.tsx Outdated
Comment thread packages/raystack/components/theme-provider/theme.tsx
Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
apps/www/src/content/docs/theme/overview/props.ts (1)

71-75: 💤 Low value

LGTM — type signature and JSDoc are accurate.

The onThemeChange prop is correctly typed and the JSDoc faithfully reflects the PR-stated contract (fires after mount, passes both raw and resolved themes).

One minor doc nit: the JSDoc only calls out the "system" → resolved mapping but doesn't mention the forcedTheme case, where resolvedTheme would equal the forced value regardless of user preference. Worth a one-liner addition for completeness, but not blocking.

📝 Optional JSDoc enhancement
  /**
   * Called when the active theme changes. `resolvedTheme` is the actual applied theme
   * (`"light"`/`"dark"` when `theme` is `"system"`). Not fired on initial mount.
+  * When `forcedTheme` is set, `resolvedTheme` reflects the forced value.
   */
  onThemeChange?: (theme: string, resolvedTheme: string) => void;
🤖 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 `@apps/www/src/content/docs/theme/overview/props.ts` around lines 71 - 75,
Update the JSDoc for onThemeChange to mention the forcedTheme case: note that
when a forcedTheme is set, resolvedTheme will equal that forced value regardless
of user preference; keep the existing note about "system" mapping and retain the
type signature onThemeChange?: (theme: string, resolvedTheme: string) => void.
Refer to the onThemeChange declaration and include a one-line addition in its
comment clarifying forcedTheme behavior.
🤖 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.

Nitpick comments:
In `@apps/www/src/content/docs/theme/overview/props.ts`:
- Around line 71-75: Update the JSDoc for onThemeChange to mention the
forcedTheme case: note that when a forcedTheme is set, resolvedTheme will equal
that forced value regardless of user preference; keep the existing note about
"system" mapping and retain the type signature onThemeChange?: (theme: string,
resolvedTheme: string) => void. Refer to the onThemeChange declaration and
include a one-line addition in its comment clarifying forcedTheme behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 83ab8049-1b50-4c45-bd45-810ba2e21cfd

📥 Commits

Reviewing files that changed from the base of the PR and between 12cb393 and 4f58c0c.

📒 Files selected for processing (1)
  • apps/www/src/content/docs/theme/overview/props.ts

@paanSinghCoder paanSinghCoder merged commit 6b10ec6 into main May 5, 2026
5 checks passed
@paanSinghCoder paanSinghCoder deleted the fix/theme-provider-callbacks-and-script branch May 5, 2026 06:45
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