From 918383b4e09b6bfd7796c1946468ad9f2e24df90 Mon Sep 17 00:00:00 2001 From: Micah Godbolt Date: Thu, 21 Jul 2022 16:14:40 -0700 Subject: [PATCH 1/6] init approach --- .../useFluentProviderThemeStyleTag.ts | 70 ++++++++++++------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts b/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts index 2b7e2d9bc0aa5..221dd536862e2 100644 --- a/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts +++ b/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts @@ -3,6 +3,33 @@ import * as React from 'react'; import type { FluentProviderState } from './FluentProvider.types'; import { fluentProviderClassNames } from './useFluentProviderStyles'; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const useInsertionEffect = (React as any)['useInsertion' + 'Effect']; + +const createStyleTag = (target: Document | undefined, id: string) => { + if (!target) { + return undefined; + } + const tag = target.createElement('style'); + tag.setAttribute('id', id); + target.head.appendChild(tag); + return tag; +}; + +const insertSheet = (tag: HTMLStyleElement, rule: string) => { + const sheet = tag.sheet; + + if (sheet) { + if (sheet.cssRules.length > 0) { + sheet.deleteRule(0); + } + sheet.insertRule(rule, 0); + } else if (process.env.NODE_ENV !== 'production') { + // eslint-disable-next-line no-console + console.error('FluentProvider: No sheet available on styleTag, styles will not be inserted into DOM.'); + } +}; + /** * Writes a theme as css variables in a style tag on the provided targetDocument as a rule applied to a CSS class * @@ -10,18 +37,13 @@ import { fluentProviderClassNames } from './useFluentProviderStyles'; */ export const useFluentProviderThemeStyleTag = (options: Pick) => { const { targetDocument, theme } = options; + const styleTag = React.useRef(); const styleTagId = useId(fluentProviderClassNames.root); - const styleTag = React.useMemo(() => { - if (!targetDocument) { - return null; - } - const tag = targetDocument.createElement('style'); - tag.setAttribute('id', styleTagId); - targetDocument.head.appendChild(tag); - return tag; - }, [styleTagId, targetDocument]); + if (!useInsertionEffect) { + styleTag.current = createStyleTag(targetDocument, styleTagId); + } const cssRule = React.useMemo(() => { const cssVarsAsString = theme @@ -34,30 +56,28 @@ export const useFluentProviderThemeStyleTag = (options: Pick 0) { - sheet.deleteRule(0); - } - sheet.insertRule(cssRule, 0); - } else if (process.env.NODE_ENV !== 'production') { - // eslint-disable-next-line no-console - console.error('FluentProvider: No sheet available on styleTag, styles will not be inserted into DOM.'); - } + // insert cssRule into HTML tag if it exists + if (styleTag.current && previousCssRule !== cssRule) { + insertSheet(styleTag.current, cssRule); } + const useEffect = useInsertionEffect || React.useEffect; + // Removes the style tag from the targetDocument on unmount or change - React.useEffect(() => { + useEffect(() => { + if (useInsertionEffect && targetDocument) { + styleTag.current = createStyleTag(document, styleTagId); + styleTag.current && insertSheet(styleTag.current, cssRule); + } return () => { - if (styleTag) { - styleTag.remove(); + if (styleTag.current) { + styleTag.current.remove(); } }; - }, [styleTag]); + }, [cssRule, styleTagId, targetDocument]); return styleTagId; }; From e70889453ed968a8e1d086557179492d3259cda3 Mon Sep 17 00:00:00 2001 From: Micah Godbolt Date: Thu, 21 Jul 2022 16:16:08 -0700 Subject: [PATCH 2/6] fix typos --- .../FluentProvider/useFluentProviderThemeStyleTag.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts b/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts index 221dd536862e2..58157de7f1580 100644 --- a/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts +++ b/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts @@ -68,8 +68,8 @@ export const useFluentProviderThemeStyleTag = (options: Pick { - if (useInsertionEffect && targetDocument) { - styleTag.current = createStyleTag(document, styleTagId); + if (useInsertionEffect) { + styleTag.current = createStyleTag(targetDocument, styleTagId); styleTag.current && insertSheet(styleTag.current, cssRule); } return () => { From 869822146fe5848f2c5b3e0e77cbf584386356fe Mon Sep 17 00:00:00 2001 From: Micah Godbolt Date: Thu, 21 Jul 2022 16:50:26 -0700 Subject: [PATCH 3/6] bit of reorg --- .../useFluentProviderThemeStyleTag.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts b/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts index 58157de7f1580..b710add07a676 100644 --- a/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts +++ b/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts @@ -41,10 +41,6 @@ export const useFluentProviderThemeStyleTag = (options: Pick { const cssVarsAsString = theme ? (Object.keys(theme) as (keyof typeof theme)[]).reduce((cssVarRule, cssVar) => { @@ -57,17 +53,21 @@ export const useFluentProviderThemeStyleTag = (options: Pick { + // React 18+ behavior if (useInsertionEffect) { styleTag.current = createStyleTag(targetDocument, styleTagId); styleTag.current && insertSheet(styleTag.current, cssRule); From 071f6d6caf8f9e015df8ab7ed2be6772613b8e22 Mon Sep 17 00:00:00 2001 From: Micah Godbolt Date: Thu, 21 Jul 2022 16:57:04 -0700 Subject: [PATCH 4/6] remove concated strings --- .../components/FluentProvider/useFluentProviderThemeStyleTag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts b/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts index b710add07a676..062aadb706fab 100644 --- a/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts +++ b/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts @@ -4,7 +4,7 @@ import type { FluentProviderState } from './FluentProvider.types'; import { fluentProviderClassNames } from './useFluentProviderStyles'; // eslint-disable-next-line @typescript-eslint/no-explicit-any -const useInsertionEffect = (React as any)['useInsertion' + 'Effect']; +const useInsertionEffect = (React as any).useInsertionEffect; const createStyleTag = (target: Document | undefined, id: string) => { if (!target) { From f8fc4e0b7f0729f6de2a690cc400c27e4f87dd0a Mon Sep 17 00:00:00 2001 From: Micah Godbolt Date: Thu, 21 Jul 2022 17:00:10 -0700 Subject: [PATCH 5/6] collapse test --- .../FluentProvider/useFluentProviderThemeStyleTag.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts b/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts index 062aadb706fab..5dec35e00f44c 100644 --- a/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts +++ b/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts @@ -53,10 +53,8 @@ export const useFluentProviderThemeStyleTag = (options: Pick Date: Thu, 21 Jul 2022 17:01:11 -0700 Subject: [PATCH 6/6] return check --- .../FluentProvider/useFluentProviderThemeStyleTag.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts b/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts index 5dec35e00f44c..062aadb706fab 100644 --- a/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts +++ b/packages/react-components/react-provider/src/components/FluentProvider/useFluentProviderThemeStyleTag.ts @@ -53,8 +53,10 @@ export const useFluentProviderThemeStyleTag = (options: Pick