Skip to content

fix: updateCSSVariable inside scoped theme#502

Merged
Brentlok merged 5 commits intomainfrom
fix/updateCSSVariable-scoped-theme
Apr 21, 2026
Merged

fix: updateCSSVariable inside scoped theme#502
Brentlok merged 5 commits intomainfrom
fix/updateCSSVariable-scoped-theme

Conversation

@Brentlok
Copy link
Copy Markdown
Contributor

@Brentlok Brentlok commented Apr 21, 2026

fixes #499

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Fixed CSS variable propagation across scoped themes and components
    • Improved theme-switching behavior to properly update all dependent styles
  • Tests

    • Added comprehensive test coverage for CSS variable updates with multiple themes
    • Enhanced native and web platform test suites for theme configuration

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

📝 Walkthrough

Walkthrough

The PR refactors CSS variable management from in-memory storage to DOM-backed CSS rules, introducing a dynamic stylesheet approach that ensures ScopedTheme components and non-global theme overrides reliably reflect runtime variable updates across native and web platforms.

Changes

Cohort / File(s) Summary
Utility Consolidation
packages/uniwind/src/common/utils.ts
Added exported arrayEquals<T> utility function for generic array equality comparison using strict element-wise equality.
Core Config Refactoring
packages/uniwind/src/core/config/config.ts
Replaced in-memory runtimeCSSVariables map with cached DOM-backed cssRules tied to theme selectors. Introduced getUniwindDynamicCSSRules() to inject and manage a dynamic <style> element. Refactored updateCSSVariables() to update all cached CSS rules directly via setProperty() and always notify listeners. Replaced onThemeChange() with __reinit() to rebuild rules when themes change, using arrayEquals for early exit optimization.
Native Config Listener Fix
packages/uniwind/src/core/config/config.native.ts
Removed conditional guard on UniwindListener.notify([StyleDependency.Variables]) to ensure listeners are notified unconditionally after CSS variables are updated.
CSS Listener Expansion
packages/uniwind/src/core/web/cssListener.ts
Extended CSSListenerBuilder.subscribeToClassName to subscribe to both StyleDependency.Theme and StyleDependency.Variables instead of theme-only subscriptions.
Hook Utility Refactoring
packages/uniwind/src/hooks/useCSSVariable/useCSSVariable.ts
Removed locally-defined arrayEquals implementation and imported it from shared utilities, consolidating array comparison logic.
Test Suite Additions
packages/uniwind/tests/native/components/scoped-theme.test.tsx, packages/uniwind/tests/web/core/config.test.ts
Added comprehensive test coverage for updateCSSVariables() behavior: native tests verify scoped theme updates across integration points, web tests validate dynamic CSS rule generation and caching across theme changes.

Sequence Diagram

sequenceDiagram
    participant App as Application
    participant Uniwind as Uniwind.updateCSSVariables()
    participant DOMRules as Dynamic CSS Rules<br/>(DOM-backed)
    participant Listener as UniwindListener
    participant Component as ScopedTheme Component

    App->>Uniwind: updateCSSVariables(theme, vars)
    Uniwind->>DOMRules: getUniwindDynamicCSSRules() if needed
    DOMRules->>DOMRules: Inject `#uniwind-dynamic-styles` element<br/>with theme selectors (.light, .dark, etc)
    Uniwind->>DOMRules: For each cached rule, call<br/>rule.style.setProperty(varName, value)<br/>for matching theme
    Uniwind->>Listener: notify([StyleDependency.Variables])
    Listener->>Component: Trigger component subscribed<br/>to Variables dependency
    Component->>Component: Re-render with updated<br/>CSS variables from DOM
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • fix: getWebStyles not return default html styles #440 — Modifies the same CSSListenerBuilder.subscribeToClassName in cssListener.ts; both PRs restructure listener subscription patterns, though with different approaches to rule tracking and variable dependency handling.

Poem

🐰 A stylesheet that blooms and grows,
With dynamic rules the DOM now knows,
No more in memory we hold our cache,
Each theme gets CSS to dash and flash! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: updateCSSVariable inside scoped theme' directly addresses the main objective of the PR (fixing updateCSSVariables behavior for ScopedTheme components), which is clearly reflected in the changeset modifications.
Linked Issues check ✅ Passed The PR comprehensively addresses issue #499 by implementing per-theme CSS rule caching on web, unconditional listener notifications on native, and refactoring array equality logic into a shared utility across both platforms.
Out of Scope Changes check ✅ Passed All changes are directly scoped to resolving the updateCSSVariables ScopedTheme issue: utility extraction (arrayEquals), CSS rule management, listener notification logic, and comprehensive test coverage for both web and native platforms.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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 fix/updateCSSVariable-scoped-theme

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.

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

🤖 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/uniwind/src/core/config/config.ts`:
- Around line 78-91: The code builds CSS selectors from theme names without
escaping, causing invalid selectors for names like "2xl" or "brand:premium"; fix
by using CSS.escape when generating selectors in styleElement.innerText (i.e.,
replace `.${theme}{}` with `.${CSS.escape(theme)}{}`) and change the cssRules
mapping to derive the theme from the original themes array by index (use the
same order as this.themes) rather than parsing selectorText; keep references to
styleElement, this.themes, UniwindCSSRule and ensure updateCSSVariables() will
receive the correct unescaped theme names.
🪄 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: 8aacfd5e-f8ed-4228-9d23-d38037de0794

📥 Commits

Reviewing files that changed from the base of the PR and between e0c91ee and 72e4373.

📒 Files selected for processing (7)
  • packages/uniwind/src/common/utils.ts
  • packages/uniwind/src/core/config/config.native.ts
  • packages/uniwind/src/core/config/config.ts
  • packages/uniwind/src/core/web/cssListener.ts
  • packages/uniwind/src/hooks/useCSSVariable/useCSSVariable.ts
  • packages/uniwind/tests/native/components/scoped-theme.test.tsx
  • packages/uniwind/tests/web/core/config.test.ts

Comment thread packages/uniwind/src/core/config/config.ts
@Brentlok Brentlok merged commit 1f90dd0 into main Apr 21, 2026
2 checks passed
@Brentlok Brentlok deleted the fix/updateCSSVariable-scoped-theme branch April 21, 2026 07:51
@github-actions
Copy link
Copy Markdown
Contributor

🚀 This pull request is included in v1.6.3. See Release v1.6.3 for release notes.

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.

Uniwind.updateCSSVariables does not update ScopedTheme components or resolve non-global web theme overrides reliably

1 participant