diff --git a/website-next/src/components/EditorToolbar.module.css b/website-next/src/components/EditorToolbar.module.css index 442194e3..3406a0b0 100644 --- a/website-next/src/components/EditorToolbar.module.css +++ b/website-next/src/components/EditorToolbar.module.css @@ -8,9 +8,6 @@ .toolbar { display: flex; column-gap: 8px; - position: absolute; - top: 10px; - right: 10px; } .toolbar button { diff --git a/website-next/src/components/EditorToolbar.tsx b/website-next/src/components/EditorToolbar.tsx index f4581057..3d2c7b7d 100644 --- a/website-next/src/components/EditorToolbar.tsx +++ b/website-next/src/components/EditorToolbar.tsx @@ -18,9 +18,15 @@ import styles from './EditorToolbar.module.css'; export type Props = Readonly<{ getCode: () => string; + className?: string; + style?: React.CSSProperties; }>; -export default function EditorToolbar({getCode}: Props): JSX.Element { +export default function EditorToolbar({ + getCode, + className, + style, +}: Props): JSX.Element { const handleCopy = useCallback( () => navigator.clipboard.writeText(getCode()), [], @@ -36,7 +42,7 @@ export default function EditorToolbar({getCode}: Props): JSX.Element { ); return ( -
+
diff --git a/website-next/src/components/Playground.module.css b/website-next/src/components/Playground.module.css index db398a15..c1c6a3f4 100644 --- a/website-next/src/components/Playground.module.css +++ b/website-next/src/components/Playground.module.css @@ -26,30 +26,42 @@ html[data-theme='dark'] { background-color: var(--yg-color-playground-background); } -.editorColumn { - position: relative; - flex: 8; - min-width: 0; -} - .playgroundRow { display: flex; flex-direction: row; column-gap: 16px; } +.editorColumn { + flex: 8; + min-width: 0; + overflow-y: auto; + border: 1px solid var(--yg-color-editor-border); + border-radius: var(--ifm-pre-border-radius); + position: relative; +} + +.editorScroll { + overflow-y: auto; +} + +.editorToolbar { + position: absolute; + top: 10px; + right: 10px; +} + .playgroundEditor { font: var(--ifm-code-font-size) / var(--ifm-pre-line-height) var(--ifm-font-family-monospace) !important; direction: ltr; height: calc(var(--yg-playground-height, 400px) - 32px); - overflow: scroll; } .playgroundEditor :global(.prism-code) { - height: 100%; box-shadow: var(--ifm-global-shadow-lw); - border: 1px solid var(--yg-color-editor-border); + min-height: 100%; + border-radius: 0; } .previewColumn { @@ -86,8 +98,7 @@ html[data-theme='dark'] { } .playgroundEditor { - height: max-content; - overflow: visible; + height: unset; } .playgroundRow { @@ -97,12 +108,13 @@ html[data-theme='dark'] { .editorColumn { padding: 0; - flex: 0 !important; margin-bottom: 10px; + flex: unset; } .previewColumn { padding: 10px; width: 100%; + flex: unset; } } diff --git a/website-next/src/components/Playground.tsx b/website-next/src/components/Playground.tsx index 0ee4a58d..2969309a 100644 --- a/website-next/src/components/Playground.tsx +++ b/website-next/src/components/Playground.tsx @@ -13,6 +13,7 @@ import React, { lazy, useCallback, useEffect, + useLayoutEffect, useRef, useState, } from 'react'; @@ -45,7 +46,11 @@ export type Props = Readonly<{ export default function Playground({code, height, autoFocus}: Props) { const prismTheme = usePrismTheme(); const playgroundRef = useRef(null); + const editorScrollRef = useRef(null); + const [isLoaded, setIsLoaded] = useState(false); + const [liveCode, setLiveCode] = useState(code ?? defaultCode); + const [scrollbarWidth, setScrollbarWidth] = useState(0); const LivePreviewWrapper = useCallback( (props: React.ComponentProps<'div'>) => { @@ -64,35 +69,52 @@ export default function Playground({code, height, autoFocus}: Props) { if (isLoaded && autoFocus) { const codeElem = playgroundRef?.current?.querySelector('.prism-code'); const sel = window.getSelection(); - if (codeElem != null && sel != null) { + if (codeElem?.clientHeight && sel != null) { sel.selectAllChildren(codeElem); sel.collapseToStart(); } } }, [isLoaded, autoFocus]); + useLayoutEffect(() => { + // The toolbar is positioned relative to the outside of the scrolling + // container so it stays in the same place when scrolling, but this means + // it isn't automatically adjusted for scrollbar width + if (editorScrollRef.current) { + setScrollbarWidth( + editorScrollRef.current.offsetWidth - + editorScrollRef.current.clientWidth, + ); + } + }); + const heightStyle = height ? ({'--yg-playground-height': height} as React.CSSProperties) : undefined; - const resolvedCode = code ?? defaultCode; - return ( - +
-
- - nullthrows( - playgroundRef.current?.querySelector('.prism-code') - ?.textContent, - ), - [], - )} - /> - +
+
+ + nullthrows( + playgroundRef.current?.querySelector('.prism-code') + ?.textContent, + ), + [], + )} + /> + +