Skip to content

Commit 63d67c8

Browse files
committed
Change how stage overlays & fullscreen are handled
This makes the layout behavior for stage overlays much more consistent. Items whose overflow *should* be contained within the stage, like the monitors and color picker loupe, are now placed within the "stage" element directly. Items whose overflow should *not* be contained within the stage, like the target highlight box and dragged sprite, are now inside a "stage overlays" container element, which is properly positioned (taking into account the stage's border width) and sized. This is made possible by unifying stage layout across both fullscreen & non-fullscreen modes via moving the fullscreen overlay styles to the StageWrapper component. Whereas previously, the stage overlays were positioned *outside* of the stage in fullscreen and had to reposition themselves correctly, they are now positioned the same in both fullscreen and regular modes.
1 parent b025959 commit 63d67c8

File tree

5 files changed

+100
-101
lines changed

5 files changed

+100
-101
lines changed

src/components/gui/gui.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ const GUIComponent = props => {
336336

337337
<Box className={classNames(styles.stageAndTargetWrapper, styles[stageSize])}>
338338
<StageWrapper
339+
isFullScreen={isFullScreen}
339340
isRendererSupported={isRendererSupported}
340341
isRtl={isRtl}
341342
stageSize={stageSize}

src/components/stage-wrapper/stage-wrapper.css

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
@import "../../css/units.css";
22
@import "../../css/colors.css";
3+
@import "../../css/z-index.css";
34

45
.stage-wrapper * {
56
box-sizing: border-box;
@@ -9,3 +10,21 @@
910
/* Hides negative space between edge of rounded corners + container, when selected */
1011
user-select: none;
1112
}
13+
14+
.stage-wrapper.full-screen {
15+
position: fixed;
16+
top: $stage-menu-height;
17+
left: 0;
18+
right: 0;
19+
bottom: 0;
20+
z-index: $z-index-stage-wrapper-overlay;
21+
background-color: $ui-white;
22+
/* spacing between stage and control bar (on the top), or between
23+
stage and window edges (on left/right/bottom) */
24+
padding: $stage-full-screen-stage-padding;
25+
26+
/* this centers the stage */
27+
display: flex;
28+
flex-direction: column;
29+
align-items: center;
30+
}

src/components/stage-wrapper/stage-wrapper.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import PropTypes from 'prop-types';
22
import React from 'react';
3+
import classNames from 'classnames';
34
import VM from 'scratch-vm';
45

56
import Box from '../box/box.jsx';
@@ -22,7 +23,10 @@ const StageWrapperComponent = function (props) {
2223

2324
return (
2425
<Box
25-
className={styles.stageWrapper}
26+
className={classNames(
27+
styles.stageWrapper,
28+
{[styles.fullScreen]: isFullScreen}
29+
)}
2630
dir={isRtl ? 'rtl' : 'ltr'}
2731
>
2832
<Box className={styles.stageMenuWrapper}>

src/components/stage/stage.css

Lines changed: 22 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@
2121

2222
/* Make sure border is not included in size calculation */
2323
box-sizing: content-box !important;
24+
25+
/* enforce overflow + reset position of absolutely-positioned children */
26+
position: relative;
27+
}
28+
29+
.stage.full-screen {
30+
border: $stage-full-screen-border-width solid rgb(126, 133, 151);
2431
}
2532

2633
.with-color-picker {
@@ -43,62 +50,29 @@
4350
position: relative;
4451
}
4552

46-
.stage-wrapper-overlay {
47-
position: fixed;
48-
top: $stage-menu-height;
49-
left: 0;
50-
right: 0;
51-
bottom: 0;
52-
z-index: $z-index-stage-wrapper-overlay;
53-
background-color: $ui-white;
54-
/* spacing between stage and control bar (on the top), or between
55-
stage and window edges (on left/right/bottom) */
56-
padding: $stage-full-screen-stage-padding;
57-
}
58-
59-
/* wraps only main content of overlay player, not monitors */
60-
.stage-overlay-content {
61-
outline: none;
62-
margin: auto;
63-
border: $stage-full-screen-border-width solid rgb(126, 133, 151);
64-
padding: 0;
65-
border-radius: $space;
66-
67-
overflow: hidden;
68-
display: flex;
69-
justify-content: center;
70-
}
71-
72-
.stage-overlay-content-border-override {
73-
border: none;
74-
}
75-
76-
/* adjust monitors when stage is standard size:
77-
shift them down and right to compensate for the stage's border */
78-
.stage-wrapper .monitor-wrapper {
53+
/* we want stage overlays to all be positioned in the same spot as the stage, but can't put them inside the border
54+
because we want their overflow to be visible, and the bordered element must have overflow: hidden set so that the
55+
stage doesn't "spill" out from under its rounded corners. instead, shift these over by the border width. */
56+
.stage-overlays {
57+
position: absolute;
7958
top: $stage-standard-border-width;
8059
left: $stage-standard-border-width;
60+
61+
/* the overlay itself should not capture pointer events; only its child elements can do that */
62+
pointer-events: none;
8163
}
8264

83-
/* adjust monitors when stage is full screen:
84-
.stage-wrapper-overlay uses position: fixed instead of relative, so we need
85-
to adjust for the border using a different method */
86-
.stage-wrapper-overlay .monitor-wrapper {
87-
padding-top: calc($stage-full-screen-stage-padding + $stage-full-screen-border-width);
88-
padding-bottom: calc($stage-full-screen-stage-padding + $stage-full-screen-border-width);
65+
.stage-overlays.full-screen {
66+
top: $stage-full-screen-border-width;
67+
left: $stage-full-screen-border-width;
8968
}
9069

9170
.monitor-wrapper,
92-
.color-picker-wrapper,
93-
.frame-wrapper,
9471
.green-flag-overlay-wrapper {
9572
position: absolute;
9673
top: 0;
9774
left: 0;
98-
width: 100%;
99-
height: 100%;
10075
pointer-events: none;
101-
overflow: hidden;
10276
}
10377

10478
.dragging-sprite {
@@ -107,14 +81,15 @@ to adjust for the border using a different method */
10781
left: 0;
10882
z-index: $z-index-dragging-sprite;
10983
filter: drop-shadow(5px 5px 5px $ui-black-transparent);
110-
}
84+
}
11185

11286
.stage-bottom-wrapper {
11387
position: absolute;
11488
display: flex;
11589
flex-direction: column;
11690
justify-content: flex-end;
11791
top: 0;
92+
left: 0;
11893
overflow: hidden;
11994
pointer-events: none;
12095
}
@@ -141,6 +116,8 @@ to adjust for the border using a different method */
141116
}
142117

143118
.green-flag-overlay-wrapper {
119+
width: 100%;
120+
height: 100%;
144121
display: flex;
145122
justify-content: center;
146123
align-items: center;

src/components/stage/stage.jsx

Lines changed: 53 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,15 @@ const StageComponent = props => {
3737
return (
3838
<div>
3939
<Box
40-
className={classNames({
41-
[styles.stageWrapper]: !isFullScreen,
42-
[styles.stageWrapperOverlay]: isFullScreen,
43-
[styles.withColorPicker]: !isFullScreen && isColorPicking
44-
})}
45-
style={{
46-
minHeight: stageDimensions.height,
47-
minWidth: stageDimensions.width
48-
}}
40+
className={classNames(
41+
styles.stageWrapper,
42+
{[styles.withColorPicker]: !isFullScreen && isColorPicking})}
4943
onDoubleClick={onDoubleClick}
5044
>
5145
<Box
5246
className={classNames(
5347
styles.stage,
54-
{[styles.stageOverlayContent]: isFullScreen}
48+
{[styles.fullScreen]: isFullScreen}
5549
)}
5650
style={{
5751
height: stageDimensions.height,
@@ -66,64 +60,68 @@ const StageComponent = props => {
6660
}}
6761
{...boxProps}
6862
/>
63+
<Box className={styles.monitorWrapper}>
64+
<MonitorList
65+
draggable={useEditorDragStyle}
66+
stageSize={stageDimensions}
67+
/>
68+
</Box>
69+
70+
{isColorPicking && colorInfo ? (
71+
<Loupe colorInfo={colorInfo} />
72+
) : null}
6973
</Box>
70-
<Box className={styles.monitorWrapper}>
71-
<MonitorList
72-
draggable={useEditorDragStyle}
73-
stageSize={stageDimensions}
74-
/>
75-
</Box>
76-
<Box className={styles.frameWrapper}>
74+
75+
{/* `stageOverlays` is for items that should *not* have their overflow contained within the stage */}
76+
<Box
77+
className={classNames(
78+
styles.stageOverlays,
79+
{[styles.fullScreen]: isFullScreen}
80+
)}
81+
>
7782
<TargetHighlight
7883
className={styles.frame}
7984
stageHeight={stageDimensions.height}
8085
stageWidth={stageDimensions.width}
8186
/>
87+
<div
88+
className={styles.stageBottomWrapper}
89+
style={{
90+
width: stageDimensions.width,
91+
height: stageDimensions.height
92+
}}
93+
>
94+
{micIndicator ? (
95+
<MicIndicator
96+
className={styles.micIndicator}
97+
stageSize={stageDimensions}
98+
/>
99+
) : null}
100+
{question === null ? null : (
101+
<div
102+
className={styles.questionWrapper}
103+
style={{width: stageDimensions.width}}
104+
>
105+
<Question
106+
question={question}
107+
onQuestionAnswered={onQuestionAnswered}
108+
/>
109+
</div>
110+
)}
111+
</div>
112+
<canvas
113+
className={styles.draggingSprite}
114+
height={0}
115+
ref={dragRef}
116+
width={0}
117+
/>
82118
</Box>
83119
{isStarted ? null : (
84120
<GreenFlagOverlay
85121
className={styles.greenFlagOverlay}
86122
wrapperClass={styles.greenFlagOverlayWrapper}
87123
/>
88124
)}
89-
{isColorPicking && colorInfo ? (
90-
<Box className={styles.colorPickerWrapper}>
91-
<Loupe colorInfo={colorInfo} />
92-
</Box>
93-
) : null}
94-
<div
95-
className={styles.stageBottomWrapper}
96-
style={{
97-
width: stageDimensions.width,
98-
height: stageDimensions.height,
99-
left: '50%',
100-
marginLeft: stageDimensions.width * -0.5
101-
}}
102-
>
103-
{micIndicator ? (
104-
<MicIndicator
105-
className={styles.micIndicator}
106-
stageSize={stageDimensions}
107-
/>
108-
) : null}
109-
{question === null ? null : (
110-
<div
111-
className={styles.questionWrapper}
112-
style={{width: stageDimensions.width}}
113-
>
114-
<Question
115-
question={question}
116-
onQuestionAnswered={onQuestionAnswered}
117-
/>
118-
</div>
119-
)}
120-
</div>
121-
<canvas
122-
className={styles.draggingSprite}
123-
height={0}
124-
ref={dragRef}
125-
width={0}
126-
/>
127125
</Box>
128126
{isColorPicking ? (
129127
<Box

0 commit comments

Comments
 (0)