diff --git a/client/i18n/locales/english/translations.json b/client/i18n/locales/english/translations.json index 64936a1e998..9a69e69c50d 100644 --- a/client/i18n/locales/english/translations.json +++ b/client/i18n/locales/english/translations.json @@ -523,7 +523,8 @@ "instructions": "Instructions", "notes": "Notes", "preview": "Preview", - "editor": "Editor" + "editor": "Editor", + "interactive-editor": "Interactive Editor" }, "editor-alerts": { "tab-trapped": "Pressing tab will now insert the tab character", @@ -952,7 +953,8 @@ "editor-a11y-on-macos": "{{editorName}} editor content. Accessibility mode set to 'on'. Press Command+E to disable or press Option+F1 for more options.", "editor-a11y-on-non-macos": "{{editorName}} editor content. Accessibility mode set to 'on'. Press Ctrl+E to disable or press Alt+F1 for more options.", "terminal-output": "Terminal output", - "not-available": "Not available" + "not-available": "Not available", + "interactive-editor-desc": "Turn static code examples into interactive editors. This allows you to edit and run the code directly on the page." }, "flash": { "no-email-in-userinfo": "We could not retrieve an email from your chosen provider. Please try another provider or use the 'Continue with Email' option.", diff --git a/client/src/components/Flash/flash.css b/client/src/components/Flash/flash.css index a95786d08f8..88fccd1ad2a 100644 --- a/client/src/components/Flash/flash.css +++ b/client/src/components/Flash/flash.css @@ -10,5 +10,5 @@ div.flash-message { padding-bottom: 3px; position: fixed; width: 100%; - z-index: 150; + z-index: var(--z-index-flash); } diff --git a/client/src/components/Header/components/universal-nav.css b/client/src/components/Header/components/universal-nav.css index 1a19453a19c..85ed12e0759 100644 --- a/client/src/components/Header/components/universal-nav.css +++ b/client/src/components/Header/components/universal-nav.css @@ -73,6 +73,7 @@ position: absolute; right: 0; width: 100%; + z-index: var(--z-index-site-header); } @media (min-width: 980px) { diff --git a/client/src/components/layouts/global.css b/client/src/components/layouts/global.css index e776537c708..a12de135c44 100644 --- a/client/src/components/layouts/global.css +++ b/client/src/components/layouts/global.css @@ -139,6 +139,14 @@ hr { min-height: 0; } +.default-layout:has(.breadcrumbs-demo) #learn-app-wrapper { + padding-top: var(--breadcrumbs-height); +} + +.default-layout:has(.action-row) #learn-app-wrapper { + padding-top: calc(var(--breadcrumbs-height) + var(--action-row-height)); +} + h1 { color: var(--secondary-color); font-weight: 700; diff --git a/client/src/components/layouts/variables.css b/client/src/components/layouts/variables.css index 76b5a316968..cef80095521 100644 --- a/client/src/components/layouts/variables.css +++ b/client/src/components/layouts/variables.css @@ -37,6 +37,9 @@ --header-sub-element-size: 45px; --header-height: 38px; --breadcrumbs-height: 44px; + --action-row-height: 64px; + --z-index-breadcrumbs: 100; + --z-index-flash: 150; --z-index-site-header: 200; } diff --git a/client/src/redux/prop-types.ts b/client/src/redux/prop-types.ts index e14270a4650..39c1fb56881 100644 --- a/client/src/redux/prop-types.ts +++ b/client/src/redux/prop-types.ts @@ -182,7 +182,12 @@ type ParagraphNodule = { type InteractiveEditorNodule = { type: 'interactiveEditor'; - data: { ext: Ext; name: string; contents: string }[]; + data: { + ext: Ext; + name: string; + contents: string; + contentsHtml: string; + }[]; }; export type ChallengeNode = { diff --git a/client/src/templates/Challenges/classic/action-row.tsx b/client/src/templates/Challenges/classic/action-row.tsx index bea0000d277..c14fe5d4aef 100644 --- a/client/src/templates/Challenges/classic/action-row.tsx +++ b/client/src/templates/Challenges/classic/action-row.tsx @@ -6,7 +6,7 @@ import store from 'store'; import { DailyCodingChallengeLanguages } from '../../../redux/prop-types'; import EditorTabs from './editor-tabs'; -interface ActionRowProps { +interface ClassicLayoutProps { dailyCodingChallengeLanguage: DailyCodingChallengeLanguages; hasNotes: boolean; hasPreview: boolean; @@ -21,24 +21,58 @@ interface ActionRowProps { showPreviewPane: boolean; showPreviewPortal: boolean; togglePane: (pane: string) => void; + hasInteractiveEditor?: never; } -const ActionRow = ({ - hasPreview, - hasNotes, - togglePane, - showNotes, - showPreviewPane, - showPreviewPortal, - showConsole, - showInstructions, - areInstructionsDisplayable, - isDailyCodingChallenge, - dailyCodingChallengeLanguage, - setDailyCodingChallengeLanguage -}: ActionRowProps): JSX.Element => { +interface InteractiveEditorProps { + hasInteractiveEditor: true; + showInteractiveEditor: boolean; + toggleInteractiveEditor: () => void; +} + +type ActionRowProps = ClassicLayoutProps | InteractiveEditorProps; + +const ActionRow = (props: ActionRowProps): JSX.Element => { const { t } = useTranslation(); + if (props.hasInteractiveEditor) { + const { toggleInteractiveEditor, showInteractiveEditor } = props; + + return ( +
+
+
+ + + {t('aria.interactive-editor-desc')} + +
+
+
+ ); + } + + const { + togglePane, + hasPreview, + hasNotes, + areInstructionsDisplayable, + showConsole, + showNotes, + showInstructions, + showPreviewPane, + showPreviewPortal, + isDailyCodingChallenge, + dailyCodingChallengeLanguage, + setDailyCodingChallengeLanguage + } = props; + // sets screen reader text for the two preview buttons function getPreviewBtnsSrText() { // no preview open diff --git a/client/src/templates/Challenges/classic/classic.css b/client/src/templates/Challenges/classic/classic.css index 7b8da74da0a..df482e7f517 100644 --- a/client/src/templates/Challenges/classic/classic.css +++ b/client/src/templates/Challenges/classic/classic.css @@ -18,8 +18,15 @@ } .action-row { + height: var(--action-row-height); + position: fixed; + top: calc(var(--header-height) + var(--breadcrumbs-height)); + left: 0; + right: 0; + z-index: 100; padding: 10px; border-bottom: 1px solid var(--quaternary-background); + background-color: var(--secondary-background); } .monaco-editor-tabs button[aria-expanded='true'], @@ -79,6 +86,7 @@ width: 30%; display: flex; justify-content: flex-end; + margin-inline-start: auto; } .monaco-editor-tabs button + button { diff --git a/client/src/templates/Challenges/classic/editor.css b/client/src/templates/Challenges/classic/editor.css index bbea71a0d3c..9480a784f72 100644 --- a/client/src/templates/Challenges/classic/editor.css +++ b/client/src/templates/Challenges/classic/editor.css @@ -32,10 +32,16 @@ textarea.inputarea { } .breadcrumbs-demo { + position: fixed; + top: var(--header-height); + left: 0; + right: 0; + z-index: var(--z-index-breadcrumbs); font-size: 16px; margin: 0; padding: 10px; height: var(--breadcrumbs-height); + background: var(--secondary-background); } @media screen and (max-height: 300px) { diff --git a/client/src/templates/Challenges/components/interactive-editor.css b/client/src/templates/Challenges/components/interactive-editor.css index 853cce90680..8a9c80705ae 100644 --- a/client/src/templates/Challenges/components/interactive-editor.css +++ b/client/src/templates/Challenges/components/interactive-editor.css @@ -23,7 +23,7 @@ } .sp-preview-actions .sp-button:hover { - background-color: var(--gray-10); + background-color: var(--gray-10) !important; color: var(--gray-90) !important; - border-color: var(--gray-90); + border-color: var(--gray-90) !important; } diff --git a/client/src/templates/Challenges/components/interactive-editor.tsx b/client/src/templates/Challenges/components/interactive-editor.tsx index 2955faf8d10..12c836ddba4 100644 --- a/client/src/templates/Challenges/components/interactive-editor.tsx +++ b/client/src/templates/Challenges/components/interactive-editor.tsx @@ -7,6 +7,7 @@ export interface InteractiveFile { ext: string; name: string; contents: string; + contentsHtml: string; fileKey?: string; } @@ -52,7 +53,7 @@ const InteractiveEditor = ({ files }: Props) => { }; return ( -