diff --git a/client/src/components/layouts/learn.css b/client/src/components/layouts/learn.css index 964a1f6ca2a..d0609b334d2 100644 --- a/client/src/components/layouts/learn.css +++ b/client/src/components/layouts/learn.css @@ -14,6 +14,22 @@ flex-direction: column; } +#learn-app-wrapper .editor-pane { + display: flex; + flex-direction: column; + min-height: 0; + width: 100%; +} + +#learn-app-wrapper .editor-pane-code { + flex: 1 1 auto; + min-height: 0; +} +#learn-app-wrapper .editor-pane > .independent-lower-jaw { + flex: 0 0 auto; + margin-top: auto; +} + #learn-app-wrapper .reflex-container.vertical { min-height: 0; flex-grow: 1; diff --git a/client/src/templates/Challenges/classic/desktop-layout.tsx b/client/src/templates/Challenges/classic/desktop-layout.tsx index b1d42a7dea5..a8fc6784f76 100644 --- a/client/src/templates/Challenges/classic/desktop-layout.tsx +++ b/client/src/templates/Challenges/classic/desktop-layout.tsx @@ -314,9 +314,14 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => { name='editorPane' {...resizeProps} data-playwright-test-label='editor-pane' + className='editor-pane' > {!isEmpty(challengeFiles) && ( - + { if (isPreFetchEnabled && envData.clientLocale === 'espanol') { diff --git a/client/src/templates/Challenges/components/independent-lower-jaw.css b/client/src/templates/Challenges/components/independent-lower-jaw.css index 75be49fe949..712f89c1e15 100644 --- a/client/src/templates/Challenges/components/independent-lower-jaw.css +++ b/client/src/templates/Challenges/components/independent-lower-jaw.css @@ -1,10 +1,8 @@ .independent-lower-jaw { - position: absolute; - left: 0; - right: 0; - bottom: 0; width: 100%; - z-index: 10; + flex: 0 0 auto; + position: relative; + z-index: 101; } .independent-lower-jaw .hint-container { @@ -13,7 +11,24 @@ flex-direction: row; justify-content: space-between; padding: 12px; - margin: 12px; + position: absolute; + bottom: 100%; + width: 95%; + left: 50%; + transform: translateX(-50%); + margin-bottom: 12px; + border: 1px solid var(--background-secondary); + opacity: 0; + animation: jaw-hint-fade-in 0.3s ease forwards; +} + +@keyframes jaw-hint-fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } } .independent-lower-jaw .btn-cta { diff --git a/client/src/templates/Challenges/components/independent-lower-jaw.tsx b/client/src/templates/Challenges/components/independent-lower-jaw.tsx index e1b94a2d00e..7c5f87f3205 100644 --- a/client/src/templates/Challenges/components/independent-lower-jaw.tsx +++ b/client/src/templates/Challenges/components/independent-lower-jaw.tsx @@ -51,6 +51,10 @@ export function IndependentLowerJaw({ const hint = firstFailedTest?.message; const [showHint, setShowHint] = React.useState(false); const [showSubmissionHint, setShowSubmissionHint] = React.useState(true); + const signInLinkRef = React.useRef(null); + const submitButtonRef = React.useRef(null); + const [wasCheckButtonClicked, setWasCheckButtonClicked] = + React.useState(false); const isChallengeComplete = tests.every(test => test.pass); @@ -58,27 +62,60 @@ export function IndependentLowerJaw({ setShowHint(!!hint); }, [hint]); + React.useEffect(() => { + if (!isChallengeComplete || !wasCheckButtonClicked) return; + + const focusTarget = isSignedIn + ? submitButtonRef.current + : signInLinkRef.current; + focusTarget?.focus(); + setWasCheckButtonClicked(false); + }, [isChallengeComplete, isSignedIn, wasCheckButtonClicked]); + + const handleCheckButtonClick = () => { + setWasCheckButtonClicked(true); + executeChallenge(); + }; + const isMacOS = navigator.userAgent.includes('Mac OS'); - const checkButtonText = isMacOS ? t('command-enter') : t('ctrl-enter'); + const checkButtonText = isMacOS + ? t('buttons.command-enter') + : t('buttons.ctrl-enter'); return ( -
+
{showHint && hint && ( -
+
-
)} {isChallengeComplete && showSubmissionHint && ( -
+

{t('learn.congratulations-code-passes')}

{!isSignedIn && ( { callGA({ event: 'sign_in' @@ -91,6 +128,7 @@ export function IndependentLowerJaw({