diff --git a/assets/src/js/v3/entries/course-builder/components/modals/QuestionPreviewModal.tsx b/assets/src/js/v3/entries/course-builder/components/modals/QuestionPreviewModal.tsx index 595a242a28..4bdb419252 100644 --- a/assets/src/js/v3/entries/course-builder/components/modals/QuestionPreviewModal.tsx +++ b/assets/src/js/v3/entries/course-builder/components/modals/QuestionPreviewModal.tsx @@ -574,25 +574,42 @@ const getPreviewFrameStyles = () => ` } /* - * Puzzle preview: board capped at min(52vh, 460px) like draw/pin; piece pool grows with content - * (no internal scroll), same as the live student scatter area on mobile. + * Puzzle preview: match student learning-area — content-sized card (no forced fill). + * Board keeps the course-builder cap; scatter grows with pieces (no inner stretch). + * Wrapper stays centered in the modal like other question previews. */ + .tutor-quiz-question-wrapper:has([data-question='puzzle']), + .tutor-quiz-question[data-question='puzzle'] { + flex: 0 1 auto; + height: auto; + max-height: none; + min-height: 0; + margin-block: 0; + } + .tutor-quiz-question[data-question='puzzle'] .quiz-question-ans-choice-area.tutor-puzzle-question { box-sizing: border-box; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + flex: 0 1 auto; width: 100%; max-width: 100%; min-width: 0; - align-items: center; - margin-top: 24px; + height: auto; + max-height: none; + margin-top: 0; + overflow: visible; } .tutor-quiz-question[data-question='puzzle'] .tutor-puzzle-playground { box-sizing: border-box; + flex: 0 0 auto; width: auto; max-width: 100%; max-height: min(52vh, 460px); height: auto; - flex-shrink: 0; margin-inline: auto; overflow: hidden; } @@ -608,10 +625,13 @@ const getPreviewFrameStyles = () => ` .tutor-quiz-question[data-question='puzzle'] .tutor-puzzle-scatter { box-sizing: border-box; + flex: 0 0 auto; width: 100%; max-width: 100%; - min-height: 96px; - margin-top: 12px; + min-height: 150px; + height: auto; + max-height: none; + margin-top: 0; overflow: visible; } diff --git a/assets/src/scss/frontend/learning-area/_quiz.scss b/assets/src/scss/frontend/learning-area/_quiz.scss index 1019926a8f..c29728504b 100644 --- a/assets/src/scss/frontend/learning-area/_quiz.scss +++ b/assets/src/scss/frontend/learning-area/_quiz.scss @@ -9,6 +9,9 @@ $tutor-quiz-pagination-height: 60px; $tutor-quiz-content-bottom-offset: calc( #{$tutor-quiz-pagination-gap-from-footer} + #{$tutor-quiz-pagination-height} + #{$tutor-spacing-2} ); +// Chrome inside the questions slot for draw/pin: meta, card padding/gap, header, actions. +// Plain sum string so it interpolates cleanly into a single outer calc(). +$tutor-quiz-draw-pin-chrome: '#{$tutor-spacing-5} + 2.5rem + #{$tutor-spacing-8} * 2 + #{$tutor-spacing-7} + 4.5rem + 3rem'; .tutor-quiz { &-submission { @@ -52,6 +55,76 @@ $tutor-quiz-content-bottom-offset: calc( overflow: auto; } + // Scope to the active question only — all questions stay in the DOM (x-show), + // so a bare :has([data-question='…']) would leak layout rules to other types. + // Draw/pin: keep the card content-sized (hugs the scaled image) while the + // questions slot remains the size container that caps the image to the viewport. + &[data-question-layout-view='single_question']:has( + .tutor-quiz-question-wrapper-active .tutor-quiz-question[data-question='draw_image'] + ), + &[data-question-layout-view='single_question']:has( + .tutor-quiz-question-wrapper-active .tutor-quiz-question[data-question='pin_image'] + ), + &[data-question-layout-view='question_pagination']:has( + .tutor-quiz-question-wrapper-active .tutor-quiz-question[data-question='draw_image'] + ), + &[data-question-layout-view='question_pagination']:has( + .tutor-quiz-question-wrapper-active .tutor-quiz-question[data-question='pin_image'] + ) { + .tutor-quiz-questions { + justify-content: center; + overflow: hidden; + container-type: size; + } + + .tutor-quiz-question-wrapper-active { + flex: 0 1 auto; + min-height: 0; + max-height: 100%; + width: 100%; + overflow: hidden; + @include tutor-flex(column); + + .tutor-quiz-question { + flex: 0 1 auto; + height: auto; + min-height: 0; + max-height: 100%; + overflow: auto; + } + } + } + + // Puzzle: don't stretch the card when board/scatter are short; scroll only when they overflow. + &[data-question-layout-view='single_question']:has( + .tutor-quiz-question-wrapper-active .tutor-quiz-question[data-question='puzzle'] + ), + &[data-question-layout-view='question_pagination']:has( + .tutor-quiz-question-wrapper-active .tutor-quiz-question[data-question='puzzle'] + ) { + .tutor-quiz-questions { + justify-content: flex-start; + overflow: hidden; + } + + .tutor-quiz-question-wrapper-active { + flex: 0 1 auto; + min-height: 0; + max-height: 100%; + width: 100%; + overflow: hidden; + @include tutor-flex(column); + + .tutor-quiz-question { + flex: 0 1 auto; + height: auto; + min-height: 0; + max-height: 100%; + overflow: hidden; + } + } + } + &[data-question-layout-view='single_question'] { &:has(.tutor-quiz-questions-pagination) { .tutor-quiz-question-wrapper { @@ -1192,6 +1265,71 @@ $tutor-quiz-content-bottom-offset: calc( } } + &-submission[data-question-layout-view='single_question'], + &-submission[data-question-layout-view='question_pagination'] { + [data-question='draw_image'], + [data-question='pin_image'] { + .tutor-quiz-question-header { + flex-shrink: 0; + } + + .tutor-draw-image-question, + .tutor-pin-image-question { + @include tutor-flex(column, center, center); + flex: 0 1 auto; + min-height: 0; + margin-top: 0; + width: 100%; + } + + .tutor-draw-image-actions { + flex-shrink: 0; + align-self: stretch; + } + + .tutor-draw-image-wrapper, + .tutor-pin-image-wrapper { + position: relative; + flex: 0 1 auto; + min-height: 0; + width: fit-content; + max-width: 100%; + + img { + display: block; + // Cap against the questions slot (size container), not a stretched card. + // Interpolate the whole value so Sass does not strip the outer calc(). + max-height: #{"min(744px, calc(100cqh - (#{$tutor-quiz-draw-pin-chrome})))"}; + max-width: 100%; + width: auto; + height: auto; + object-fit: contain; + } + } + } + + // Puzzle: content-sized body; scrolls only when board + scatter exceed the card. + [data-question='puzzle'] { + .tutor-quiz-question-header { + flex-shrink: 0; + } + + .tutor-puzzle-question { + @include tutor-flex(column, center, flex-start); + flex: 0 1 auto; + min-height: 0; + max-height: 100%; + height: auto; + margin-top: 0; + width: 100%; + overflow-x: hidden; + overflow-y: auto; + overscroll-behavior: contain; + -webkit-overflow-scrolling: touch; + } + } + } + &-footer { padding-block: $tutor-spacing-8; margin-top: auto;