diff --git a/src/components/ThemeProvider.tsx b/src/components/ThemeProvider.tsx index 76371bbbc9e1..72172365df13 100644 --- a/src/components/ThemeProvider.tsx +++ b/src/components/ThemeProvider.tsx @@ -1,7 +1,8 @@ /* eslint-disable react/jsx-props-no-spreading */ import PropTypes from 'prop-types'; -import React, {useMemo} from 'react'; +import React, {useEffect, useMemo} from 'react'; import useThemePreferenceWithStaticOverride from '@hooks/useThemePreferenceWithStaticOverride'; +import DomUtils from '@libs/DomUtils'; // eslint-disable-next-line no-restricted-imports import themes from '@styles/theme'; import ThemeContext from '@styles/theme/context/ThemeContext'; @@ -21,6 +22,10 @@ function ThemeProvider({children, theme: staticThemePreference}: ThemeProviderPr const theme = useMemo(() => themes[themePreference], [themePreference]); + useEffect(() => { + DomUtils.addCSS(DomUtils.getAutofilledInputStyle(theme.text), 'autofill-input'); + }, [theme.text]); + return {children}; } diff --git a/src/libs/DomUtils/index.native.ts b/src/libs/DomUtils/index.native.ts index 7117f5942f9a..eac988e55f1b 100644 --- a/src/libs/DomUtils/index.native.ts +++ b/src/libs/DomUtils/index.native.ts @@ -2,6 +2,10 @@ import type GetActiveElement from './types'; const getActiveElement: GetActiveElement = () => null; +const addCSS = () => {}; + +const getAutofilledInputStyle = () => null; + const requestAnimationFrame = (callback: () => void) => { if (!callback) { return; @@ -11,6 +15,8 @@ const requestAnimationFrame = (callback: () => void) => { }; export default { + addCSS, + getAutofilledInputStyle, getActiveElement, requestAnimationFrame, }; diff --git a/src/libs/DomUtils/index.ts b/src/libs/DomUtils/index.ts index 068eb0c9fe7e..330123833c1f 100644 --- a/src/libs/DomUtils/index.ts +++ b/src/libs/DomUtils/index.ts @@ -2,7 +2,68 @@ import type GetActiveElement from './types'; const getActiveElement: GetActiveElement = () => document.activeElement; +const addCSS = (css: string, styleId: string) => { + const existingStyle = document.getElementById(styleId); + + if (existingStyle) { + if ('styleSheet' in existingStyle) { + // Supports IE8 and below + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (existingStyle.styleSheet as any).cssText = css; + } else { + existingStyle.innerHTML = css; + } + } else { + const styleElement = document.createElement('style'); + styleElement.setAttribute('id', styleId); + styleElement.setAttribute('type', 'text/css'); + + if ('styleSheet' in styleElement) { + // Supports IE8 and below + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (styleElement.styleSheet as any).cssText = css; + } else { + styleElement.appendChild(document.createTextNode(css)); + } + + const head = document.getElementsByTagName('head')[0]; + head.appendChild(styleElement); + } +}; + +/** + * Customizes the background and text colors for autofill inputs in Chrome + * Chrome on iOS does not support the autofill pseudo class because it is a non-standard webkit feature. + * We should rely on the chrome-autofilled property being added to the input when users use auto-fill + */ +const getAutofilledInputStyle = (inputTextColor: string) => ` + input[chrome-autofilled], + input[chrome-autofilled]:hover, + input[chrome-autofilled]:focus, + textarea[chrome-autofilled], + textarea[chrome-autofilled]:hover, + textarea[chrome-autofilled]:focus, + select[chrome-autofilled], + select[chrome-autofilled]:hover, + select[chrome-autofilled]:focus, + input:-webkit-autofill, + input:-webkit-autofill:hover, + input:-webkit-autofill:focus, + textarea:-webkit-autofill, + textarea:-webkit-autofill:hover, + textarea:-webkit-autofill:focus, + select:-webkit-autofill, + select:-webkit-autofill:hover, + select:-webkit-autofill:focus { + -webkit-background-clip: text; + -webkit-text-fill-color: ${inputTextColor}; + caret-color: ${inputTextColor}; + } +`; + export default { + addCSS, + getAutofilledInputStyle, getActiveElement, requestAnimationFrame: window.requestAnimationFrame.bind(window), }; diff --git a/web/index.html b/web/index.html index 7c02614d17b2..49ffd0d0a62f 100644 --- a/web/index.html +++ b/web/index.html @@ -70,32 +70,6 @@ display: none; } - /* Customizes the background and text colors for autofill inputs in Chrome */ - /* Chrome on iOS does not support the autofill pseudo class because it is a non-standard webkit feature. - We should rely on the chrome-autofilled property being added to the input when users use auto-fill */ - input[chrome-autofilled], - input[chrome-autofilled]:hover, - input[chrome-autofilled]:focus, - textarea[chrome-autofilled], - textarea[chrome-autofilled]:hover, - textarea[chrome-autofilled]:focus, - select[chrome-autofilled], - select[chrome-autofilled]:hover, - select[chrome-autofilled]:focus, - input:-webkit-autofill, - input:-webkit-autofill:hover, - input:-webkit-autofill:focus, - textarea:-webkit-autofill, - textarea:-webkit-autofill:hover, - textarea:-webkit-autofill:focus, - select:-webkit-autofill, - select:-webkit-autofill:hover, - select:-webkit-autofill:focus { - -webkit-background-clip: text; - -webkit-text-fill-color: #ffffff; - caret-color: #ffffff; - } - /* Customize Plaid iframe */ [id^="plaid-link-iframe"] { color-scheme: dark !important;