diff --git a/.changeset/remove-ssr-handoff-script-under-ff.md b/.changeset/remove-ssr-handoff-script-under-ff.md new file mode 100644 index 00000000000..b9801290687 --- /dev/null +++ b/.changeset/remove-ssr-handoff-script-under-ff.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +ThemeProvider: Skip rendering the SSR handoff script when the `primer_react_theme_provider_remove_ssr_handoff` feature flag is enabled diff --git a/packages/react/src/FeatureFlags/DefaultFeatureFlags.ts b/packages/react/src/FeatureFlags/DefaultFeatureFlags.ts index eebbd691c10..78d1837d5bb 100644 --- a/packages/react/src/FeatureFlags/DefaultFeatureFlags.ts +++ b/packages/react/src/FeatureFlags/DefaultFeatureFlags.ts @@ -7,4 +7,5 @@ export const DefaultFeatureFlags = FeatureFlagScope.create({ primer_react_styled_react_use_primer_theme_providers: false, primer_react_action_list_group_heading_trailing_action: false, primer_react_timeline_list_semantics: false, + primer_react_theme_provider_remove_ssr_handoff: false, }) diff --git a/packages/react/src/ThemeProvider.tsx b/packages/react/src/ThemeProvider.tsx index b6b5384f733..9b30341168b 100644 --- a/packages/react/src/ThemeProvider.tsx +++ b/packages/react/src/ThemeProvider.tsx @@ -2,6 +2,7 @@ import React from 'react' import defaultTheme from './theme' import deepmerge from 'deepmerge' import {useId} from './hooks' +import {useFeatureFlag} from './FeatureFlags' import {useSyncedState} from './hooks/useSyncedState' export const defaultColorMode = 'day' @@ -17,6 +18,9 @@ export type ThemeProviderProps = { colorMode?: ColorModeWithAuto dayScheme?: string nightScheme?: string + /** + * No-op when the `primer_react_theme_provider_remove_ssr_handoff` feature flag is enabled. + */ preventSSRMismatch?: boolean /** * When true, only provides theme context to descendants without rendering @@ -82,6 +86,7 @@ export const ThemeProvider: React.FC // Initialize state const theme = fallbackTheme ?? defaultTheme + const removeSSRHandoff = useFeatureFlag('primer_react_theme_provider_remove_ssr_handoff') const uniqueDataId = useId() const [colorMode, setColorMode] = useSyncedState(props.colorMode ?? fallbackColorMode ?? defaultColorMode) @@ -91,11 +96,12 @@ export const ThemeProvider: React.FC const clientColorMode = resolveColorMode(colorMode, systemColorMode) // During SSR/hydration, use the server-rendered color mode from the handoff script tag // to avoid mismatches. After hydration, resolve from client state. - const resolvedColorMode = React.useSyncExternalStore( + const ssrResolvedColorMode = React.useSyncExternalStore( emptySubscribe, () => clientColorMode, () => getServerHandoff(uniqueDataId).resolvedServerColorMode ?? clientColorMode, ) + const resolvedColorMode = removeSSRHandoff ? clientColorMode : ssrResolvedColorMode const colorScheme = chooseColorScheme(resolvedColorMode, dayScheme, nightScheme) const {resolvedTheme, resolvedColorScheme} = React.useMemo( () => applyColorScheme(theme, colorScheme), @@ -129,13 +135,14 @@ export const ThemeProvider: React.FC ], ) - const ssrHandoffScript = props.preventSSRMismatch ? ( -