// Assist dialog input-field readability patch // Targets ha-voice-command-dialog's text input and forces theme-driven colors, // since HA's own theme variables don't reach the nested mwc-textfield shadow root. (function () { if (window.__assistFixLoaded) return; window.__assistFixLoaded = true; const css = ` :host .mdc-text-field, :host .mdc-text-field--filled, .mdc-text-field, .mdc-text-field--filled { background-color: var(--card-background-color, rgba(22, 24, 40, 0.92)) !important; border-radius: 8px !important; } :host .mdc-text-field__input, .mdc-text-field__input, :host input, input { color: var(--primary-text-color, #e7e9f4) !important; caret-color: var(--primary-text-color, #e7e9f4) !important; } :host .mdc-floating-label, .mdc-floating-label, :host .mdc-text-field__affix, .mdc-text-field__affix { color: var(--secondary-text-color, #9a9cb8) !important; } :host .mdc-line-ripple::before, .mdc-line-ripple::before { border-bottom-color: var(--divider-color, rgba(255, 255, 255, 0.18)) !important; } `; function walkShadow(root, depth = 0) { if (!root || depth > 8) return []; const found = []; try { root.querySelectorAll('ha-textfield, ha-textarea, mwc-textfield, mwc-textarea').forEach(el => found.push(el)); root.querySelectorAll('*').forEach(el => { if (el.shadowRoot) found.push(...walkShadow(el.shadowRoot, depth + 1)); }); } catch (e) {} return found; } function injectInto(textfield) { if (!textfield || textfield.__assistFixDone) return; textfield.__assistFixDone = true; const sr = textfield.shadowRoot; if (!sr) return; const style = document.createElement('style'); style.textContent = css; sr.appendChild(style); // Also patch the nested mwc-textfield if present walkShadow(sr).forEach(tf => { if (tf !== textfield && !tf.__assistFixDone && tf.shadowRoot) { tf.__assistFixDone = true; const s = document.createElement('style'); s.textContent = css; tf.shadowRoot.appendChild(s); } }); } function scan() { // Look for any Assist dialog in the DOM const dialogs = document.querySelectorAll( 'ha-voice-command-dialog, dialog-voice-command-dialog, ha-conversation-dialog' ); dialogs.forEach(d => { if (d.shadowRoot) walkShadow(d.shadowRoot).forEach(injectInto); }); // Also scan root-level more-info dialogs that might host textfields if (document.body) { walkShadow(document.body).forEach(injectInto); } } // Run on mutations (dialog opens / closes) const obs = new MutationObserver(() => scan()); obs.observe(document.body || document.documentElement, { childList: true, subtree: true, }); // Initial pass + periodic sweep for first 30s (covers page-load races) let passes = 0; const interval = setInterval(() => { scan(); if (++passes > 30) clearInterval(interval); }, 1000); scan(); console.log('[assist-fix] loaded'); })();