diff --git a/src/components/Playground/PixiPlayground/MonacoEditor.tsx b/src/components/Playground/PixiPlayground/MonacoEditor.tsx index e0cabf76a..5c64f8b62 100644 --- a/src/components/Playground/PixiPlayground/MonacoEditor.tsx +++ b/src/components/Playground/PixiPlayground/MonacoEditor.tsx @@ -55,6 +55,13 @@ export default function MonacoEditor({ useTabs, onChange }: MonacoEditorProps) const { code, updateCode } = useActiveCode(); const { sandpack } = useSandpack(); + useEffect(() => + { + const tab = document.querySelector('.sp-tab-button[data-active=true]'); + + tab?.scrollIntoView(); + }, [sandpack.activeFile]); + const getFileExtension = (filename: string): string => { const parts = filename.split('.'); diff --git a/src/components/Playground/PixiPlayground/index.module.scss b/src/components/Playground/PixiPlayground/index.module.scss index 5291562e3..6eafd4476 100644 --- a/src/components/Playground/PixiPlayground/index.module.scss +++ b/src/components/Playground/PixiPlayground/index.module.scss @@ -1,116 +1,173 @@ .spWrapper { display: flex !important; flex: 1 0 100% !important; +} - .spLayout { - display: flex; - width: 100%; - flex: 1 0 100%; +.tpWrapper { + display: flex !important; + flex: 1 0 100%; +} - & > button { - display: none; - height: 3rem; - color: #fff; - background: var(--ifm-color-primary); - border: none; - border-radius: 0.5rem; - text-transform: uppercase; - font-weight: 700; - font-family: var(--ifm-font-family-base); - transition: background-color 0.12s ease-out; - - &:hover { - background: #e96e97; - } +.spLayout { + display: flex; + width: 100%; + flex: 1 0 100%; - &:active { - background: #c52359; - } + & > button { + display: none; + height: 3rem; + color: #fff; + background: var(--ifm-color-primary); + border: none; + border-radius: 0.5rem; + text-transform: uppercase; + font-weight: 700; + font-family: var(--ifm-font-family-base); + transition: background-color 0.12s ease-out; + + &:hover { + background: #e96e97; } - .editorWrapper { - flex: 1 1 !important; - width: 100%; - overflow: auto; + &:active { + background: #c52359; } + } - .previewWrapper { - position: relative; - display: flex; - flex: 1 1 !important; - } + &.tutorial { + @media only screen and (max-width: 920px), (max-aspect-ratio: 5/4) { + button { + display: unset; + } - &.tutorial { - @media only screen and (max-width: 920px), (max-aspect-ratio: 5/4) { - button { - display: unset; - } + .editorWrapper { + display: unset; + } + .previewWrapper { + display: none; + } + + &.showOutput { .editorWrapper { - display: unset; + display: none; } .previewWrapper { - display: none; + display: flex; } + } + } - &.showOutput { - .editorWrapper { - display: none; - } + @media only screen and (max-width: 1440px) { + flex-direction: column; + } + } - .previewWrapper { - display: flex; - } - } + &.fullscreen { + @media only screen and (max-width: 375px) { + button { + display: unset; } - @media only screen and (max-width: 1440px) { - flex-direction: column; + .editorWrapper { + display: unset; } - } - &.fullscreen { - @media only screen and (max-width: 375px) { - button { - display: unset; - } + .previewWrapper { + display: none; + } + &.showOutput { .editorWrapper { - display: unset; + display: none; } .previewWrapper { - display: none; + display: flex; } + } + } - &.showOutput { - .editorWrapper { - display: none; - } + @media only screen and (max-aspect-ratio: 1/1) { + flex-direction: column; + } + } - .previewWrapper { - display: flex; - } - } - } + &.example { + @media only screen and (max-width: 1280px) { + flex-direction: column; + } + } - @media only screen and (max-aspect-ratio: 1/1) { - flex-direction: column; - } + .editorWrapper { + flex: 1 1 !important; + width: 100%; + overflow: auto; + + // Hide scrollbar + -ms-overflow-style: none; + scrollbar-width: none; + ::-webkit-scrollbar { + display: none; } - &.example { - @media only screen and (max-width: 1280px) { - flex-direction: column; + .spTabs { + padding: 0; + + .spTabButton { + position: relative; + padding: 0 1rem; + + &::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(255, 255, 255, 0.1); + opacity: 0; + transition: opacity 0.1s ease-in-out; + } + + &::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 0.25rem; + background: var(--ifm-color-primary); + opacity: 0; + } + + &[data-active='true'] { + color: var(--ifm-color-primary); + cursor: default; + pointer-events: none; + + &::after { + opacity: 1; + } + } + + &[data-active='false'] { + &:hover { + &::before { + opacity: 1; + } + } + } } } } -} -.tpWrapper { - display: flex !important; - flex: 1 0 100%; + .previewWrapper { + position: relative; + display: flex; + flex: 1 1 !important; + } } .sandpackLoadingOverlay { diff --git a/src/components/Playground/PixiPlayground/index.tsx b/src/components/Playground/PixiPlayground/index.tsx index f10547896..2d9d7720f 100644 --- a/src/components/Playground/PixiPlayground/index.tsx +++ b/src/components/Playground/PixiPlayground/index.tsx @@ -112,6 +112,8 @@ export default function PixiPlayground({ classes: { 'sp-wrapper': mode === 'tutorial' ? styles.tpWrapper : styles.spWrapper, 'sp-layout': styles.spLayout, + 'sp-tabs-scrollable-container': styles.spTabs, + 'sp-tab-button': styles.spTabButton, }, visibleFiles: ['src/index.js', ...visibleExtraFiles], activeFile: active, diff --git a/src/components/Tutorial/index.tsx b/src/components/Tutorial/index.tsx index 31d263ada..8d6b10f8c 100644 --- a/src/components/Tutorial/index.tsx +++ b/src/components/Tutorial/index.tsx @@ -6,7 +6,7 @@ import PixiPlayground from '../Playground/PixiPlayground'; import type { IVersion } from '../Playground/PixiPlayground/usePixiVersions'; import type { TutorialStep } from '@site/src/tutorials'; import { getTutorialEntry } from '@site/src/tutorials'; -import { useCodeSource } from '../Playground/PixiPlayground/useEditorCode'; +import { extractSource } from '../Playground/PixiPlayground/useEditorCode'; function BrowserTutorial({ data, @@ -39,8 +39,8 @@ function BrowserTutorial({ setShowSolution(!showSolution); }; - const { indexCode, extraFiles } = useCodeSource(code); - const { indexCode: indexCodeCompleted, extraFiles: extraFilesCompleted } = useCodeSource(completedCode ?? code); + const { indexCode, extraFiles } = extractSource(code); + const { indexCode: indexCodeCompleted, extraFiles: extraFilesCompleted } = extractSource(completedCode ?? code); return ( <>