From 2caa8ac8cb1e00d3dd9d1706d8a95fbf90ee88e5 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 19 Dec 2023 12:46:26 -0800 Subject: [PATCH] Workaround Docusaurus prism highlighting hydration bug (#1519) Summary: Pull Request resolved: https://github.com/facebook/yoga/pull/1519 See https://github.com/facebook/docusaurus/issues/9629 We use prism to render the code for the inline editor. Prism renders colors to style directly, and the color chosen is dependent on a setting that may not be available at SSR time. This adds an SSR-specific representation of the code, missing some of the nuances in token colorization (similar to https://github.com/facebook/docusaurus/pull/7373). This adds a little bit of jank compared to perfect SSR, but fixes cases where the mode is incorrect, and is a lot less jank then the more generic solution used by theme-live-codeblock of keeping the rendering of the opposite color until rehydration. Preview: https://yoga-website-next-git-fork-nickgerleman-exp-2f8171-fbopensource.vercel.app/ Reviewed By: yungsters Differential Revision: D52163722 fbshipit-source-id: 312dc52134f0084d40f78147190151700ee10ff7 --- .../src/components/Playground.module.css | 14 ++++++- website-next/src/components/Playground.tsx | 38 +++++++++++++++---- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/website-next/src/components/Playground.module.css b/website-next/src/components/Playground.module.css index 9c89296e..a3839ad7 100644 --- a/website-next/src/components/Playground.module.css +++ b/website-next/src/components/Playground.module.css @@ -9,12 +9,16 @@ html[data-theme='light'] { --yg-color-preview-background: var(--ifm-color-primary-lighter); --yg-color-playground-background: var(--ifm-color-gray-200); --yg-color-editor-border: var(--ifm-color-gray-400); + --yg-color-editor-fallback-bg: rgb(246, 248, 250); + --yg-color-editor-fallback-text: rgb(0, 0, 159); } html[data-theme='dark'] { --yg-color-preview-background: var(--ifm-color-primary-dark); --yg-color-playground-background: var(--ifm-color-background); --yg-color-editor-border: var(--ifm-color-gray-800); + --yg-color-editor-fallback-bg: rgb(40, 44, 52); + --yg-color-editor-fallback-text: rgb(209, 154, 102); } .wrapper { @@ -47,8 +51,8 @@ html[data-theme='dark'] { .editorToolbar { position: absolute; - top: 10px; - right: 10px; + top: var(--ifm-pre-padding); + right: var(--ifm-pre-padding); } .playgroundEditor { @@ -62,6 +66,12 @@ html[data-theme='dark'] { box-shadow: var(--ifm-global-shadow-lw); min-height: 100%; border-radius: 0; + padding: var(--ifm-pre-padding) !important; +} + +.liveEditorFallback { + background-color: var(--yg-color-editor-fallback-bg); + color: var(--yg-color-editor-fallback-text); } .previewColumn { diff --git a/website-next/src/components/Playground.tsx b/website-next/src/components/Playground.tsx index 9887eb30..c2091d90 100644 --- a/website-next/src/components/Playground.tsx +++ b/website-next/src/components/Playground.tsx @@ -27,6 +27,7 @@ import type {FlexStyle} from './FlexStyle'; import type {StyleNode} from './YogaViewer'; import styles from './Playground.module.css'; +import useIsBrowser from '@docusaurus/useIsBrowser'; export type Props = Readonly<{ code: string; @@ -37,6 +38,7 @@ export type Props = Readonly<{ export default function Playground({code, height, autoFocus}: Props) { const prismTheme = usePrismTheme(); const editorScrollRef = useRef(null); + const isBrowser = useIsBrowser(); const [liveCode, setLiveCode] = useState(code); const [hasCodeChanged, setHasCodeChanged] = useState(false); @@ -72,6 +74,11 @@ export default function Playground({code, height, autoFocus}: Props) { ? ({'--yg-playground-height': height} as React.CSSProperties) : undefined; + const handleCodeChange = useCallback((code: string) => { + setHasCodeChanged(true); + setLiveCode(code); + }, []); + return ( - { - setHasCodeChanged(true); - setLiveCode(code); - }, [])} - /> + + {isBrowser ? ( + + ) : ( + + )}
@@ -105,6 +114,21 @@ export default function Playground({code, height, autoFocus}: Props) { ); } +/** + * Provides a non-editable approximation of the LiveEditor result, without + * relying on prism rendering, for use during SSR. + * See https://github.com/facebook/docusaurus/issues/9629 + */ +function LiveEditorFallback({code}: Readonly<{code: string}>) { + return ( +
+
+        {code}
+      
+
+ ); +} + type RootLiveNodeProps = Readonly<{ children: React.ReactNode; config?: {useWebDefaults?: boolean};