From a2f089410aa3b8d0644c04c7eac52059f0830518 Mon Sep 17 00:00:00 2001 From: paulj Date: Thu, 13 Nov 2025 11:19:38 -0500 Subject: [PATCH 1/2] fix: re-sync onboarding options visibility after keyword interpolation When isMounted triggers keyword interpolation, makeKeywordsClickable clones React elements causing DOM recreation that loses .hidden classes. Added useLayoutEffect to re-apply visibility state synchronously before paint. Fixes checkbox display bug introduced by hydration fix in #15473. --- src/components/codeBlock/index.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/components/codeBlock/index.tsx b/src/components/codeBlock/index.tsx index 310df8d13b5a9b..44cced81ce4257 100644 --- a/src/components/codeBlock/index.tsx +++ b/src/components/codeBlock/index.tsx @@ -1,14 +1,16 @@ 'use client'; -import {RefObject, useEffect, useRef, useState} from 'react'; +import {RefObject, useContext, useEffect, useLayoutEffect, useRef, useState} from 'react'; import {Clipboard} from 'react-feather'; import {usePlausibleEvent} from 'sentry-docs/hooks/usePlausibleEvent'; import styles from './code-blocks.module.scss'; +import {CodeContext} from '../codeContext'; import {makeHighlightBlocks} from '../codeHighlights'; import {makeKeywordsClickable} from '../codeKeywords'; +import {updateElementsVisibilityForOptions} from '../onboarding'; export interface CodeBlockProps { children: React.ReactNode; @@ -53,6 +55,7 @@ function getCopiableText(element: HTMLDivElement) { export function CodeBlock({filename, language, children}: CodeBlockProps) { const [showCopied, setShowCopied] = useState(false); const codeRef = useRef(null); + const codeContext = useContext(CodeContext); // Show the copy button after js has loaded // otherwise the copy button will not work @@ -83,6 +86,15 @@ export function CodeBlock({filename, language, children}: CodeBlockProps) { }; }, []); + // Re-sync onboarding visibility after keyword interpolation recreates DOM nodes. + // makeKeywordsClickable clones elements, losing .hidden classes. useLayoutEffect + // corrects this synchronously before paint to prevent visible flicker. + useLayoutEffect(() => { + if (isMounted && codeContext?.onboardingOptions) { + updateElementsVisibilityForOptions(codeContext.onboardingOptions, false); + } + }, [isMounted, codeContext?.onboardingOptions]); + useCleanSnippetInClipboard(codeRef, {language}); // Mermaid blocks should not be processed by CodeBlock - they need special client-side rendering From 10aeca3dcc250ee07528f6366f80173e3da976ec Mon Sep 17 00:00:00 2001 From: paulj Date: Thu, 13 Nov 2025 11:36:37 -0500 Subject: [PATCH 2/2] update test react import --- src/components/onboarding/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/onboarding/index.tsx b/src/components/onboarding/index.tsx index cc12dc984359c3..7e8e00a689594f 100644 --- a/src/components/onboarding/index.tsx +++ b/src/components/onboarding/index.tsx @@ -1,6 +1,7 @@ 'use client'; -import {ReactNode, useContext, useEffect, useReducer, useState} from 'react'; +// eslint-disable-next-line no-restricted-imports -- Required for JSX in test environment +import React, {ReactNode, useContext, useEffect, useReducer, useState} from 'react'; import {QuestionMarkCircledIcon} from '@radix-ui/react-icons'; import * as Tooltip from '@radix-ui/react-tooltip'; import {Button, Checkbox, Theme} from '@radix-ui/themes';