Skip to content

Commit d790545

Browse files
committed
fix: sync kapa widget theme on first modal open
Kapa lazily renders #kapa-widget-root inside the shadow DOM only when the modal first opens, not when kapa-widget-container is added to the body. The previous sync() ran too early (returned false) and the only recovery path was a manual theme toggle. Three changes: - After finding kapa-widget-container, observe the shadow root's subtree so sync() fires the moment #kapa-widget-root appears (lazy render on first open) - Once #kapa-widget-root exists, observe its data-mantine-color-scheme attribute so any reset by Kapa's React re-renders is patched immediately - Guard the setAttribute call with an equality check to prevent observer loops
1 parent b82f813 commit d790545

1 file changed

Lines changed: 26 additions & 2 deletions

File tree

public/kapa.js

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,33 @@
3838
dark: '#kapa-widget-root{--mantine-color-body:#1b1812;--mantine-color-default:#221e18;--mantine-color-default-border:#2d2820;--mantine-color-text:#f0ebe0;--mantine-color-placeholder:#a29a8d;}',
3939
};
4040

41+
// _schemeObserver is set once #kapa-widget-root exists and guards against Kapa
42+
// resetting data-mantine-color-scheme on every modal open/render cycle.
43+
var _schemeObserver = null;
44+
4145
function sync() {
4246
var c = document.getElementById('kapa-widget-container');
4347
if (!c || !c.shadowRoot) return false;
4448
var r = c.shadowRoot.querySelector('#kapa-widget-root');
4549
if (!r) return false;
4650
var scheme = document.documentElement.dataset.theme === 'dark' ? 'dark' : 'light';
47-
r.setAttribute('data-mantine-color-scheme', scheme);
51+
// Only write the attribute when it differs — prevents observer re-entry loops.
52+
if (r.getAttribute('data-mantine-color-scheme') !== scheme) {
53+
r.setAttribute('data-mantine-color-scheme', scheme);
54+
}
4855
var st = c.shadowRoot.querySelector('#kapa-icp-tokens');
4956
if (!st) {
5057
st = document.createElement('style');
5158
st.id = 'kapa-icp-tokens';
5259
c.shadowRoot.appendChild(st);
5360
}
5461
st.textContent = TOKENS[scheme];
62+
// Arm the attribute observer on first successful sync so future resets by
63+
// Kapa's React re-renders are caught immediately without a theme toggle.
64+
if (!_schemeObserver) {
65+
_schemeObserver = new MutationObserver(sync);
66+
_schemeObserver.observe(r, { attributes: true, attributeFilter: ['data-mantine-color-scheme'] });
67+
}
5568
return true;
5669
}
5770

@@ -61,8 +74,19 @@
6174
var added = mutations[i].addedNodes;
6275
for (var j = 0; j < added.length; j++) {
6376
if (added[j].id === 'kapa-widget-container') {
77+
bodyObserver.disconnect();
78+
var c = added[j];
6479
// Give kapa's React one tick to finish rendering the shadow root.
65-
setTimeout(function () { if (sync()) bodyObserver.disconnect(); }, 0);
80+
setTimeout(function () {
81+
if (sync()) return;
82+
// #kapa-widget-root not rendered yet (modal hasn't opened).
83+
// Observe the shadow root's subtree so sync() fires the moment it appears.
84+
if (!c.shadowRoot) return;
85+
var shadowObserver = new MutationObserver(function () {
86+
if (sync()) shadowObserver.disconnect();
87+
});
88+
shadowObserver.observe(c.shadowRoot, { childList: true, subtree: true });
89+
}, 0);
6690
return;
6791
}
6892
}

0 commit comments

Comments
 (0)