From 8dc26d8d307ff0fd71d142f2dfde649368edd5f2 Mon Sep 17 00:00:00 2001
From: Matthew Taylor <mewtaylor@gmail.com>
Date: Wed, 20 Dec 2017 14:49:27 -0500
Subject: [PATCH] Partially Implement GH-830: Add coming soon tooltips (#1069)

* Implement GH-830: Add coming soon tooltips

This implements coming soon tooltips for:
* the small stage size
* save, load and language

It also creates the component that can be copied over into the paint editor for use there as well.

Lastly, this does a small refactor on the full screen implementation to include multiple small screen sizes too.
---
 package.json                                  |   1 +
 src/components/button/button.jsx              |  34 +--
 src/components/coming-soon/aww-cat.png        | Bin 0 -> 4467 bytes
 src/components/coming-soon/coming-soon.css    |  68 ++++++
 src/components/coming-soon/coming-soon.jsx    | 143 ++++++++++++
 src/components/coming-soon/cool-cat.png       | Bin 0 -> 3829 bytes
 src/components/gui/gui.css                    |   8 -
 src/components/gui/gui.jsx                    |   8 +-
 .../language-selector/language-icon.svg       | Bin 3693 -> 1898 bytes
 .../language-selector/language-selector.css   |   5 +-
 .../language-selector/language-selector.jsx   |  49 +++--
 src/components/load-button/load-button.jsx    |  26 ++-
 src/components/menu-bar/menu-bar.css          |  10 +-
 .../prompt/icon--dropdown-caret.svg           | Bin 0 -> 950 bytes
 src/components/prompt/prompt.css              |  26 +++
 src/components/prompt/prompt.jsx              |  32 ++-
 .../stage-header/icon--fullscreen.svg         | Bin 0 -> 2620 bytes
 .../stage-header/icon--large-stage.svg        | Bin 0 -> 1167 bytes
 .../stage-header/icon--small-stage.svg        | Bin 0 -> 1173 bytes
 .../stage-header/icon--unfullscreen.svg       | Bin 0 -> 3006 bytes
 src/components/stage-header/icon--unzoom.svg  | Bin 2906 -> 0 bytes
 src/components/stage-header/icon--zoom.svg    | Bin 2902 -> 0 bytes
 src/components/stage-header/stage-header.css  |  45 +++-
 src/components/stage-header/stage-header.jsx  | 204 ++++++++++++------
 src/components/stage/stage.jsx                |  14 +-
 src/containers/save-button.jsx                |  18 +-
 src/containers/stage-header.jsx               |  17 +-
 src/containers/stage.jsx                      |   6 +-
 src/css/colors.css                            |   2 +
 src/reducers/gui.js                           |   4 +-
 src/reducers/stage-size.js                    |  55 +++++
 src/reducers/zoom.js                          |  23 --
 test/integration/test.js                      |   6 +-
 33 files changed, 615 insertions(+), 189 deletions(-)
 create mode 100644 src/components/coming-soon/aww-cat.png
 create mode 100644 src/components/coming-soon/coming-soon.css
 create mode 100644 src/components/coming-soon/coming-soon.jsx
 create mode 100644 src/components/coming-soon/cool-cat.png
 create mode 100644 src/components/prompt/icon--dropdown-caret.svg
 create mode 100644 src/components/stage-header/icon--fullscreen.svg
 create mode 100644 src/components/stage-header/icon--large-stage.svg
 create mode 100644 src/components/stage-header/icon--small-stage.svg
 create mode 100644 src/components/stage-header/icon--unfullscreen.svg
 delete mode 100644 src/components/stage-header/icon--unzoom.svg
 delete mode 100644 src/components/stage-header/icon--zoom.svg
 create mode 100644 src/reducers/stage-size.js
 delete mode 100644 src/reducers/zoom.js

diff --git a/package.json b/package.json
index 778cc2eea..50369a1f7 100644
--- a/package.json
+++ b/package.json
@@ -79,6 +79,7 @@
     "react-style-proptype": "3.1.0",
     "react-tabs": "2.1.1",
     "react-test-renderer": "16.2.0",
+    "react-tooltip": "3.4.0",
     "redux": "3.7.0",
     "redux-mock-store": "^1.2.3",
     "redux-throttle": "0.1.1",
diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx
index ae322d10f..59b39668f 100644
--- a/src/components/button/button.jsx
+++ b/src/components/button/button.jsx
@@ -9,23 +9,31 @@ const ButtonComponent = ({
     onClick,
     children,
     ...props
-}) => (
-    <span
-        className={classNames(
-            styles.button,
-            className
-        )}
-        role="button"
-        onClick={onClick}
-        {...props}
-    >
-        {children}
-    </span>
-);
+}) => {
+    if (props.disabled === true) {
+        onClick = function () {};
+    }
+
+    return (
+        <span
+            className={classNames(
+                styles.button,
+                className
+            )}
+            role="button"
+            onClick={onClick}
+            {...props}
+        >
+            {children}
+        </span>
+    );
+};
 
 ButtonComponent.propTypes = {
     children: PropTypes.node,
     className: PropTypes.string,
+    disabled: PropTypes.bool,
     onClick: PropTypes.func.isRequired
 };
+
 export default ButtonComponent;
diff --git a/src/components/coming-soon/aww-cat.png b/src/components/coming-soon/aww-cat.png
new file mode 100644
index 0000000000000000000000000000000000000000..bddfb8de9ee95ccef600bcb6a67ce5ed3c5ed4d5
GIT binary patch
literal 4467
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
FV1kgta$x`f

literal 0
HcmV?d00001

diff --git a/src/components/coming-soon/coming-soon.css b/src/components/coming-soon/coming-soon.css
new file mode 100644
index 000000000..7c3bdeb14
--- /dev/null
+++ b/src/components/coming-soon/coming-soon.css
@@ -0,0 +1,68 @@
+/*
+ * NOTE: the copious use of `important` is needed to overwrite
+ * the default tooltip styling, and is required by the 3rd party
+ * library being used, `react-tooltip`
+ */
+
+@import "../../css/colors.css";
+
+.coming-soon {
+    background-color: $data-primary !important;
+    border: 1px solid hsla(0, 0%, 0%, .1) !important;
+    border-radius: .25rem !important;
+    box-shadow: 0 0 .5rem hsla(0, 0%, 0%, .25) !important;
+    padding: .75rem 1rem !important;
+    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !important;
+    font-size: 1rem !important;
+    line-height: 1.25rem !important;
+    z-index: 100 !important;
+}
+
+.coming-soon:after {
+    content: "";
+    border-top: 1px solid hsla(0, 0%, 0%, .1) !important;
+    border-left: 0 !important;
+    border-bottom: 0 !important;
+    border-right: 1px solid hsla(0, 0%, 0%, .1) !important;
+    border-radius: .25rem;
+    background-color: $data-primary !important;
+    height: 1rem !important;
+    width: 1rem !important;
+}
+
+.show,
+.show:before,
+.show:after {
+    opacity: 1 !important;
+}
+
+.left:after {
+    margin-top: -.5rem !important;
+    right: -.5rem !important;
+    transform: rotate(45deg) !important;
+}
+
+.right:after {
+    margin-top: -.5rem !important;
+    left: -.5rem !important;
+    transform: rotate(-135deg) !important;
+}
+
+.top:after {
+    margin-right: -.5rem !important;
+    bottom: -.5rem !important;
+    transform: rotate(135deg) !important;
+}
+
+.bottom:after {
+    margin-left: -.5rem !important;
+    top: -.5rem !important;
+    transform: rotate(-45deg) !important;
+}
+
+.coming-soon-image {
+    margin-left: .125rem;
+    width: 1.25rem;
+    height: 1.25rem;
+    vertical-align: middle;
+}
diff --git a/src/components/coming-soon/coming-soon.jsx b/src/components/coming-soon/coming-soon.jsx
new file mode 100644
index 000000000..e16ae80be
--- /dev/null
+++ b/src/components/coming-soon/coming-soon.jsx
@@ -0,0 +1,143 @@
+import bindAll from 'lodash.bindall';
+import classNames from 'classnames';
+import {defineMessages, injectIntl, intlShape, FormattedMessage} from 'react-intl';
+import PropTypes from 'prop-types';
+import React from 'react';
+import ReactTooltip from 'react-tooltip';
+
+import styles from './coming-soon.css';
+
+import awwCatIcon from './aww-cat.png';
+import coolCatIcon from './cool-cat.png';
+
+const messages = defineMessages({
+    message1: {
+        defaultMessage: 'Don\'t worry, we\'re on it {emoji}',
+        description: 'One of the "coming soon" random messages for yet-to-be-done features',
+        id: 'gui.comingSoon.message1'
+    },
+    message2: {
+        defaultMessage: 'Coming Soon...',
+        description: 'One of the "coming soon" random messages for yet-to-be-done features',
+        id: 'gui.comingSoon.message2'
+    },
+    message3: {
+        defaultMessage: 'We\'re working on it {emoji}',
+        description: 'One of the "coming soon" random messages for yet-to-be-done features',
+        id: 'gui.comingSoon.message3'
+    }
+});
+
+class ComingSoonContent extends React.Component {
+    constructor (props) {
+        super(props);
+        bindAll(this, [
+            'setHide',
+            'setShow',
+            'getRandomMessage'
+        ]);
+        this.state = {
+            isShowing: false
+        };
+    }
+    setShow () {
+        // needed to set the opacity to 1, since the default is .9 on show
+        this.setState({isShowing: true});
+    }
+    setHide () {
+        this.setState({isShowing: false});
+    }
+    getRandomMessage () {
+        // randomly chooses a messages from `messages` to display in the tooltip.
+        const images = [awwCatIcon, coolCatIcon];
+        const messageNumber = Math.floor(Math.random() * Object.keys(messages).length) + 1;
+        const imageNumber = Math.floor(Math.random() * Object.keys(images).length);
+        return (
+            <FormattedMessage
+                {...messages[`message${messageNumber}`]}
+                values={{
+                    emoji: (
+                        <img
+                            className={styles.comingSoonImage}
+                            src={images[imageNumber]}
+                        />
+                    )
+                }}
+            />
+        );
+    }
+    render () {
+        return (
+            <ReactTooltip
+                afterHide={this.setHide}
+                afterShow={this.setShow}
+                className={classNames(
+                    styles.comingSoon,
+                    this.props.className,
+                    {
+                        [styles.show]: (this.state.isShowing),
+                        [styles.left]: (this.props.place === 'left'),
+                        [styles.right]: (this.props.place === 'right'),
+                        [styles.top]: (this.props.place === 'top'),
+                        [styles.bottom]: (this.props.place === 'bottom')
+                    }
+                )}
+                getContent={this.getRandomMessage}
+                id={this.props.tooltipId}
+            />
+        );
+    }
+}
+
+ComingSoonContent.propTypes = {
+    className: PropTypes.string,
+    intl: intlShape,
+    place: PropTypes.oneOf(['top', 'right', 'bottom', 'left']),
+    tooltipId: PropTypes.string.isRequired
+};
+
+ComingSoonContent.defaultProps = {
+    place: 'bottom'
+};
+
+const ComingSoon = injectIntl(ComingSoonContent);
+
+const ComingSoonTooltip = props => (
+    <div className={props.className}>
+        <div
+            data-delay-hide={props.delayHide}
+            data-delay-show={props.delayShow}
+            data-effect="solid"
+            data-for={props.tooltipId}
+            data-place={props.place}
+            data-tip="tooltip"
+        >
+            {props.children}
+        </div>
+        <ComingSoon
+            className={props.tooltipClassName}
+            place={props.place}
+            tooltipId={props.tooltipId}
+        />
+    </div>
+);
+
+ComingSoonTooltip.propTypes = {
+    children: PropTypes.node.isRequired,
+    className: PropTypes.string,
+    delayHide: PropTypes.number,
+    delayShow: PropTypes.number,
+    place: PropTypes.oneOf(['top', 'right', 'bottom', 'left']),
+    tooltipClassName: PropTypes.string,
+    tooltipId: PropTypes.string.isRequired
+};
+
+ComingSoonTooltip.defaultProps = {
+    delayHide: 0,
+    delayShow: 0
+};
+
+export {
+    ComingSoon as ComingSoonComponent,
+    ComingSoonTooltip
+};
diff --git a/src/components/coming-soon/cool-cat.png b/src/components/coming-soon/cool-cat.png
new file mode 100644
index 0000000000000000000000000000000000000000..15b2151e35bd84cfa154e6af8fd20607ca4d5e9e
GIT binary patch
literal 3829
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

literal 0
HcmV?d00001

diff --git a/src/components/gui/gui.css b/src/components/gui/gui.css
index 3d08cadf6..2c0533e98 100644
--- a/src/components/gui/gui.css
+++ b/src/components/gui/gui.css
@@ -143,14 +143,6 @@
     overflow: hidden;
 }
 
-.stage-menu-wrapper {
-    display: flex;
-    flex-shrink: 0;
-    align-items: center;
-    height: $stage-menu-height;
-    padding: $space;
-}
-
 .extension-button-container {
     width: 3.25rem;
     height: 3.25rem;
diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx
index 349e20d5e..639c8cbd3 100644
--- a/src/components/gui/gui.jsx
+++ b/src/components/gui/gui.jsx
@@ -112,13 +112,7 @@ const GUIComponent = props => {
 
                     <Box className={styles.stageAndTargetWrapper}>
                         <Box className={styles.stageMenuWrapper}>
-                            <MediaQuery minWidth={layout.fullSizeMinWidth}>{isFullSize => (
-                                <StageHeader
-                                    height={isFullSize ? layout.fullStageHeight : layout.smallerStageHeight}
-                                    vm={vm}
-                                    width={isFullSize ? layout.fullStageWidth : layout.smallerStageWidth}
-                                />
-                            )}</MediaQuery>
+                            <StageHeader vm={vm} />
                         </Box>
                         <Box className={styles.stageWrapper}>
                             <MediaQuery minWidth={layout.fullSizeMinWidth}>{isFullSize => (
diff --git a/src/components/language-selector/language-icon.svg b/src/components/language-selector/language-icon.svg
index 3644ab6fde2247b0cd949231071e98bc95638a10..42bd409ab18e8ed0e737e6547c7ecc89ea57df0d 100644
GIT binary patch
literal 1898
zcma)7QE!_t5Pt8k@Vu8+3dS}D>?)+vB5g05G^yLm-dJ!6D}e}TlKuOg4J4PU(i%mI
z`F#HF^LKY-`Ec6R<Y2qLYMYD-#woGQrY)+b%;?V_p94)vKjcl3*KK1n+O+gxb+hab
zB{^2bu+6CC`x7NwTb0{kemYe4_^CZ*loL**`%;`lPy%V2KBL=V*x!fY@pxp%h_ziA
zO3rx*^i#<Fsjiymw*rMRCiJ^>bwl8@{161>i*0O|4{di(9-r;7*%Fm9L2gy7q`V^m
zK^cFyTf3|B>AGyw?!taN69g0GPz|+Rea)NlB`@tV9G}N@h3z-1b!YRz7GTD(oiegz
z=(pymr+(!S_!*IsR7FO=1783}^h4J^dt)0rKLwMuu>DlkwR7EVx^>XK)DUeCwrPvv
zd;m<cn|z<qu6=0$Zuj}78va57n2fKY{<IYodJG!{dGAJ1^F`+q8T|<5fX@t^l{wnW
z@rh#S@}_@kyIn^8vIc8zB^xOgWM199I_XdEb1)Em`6gnPM6q0GCWJIf2u;>ACM1)I
zmQfrLzf4kySd6=AqEg}yMQ(}Fb;L}Za(58JoW)uvLZk`67iJ7&5g7M`kcB4%ak~fu
zbSf2C35M55H^%21BH|fB8h%mVJCD9+pnIUPoNw2Kcx9(xMsw}$O#EfR&IvOtRVI$X
zLjq7L;z(<`fTc{hP(nIX!r(v+oI%P+kFEtMk7Et)Ereo`i6Xc(F--9^am5);R<1bS
z2kvWz(RISKh*DQw3`6M?BU2t5OstqmK%6f%QlVHZX6B1z#iUXZ#EJ#F9zva+vk?eR
zn9|ZI76cJP>NN6=1L#>r1ipz8U1P~i%gIi3Jy&H7zB!9r?nyF+*T_1IW1lbFs3=$n
zsvuGgs4qXd-V7lluKOx_PhW8ushCg018*7ar<Ht#u7wd*e$>wJRolXg<Ns}o>0@S8
z;@%17iv9v$(WmdB_cJA++tmULH=KiBM~`qneyN*|D|+)b{W2^sQ+R&xi>3QJTm1uf
CZO0@4

literal 3693
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
V&ra539k2RB<p1!ZztLVD{sq2uFpvNM

diff --git a/src/components/language-selector/language-selector.css b/src/components/language-selector/language-selector.css
index a060131a8..0ae9e0a10 100644
--- a/src/components/language-selector/language-selector.css
+++ b/src/components/language-selector/language-selector.css
@@ -1,3 +1,4 @@
+@import "../../css/colors.css";
 @import "../../css/units.css";
 
 .group {
@@ -9,7 +10,7 @@
 
 .language-icon {
     height:  2rem;
-    display:none;
+    display: none;
 }
 
 .language-select {
@@ -19,7 +20,7 @@
     user-select: none;
     outline: none;
     background: rgba(255, 255, 255, 0.5);
-    color: #3373cc;
+    color: $motion-tertiary;
     font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
 }
 
diff --git a/src/components/language-selector/language-selector.jsx b/src/components/language-selector/language-selector.jsx
index d3d3bb48d..db846fef5 100644
--- a/src/components/language-selector/language-selector.jsx
+++ b/src/components/language-selector/language-selector.jsx
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
 import React from 'react';
 
 import Box from '../box/box.jsx';
+import {ComingSoonTooltip} from '../coming-soon/coming-soon.jsx';
 import locales from 'scratch-l10n';
 import languageIcon from './language-icon.svg';
 import styles from './language-selector.css';
@@ -12,27 +13,33 @@ const LanguageSelector = ({
     ...props
 }) => (
     <Box {...props}>
-        <div className={styles.group}>
-            <img
-                className={styles.languageIcon}
-                src={languageIcon}
-            />
-            <select
-                aria-label="language selector"
-                className={styles.languageSelect}
-                value={currentLocale}
-                onChange={onChange}
-            >
-                {Object.keys(locales).map(locale => (
-                    <option
-                        key={locale}
-                        value={locale}
-                    >
-                        {locales[locale].name}
-                    </option>
-                ))}
-            </select>
-        </div>
+        <ComingSoonTooltip
+            place="bottom"
+            tooltipId="language-selector"
+        >
+            <div className={styles.group}>
+                <img
+                    className={styles.languageIcon}
+                    src={languageIcon}
+                />
+                <select
+                    disabled
+                    aria-label="language selector"
+                    className={styles.languageSelect}
+                    value={currentLocale}
+                    onChange={onChange}
+                >
+                    {Object.keys(locales).map(locale => (
+                        <option
+                            key={locale}
+                            value={locale}
+                        >
+                            {locales[locale].name}
+                        </option>
+                    ))}
+                </select>
+            </div>
+        </ComingSoonTooltip>
     </Box>
 );
 
diff --git a/src/components/load-button/load-button.jsx b/src/components/load-button/load-button.jsx
index dd94a2a11..0f580278c 100644
--- a/src/components/load-button/load-button.jsx
+++ b/src/components/load-button/load-button.jsx
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
 import React from 'react';
 
 import ButtonComponent from '../button/button.jsx';
+import {ComingSoonTooltip} from '../coming-soon/coming-soon.jsx';
 
 import styles from './load-button.css';
 
@@ -13,13 +14,24 @@ const LoadButtonComponent = ({
     ...props
 }) => (
     <span {...props}>
-        <ButtonComponent onClick={onClick}>{title}</ButtonComponent>
-        <input
-            className={styles.fileInput}
-            ref={inputRef}
-            type="file"
-            onChange={onChange}
-        />
+        <ComingSoonTooltip
+            place="bottom"
+            tooltipId="load-button"
+        >
+            <ButtonComponent
+                disabled
+                onClick={onClick}
+            >
+                {title}
+            </ButtonComponent>
+            <input
+                disabled
+                className={styles.fileInput}
+                ref={inputRef}
+                type="file"
+                onChange={onChange}
+            />
+        </ComingSoonTooltip>
     </span>
 );
 
diff --git a/src/components/menu-bar/menu-bar.css b/src/components/menu-bar/menu-bar.css
index a9d3b37fa..a85926d39 100644
--- a/src/components/menu-bar/menu-bar.css
+++ b/src/components/menu-bar/menu-bar.css
@@ -1,3 +1,4 @@
+@import "../../css/colors.css";
 @import "../../css/units.css";
 
 .menu-bar {
@@ -23,7 +24,7 @@
         width: 100%; 
     */
     font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-    background-color: #4c97ff;
+    background-color: $motion-primary;
     color: white;
 }
 
@@ -56,11 +57,6 @@
     line-height: $menu-bar-height; 
     cursor: pointer;
     text-decoration: none;
-    color: white;
+    color: $motion-tertiary;
     user-select: none;
 }
-
-.menu-item:hover {
-    opacity: 0.8;
-    background: rgba(255, 255, 255, 0.2)
-}
diff --git a/src/components/prompt/icon--dropdown-caret.svg b/src/components/prompt/icon--dropdown-caret.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8e08eda35e5cb30d80ec7d97a21352dbe6098f7a
GIT binary patch
literal 950
zcmZuw+m4$s5PjdTaNU<y3dVPv2w166+m~IbQri!p!3!uXj=&A+-*>n~CDrC7_L-S;
zW{!vS@%q}Li|dERcNu1cV&uA`FPpB)@XsG#B8$-wimohL-?<ET9zW&}>2Rsg*p#8p
zusvTfs$EmnA;W6ATpBli^4APgM3F@bkbeRUBarNd4A&u?_i;RqBN+wpeHC*`X$;hB
z%Kq9m-RZ4FmLy3$M{)ju;FrFOBJ|aDt}lY`_vrh{g=3ARB@BI#hAa9JMQEe=%h&F;
zDb`WR(Z9ySQWHfhWoSa{^0N2m(vMwqEP5BBsxSVe@e*2;OE(<zL+^^<O7JAqt2jyH
zIdsc<8S)8%zXhpKQ)c*EQMm{_8A9(*v%j6Y-J;cD2){IKJDEQPr*qW*ZXw%UT<6Pj
zHDNYlp?#z48_9cR)MukMHFMp$fX<<zXSq}8AP9KIsi78bf=I=*pj7W9v58I;l@rP(
z<0dfzPz|sWjG-q=1e2NxW%!N}OSRUV8+3>$VN_bfSi&G662Y~y0^Q*hWTlpza)Gu)
z)0t9fgkb0ZNrGF;rLeoXS_qkdv>{vry;1r<SX(8mmST5D1FNz21GwQrN?{B~8+g;D
zfeBZV%}`I07?mVKGqd&JAc>NRvM}D(FiE)4ltSm=DY%U11-O4H3_CKt#Ihsv!^G9P
LFw-HOK9Bq_1LgV`

literal 0
HcmV?d00001

diff --git a/src/components/prompt/prompt.css b/src/components/prompt/prompt.css
index 94b907c04..527901233 100644
--- a/src/components/prompt/prompt.css
+++ b/src/components/prompt/prompt.css
@@ -49,3 +49,29 @@
 .button-row button + button {
     margin-left: 0.5rem;
 }
+
+.more-options {
+    border-top: 1px dashed hsla(0, 0%, 0%, .25);
+    overflow: visible;
+    padding: 1rem;
+    text-align: center;
+    margin: 0 0 1rem;
+}
+
+.more-options-accordion {
+    width: 60%;
+    margin: 0 auto;
+}
+
+.more-options-text {
+    opacity: .5;
+}
+
+.more-options-icon {
+    width: .75rem;
+    height: .75rem;
+    margin-left: .5rem;
+    vertical-align: middle;
+    padding-bottom: .2rem;
+    opacity: .5;
+}
diff --git a/src/components/prompt/prompt.jsx b/src/components/prompt/prompt.jsx
index 4fca4cb4a..b99580b79 100644
--- a/src/components/prompt/prompt.jsx
+++ b/src/components/prompt/prompt.jsx
@@ -1,10 +1,23 @@
+import {defineMessages, FormattedMessage} from 'react-intl';
 import PropTypes from 'prop-types';
 import React from 'react';
-import Modal from '../modal/modal.jsx';
+
 import Box from '../box/box.jsx';
+import {ComingSoonTooltip} from '../coming-soon/coming-soon.jsx';
+import Modal from '../modal/modal.jsx';
 
 import styles from './prompt.css';
 
+import dropdownIcon from './icon--dropdown-caret.svg';
+
+const messages = defineMessages({
+    moreOptionsMessage: {
+        defaultMessage: 'More Options',
+        description: 'Dropdown message for variable/list options',
+        id: 'gui.gui.variablePrompt'
+    }
+});
+
 const PromptComponent = props => (
     <Modal
         className={styles.modalContent}
@@ -24,6 +37,23 @@ const PromptComponent = props => (
                     onKeyPress={props.onKeyPress}
                 />
             </Box>
+            <Box className={styles.moreOptions}>
+                <ComingSoonTooltip
+                    className={styles.moreOptionsAccordion}
+                    place="right"
+                    tooltipId="variable-options-accordion"
+                >
+                    <div className={styles.moreOptionsText}>
+                        <FormattedMessage
+                            {...messages.moreOptionsMessage}
+                        />
+                        <img
+                            className={styles.moreOptionsIcon}
+                            src={dropdownIcon}
+                        />
+                    </div>
+                </ComingSoonTooltip>
+            </Box>
             <Box className={styles.buttonRow}>
                 <button
                     className={styles.cancelButton}
diff --git a/src/components/stage-header/icon--fullscreen.svg b/src/components/stage-header/icon--fullscreen.svg
new file mode 100644
index 0000000000000000000000000000000000000000..9d26e43918902d57eaa8c1719ee4c133877d85f9
GIT binary patch
literal 2620
zcmb7G+ioI95PjdT=uBRAC20Cm)fWp`DJaehks>Ae0Aj{~j0X#5ZGV1F4-8Z6T8c8V
z<gU}z)m?S!ls*0W{=8SO_3^YjG_%TTQ>nUnIIMTgW>)?E*ZnwE>eQ~9^=f};>RHts
zs;~1;)6?rlz3tZRc2+s_@?NQJz1wWt-g@2DZ@(PgXO&S#x$;xVOKhcZZF8Dc+qQkV
zn@rx`-t?Q-hvR1Aj4>00zqs7J?|049M~*h<Jn43;`6q>M`qOx<eyf}MxM~l_JN4&N
z-9Bs;MQzn*Vsh?_8Y^+*KZkAoyjxw;)enc~$?1G%Jidf%ckRBO-+$ZhPY=hsZl;qn
za=vg~pC0CmW4&tYHOkR$FL&zcq}%Gf9#8Xv;MW=1sNH&2{ju8AW0d059uH4lX`8yY
z#+Tw^`*FA5m%5kDvK}A5?crU&*3DtPzU1EJe-1l5wm<tbNB%Xka24*4*W4=A9#_rj
z@o;>eRo!xr#6EisM(~YPzxwiBq%PXa3h5)O->ui)CzJh%v}fbl1yW1vG*L={Xyi3<
zN*?^FW!BzO@@(CRb@HBEB&!xlXO7m#Y)3&`lN?8rRMO;Aj)?#oA8bw?Xagl?j{qS=
zc4WO;M4iboB^v<yXtK#Rse(ohE?B%R2WM<>jIezK(jhs^+2OrLv&VZlj;v-fhHc>T
z-ViuZAUiTxA|FF3szughL(I$soNU59A(G0Pv(M3m2pBPpi#|HMI_vBS?k0S<u|)ZT
zb<X0AMlE0^N0d>v+W@uz7G+NCGpo+@DaGUo1zf@=ZIZzao)D&(5CB=Est}Zsr^^N9
z%m#5%L4V+_>KgUFbe*lx!-eE?4;Rk+Z+hjv)Wl{Ja>^r=in0UIg?-Izt>;or6qZa%
zE~sUxH|mPM7!?u%NCHa>)`naHJ$V#$%GMz<r&x2a2898b5jy4wtn?01#Ch*AI+A6z
zKzDE?wrG^310sR+qzdZDM_-<1e1r?gA0m`i#3{ma(V@5?xil(m%UGeO@LKePWzTuk
z)yjH9Xf>2D;cB8#U{2Q9m=wxwLZRCiG-tfmIiMymTv2&}E{*mng1Q9JSkMJ#BbejT
zX2Q=DBcZu6QtymlQ7}SZ8swBM%I7kU!{CVfyw9q%V@$DB1TfmQyb9<?L<ze6|E2pz
z>;v6W?1FA7c0sog`#`r4`@ohIyWm@hUGOc$K12{=7kmq?3%+l(E(n)e7mVLZRgiwW
zal<>rE@{8@G&f=|me9I^iU+9|>#B4~zL2_Pf8b59kG~cFEp{~HWnkP$eHipo>SEAK
zsf$4`q&^J#LF&VlmQojUUPxWcc_H;7f{?nL^Fr%l&Ua~Ev@XUx;9l!u$^-4SE=IgS
zmst1ny+|EqKj4KI=5^V)Nd0VGwGLB=y|b=r$Ekj_4`K)S15twP_%Yej$z~Y!SEE}@
J%RgxIe*s>oO49%U

literal 0
HcmV?d00001

diff --git a/src/components/stage-header/icon--large-stage.svg b/src/components/stage-header/icon--large-stage.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ed4361ca3ac88804e87a1531ea79c7fc53201721
GIT binary patch
literal 1167
zcma)*O^=%}5QgvjE2i!xkuYFB!X|>ORHXEhm8x!g>5YN|ZipR$H%b3}#|Dz^Hiueh
z{5|u|GdO*^99lT>t`|yXgt<NeE=yGjS!d+?w+($H(Cb20MXMywh*ach{gC#j8qT89
zO-2I$cp=bmQ8#*;odiFBQkRVQ;6q?O@-_$~fMI2ykw)v|%Ja_WvwIF*)zx0$`@V<n
z$0MstE9Cy(LAG2jJ-bWR4}dNGKq-9Yl6Qqx-3ngzT$c?*iOXOX#ZeH<fx?@JKUKpI
zq8QV4OLg%2;SQyvOD%NE*W042IlSls?W`!ZIPrPv4SPfAiudI@?|7kkg<y0uMt4)s
zZcV3l{o1TxH>}hks*HR=#}uLTx>I`#S@LN{N6fgr6K!iMU^dN|cCRg-<|i&yRb4M2
zFkTkNjCAT%{=NK539Rz4J}9u@1{F3-YO|zMmXp(re2nsCve}HR%{9}~;c9CDQT$KP
z&V(Eh5zt*B`<?0z8L`6_`OHEWON`BdXdKPod9|L81yV#f&&=^*n+%2puw~BG=Dr(6
zNy6eFHj4{4S%h(z#0+sJ4r6W{2f<^MfR7W{q8&_5-yOaAf!ol*=fI*k^cNxeTYwSr
zgV>6F<t09fy5$7xX_Ve*S}q37H36%gg(d@Qa~4j*9Qr;+<lF=Ri;QBlu^Yq&!qndp
zGX5UdI{l9>^l6-1YXF&e4078|65)+nWQ-XY{7Bc@_#YxPSI6J?v7}yo<8+<aL2BOo
F`VZpxIBfs`

literal 0
HcmV?d00001

diff --git a/src/components/stage-header/icon--small-stage.svg b/src/components/stage-header/icon--small-stage.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f73f5b242583675de267ad84dde99a7173a7e032
GIT binary patch
literal 1173
zcma)*O^=%}5QgvjE2i#cSHfWP5jHExN{!lHwo=t?FTGK4z+GZT;7!th-?2?X8ttJL
z8vHr)&NFuLc-;1|7sDvEDhUr60ikN$NY$3)$M;Y4p1^1-)l|J!q9jU_$JI?S?prv>
z#&ji#+3rZ76SD2hX|$K(@IfC-!hk_+KXMs_6Tq-)EJ<g~?jec}heLQsLOrxm%ovN%
z{j}xb*h}^D)<(WuE+e-}RyTmHct<IG7D^12(Zd5gzX(%zkmezW+cZn#_zoysMEs>Y
zv6a=7ZdmJWH2O1?PA-i!y;wbOtG<V4Q?&warK)Np_u{UI{HhP$h_PO+2T>W(AR5z6
z@xvl=OQ&6%ab;)l=Vw}wO-a6@Yl>J#Gw2tGS&7q#PM~plBm3Ugz%JT89bS9fE%rj`
zra2!#WTLKiB^mUq`gi)bmRM&$?-e+7UWLn(x;*Ke=gDnJ-e-CCG0!I6_MmNrKRjAU
z6z>XVa(UPcl^QpC*p|d~dn9z5gji;50i;v!?#iq4ysMBS;`zb@22Y$#md7{<&UVeh
zG|h9K#hIO4g!v-Ll04&xG!Hlrvn-D9(;OHM;0diaYkIYH_5*V_z(>K;EMbcT{Vl*s
z`AJ;WzKI&2M%xR5HMLr2qK=G(GpFFyCoTtT*E~5X3+Q!_G?*0tPpxFMiG$$n8!D#z
zaW2z;iL&0jXN=;*;BReX&g3qnB4M6*_(;-Lf}yT!B6O{Hf8NGYMD5J!JaC=DzWmi+
D4$?Xw

literal 0
HcmV?d00001

diff --git a/src/components/stage-header/icon--unfullscreen.svg b/src/components/stage-header/icon--unfullscreen.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bf4a3e450de8aa70b034203d69824860d568f1c0
GIT binary patch
literal 3006
zcmb7G+iv4F5PjdTVAYomAkiG&8Q5N+Mz=36P@wGxxUpgzaiqXj;(UG&WznM3EYcVY
zEa#9j9L^k_$@JUn<DR|LhvTkoW(9Fku)4Wx*SlsjEB^lLd*usu>{iWswQrkxRy1w#
zZT@9?eA%$mZryEXg%nS(1>4rU&9+O{%dS5C(!S0L!32}>Uy)xz1;e$?aaL@*?&)?i
zIh{`Yq<DMSOr#KEg7CwU+t>ZBd3f(2g%BqFZZZGD@SFZrRqVIAsSm5JJ>0TCAL{OI
z%e3djzG^3pxM3B`Zv3a+){nc@@LYb^K2DBjpQ;){cDrt0&!3y>{&~MY-W}??nNH5&
z`ObBHyqhl$^{T7as7SXRuI1B7zm-niALkLle`jRFcI#R3$7)kosK&87v=4oCn>tz5
zP+x4{@Amsx`nVa_)!})M)AdW;wCnZo{JsR|uvhse_n(b3zdDnh9z43ksyW`bhsRmb
zFZX!MSIN-_{7RNqH*Y+9@23@BjEDSAhAZVoP^IR|2xX+zY)P7H?Y-5yR9qYH6}kqP
zxFYS9q0(@#l$K5tTae(vI8rW@mXq+(IN=#kt$c7^0~N|r@Mn~)_QoiLu+|x=NwG!X
zK}(}OS-{GPAOd+7QD>~QgzSQqf~+(#a0;Qh^^#1G$W3yikdkpFaifJWWKEy4wZ?0!
zOM(0FB%!@S&croY7mNX}$>SpHGy`mc3Qjt}h#{m?PR6{62c>bG-fS#UK}%8+k`#!G
z!bq(HD)%OU1wg2@H!9!}(Nx|$uQY17gsr*o!k`BlVWO!eii4*z1T}c43>v5jMj#GS
zdZ%?oPtWg>YvA9z3?X%)NLt;nL)%66Anvevb9U}IRb?*K=u_a!h&(!f8Ie}$H@(m+
z)|`T{!G{thv^q$T3D4!IBq<ZSg~n;&y|io@`-#4RdS%~b3mQnaFkEQq(f?2e?g622
zlA$P;1PTu@AhHV%SY)Tx2#fM6h>{0E!9U})Ay5&pMJRNeMO13#RG*qq4rf#zA+jBA
z8Xp9{0^Hyw@<Lw>R$wjC1>wjjg9x!1qy!=?&?AqlwYCv9o&-71;3sV4lZt2vNLWgs
z!WtY!Ycq5ix#7SKj}Mb9TYx$a)G$_4eojQggS`Q7?+r_YXM*^!Kv@a|+Q2_r#^FY=
zD-zy$7i$t>d=W7(!0+`cW0d*<qY@=bb|K0~j2c}=a^0}cGU`gQMn>h5l`$%ptc+2a
zWQ~l<6l<hZE?60*GQr9yl?m1uA=9gjQJGw2jJlGmj8eH=Wt_TJn~YZ18&}MNUggBP
zJ}IvBDq5Lb2?)`sR?)hMRnD$Vt#WpaeaqNoK4e!S%_qn;y8It*;bR(x;gwe5al<go
zwF*blFwC_I>og2Atpb{c;V4$U+j$mZc~Pru76MLcmCZujoYX20k;zp)43T}(tN5y6
z81_#c^a^mAg@BV@0ZpS2Xwoa7X%1%S66-Vsqg=sEQ!qOPrH&heT%E0pUPUt#th1RE
t3vOuu#$*S<0{WkJWrT7+Ak;;qKA~5c&&Pr_oovRLcrp6LH2#S^{}-kdt)Kt^

literal 0
HcmV?d00001

diff --git a/src/components/stage-header/icon--unzoom.svg b/src/components/stage-header/icon--unzoom.svg
deleted file mode 100644
index c929966dc735c3c1aeaadc4c10fdfa82306596f6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2906
zcmd5;%Wm8@6y5tPSb38mCPh(iMRI`F2$DrNZQ26e(Gq7ywL}gm&W!D^@1-P4;}?)F
zidL`z@jl3V?m4`g^3#3ap`*}4t7PQ`gnCHGS~acQR^D&lKI6<ogW<B_osy#Rr1Cyp
zUz9&!jDFIB8_}RsYj)_Xyc=r17wFy2n0?{<r_+hFvymvh_1`0muP-jj;kdm(2*J5>
zD4M$R=7jx0cVl2v`=S%QkY?}$68PR4Ua#S`J-t1OTJ^n>!<Z?D%d=qJY?jS!HK%Y4
z3i3SnDf1b_5P^pWY4|;UnhG_(mdYrlKKRx{zAvg6prL#CU&5V%4C<h3v4I8&B8Bm9
zzTNoFi79DJvmREselFX*XtLzJ81}ptgYSaJ{4<7w(a<)P2T0hsIJJ%0RbDu)cB0+x
z%(6VT;`F1suRMw<3K{&3Ij+c}QMEm_^4eNSj1Tfrsh+qlxhjgK0!niBp%F*Xp@Y1W
z>Lk5uV7Tms;SD$3vW<|f&snlD078JT;+LDxHrzgCT^D~SeK#+`VgvZCIzaVv&KTF!
z1$4OQ=DO|qR#*x@fc{E<bu4?7U^5SUu^8rUwV0?{dVj9hrtVvt<o{~guKQ{a@sRK8
zgi7tEt?9&SEd9CqDXR3(z?Hs(K6a)Nn_())cEzredG~T*!BWszs;0m_R8Xr<>B_s@
zjL%3KLbpmcLOWM7KC^3~3K%`u>xZ>6aL4Rmpij~jC=BqzyqL}E_AgNzqdK9vtU(Kb
zOW11A)@$}d+lbd3OBEKva**5ZiFerXMx82e5+rD59yi6QmEgd$tb?4rNS`B|)bq?C
zu^nD|8O`v9ojO?{mAB#DAfETD7koHqfniQ+P+k;}B+0U?AR#PVH+IFjXdz)gdiA0-
zdwl>CB`l4fpH#y&w4ON4((r}T5)zYuhAeuKIRm!W_<7#!f^3$(;p_Q*+qaJbDqb4p
z@YDybtynt#AV6+gpng($InMbrTDDpp_PuIAA7k+I!#aK|y2_ib&nkGk<FqoMuEE~q
z${Sxh`2M`3R{?v!ObC$S6pP@q_0Yjl8@Q3hWmM<sX7kZ5@T{sL_&6A??!+XN0tQo*
z(lE`Oo~9|JVatf64mX1D-8e0w)nSz9(Hia46flxTVVtii(Dsb5B+gmrm_Y~{ju{DQ
zo+Zp(Xc!fHZg&3|LLuSn{1i?AG6|C;J*yn(>k$h{7SNc6S2zHrQkn(<I--=ochNp*
zhcZ}0X^c_m2dr^SKyU%gtsUOeoaIT59%ow4`V_{=YFreeq=Y6ajX^6%Zs4w18M;~c
zFC+dL*{hVWG>@Yz9NN1XXGwy-AfRNlk8m>rA9r{ni+90(L=Jic3F}7a&lM(gb<_x8
z$1A(bFoLh*e~7+EVL;LZ*aouW928;kS;QH<EI5Bh0my=8EDiwYobndP{~g7>rIIBy
twNp1IF-xP&Y8r6PU>Bgfg;4O%QcmAcGEP^Lze~%dzlGn%_UFa*#ot~xI<x=)

diff --git a/src/components/stage-header/icon--zoom.svg b/src/components/stage-header/icon--zoom.svg
deleted file mode 100644
index 62e008983d41b35d568610d17287c2854e2b7ca7..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2902
zcmd5;O^@3)5WVlOV6~S7SyCkRtw;{g20?S^rA<+wH?2h5>Pn;`(f02C`V1*i@_wX9
zFKvZg!{p3x=FNLUx%hD3cjzRBu~oA47@-~#vQ|wiccu6HmrpqL(5NffRGpHd^rZ4W
zY_5tQFh)NOqSB&4=T`60XL&c))j^;)d#w+-@1M_S($1Si4LkoW!gzCaRg9<I6+#H|
z$}w;1(whSg$Dy;1P3?<L^g`;<XN39Q>RzwzwaMO|M6LQ>$<ap2@%qAfXtvAYrkZnL
zomiG-KIJ~=7(DR!Aa!+*pN2w>uZ40-sSma_$@h8XBQ*2?|BJiZAfq}Cwb(*~1d&4f
zAHRI`oe@*g=w?lpyM8XmylAqldNCfVT8zGPw(%DXGrQ3?r3Xm3U7XuS?@KS3R(sLz
z_Ig>KT5<kS-IpFk6a^gqY>X>1Z&YovmR?&ciSeUSJ#js9HRMZvN;3Yg5hu~1qr8*q
zEWHizTl7L#O{FWtHA1F3x06~2Z~?aRUq5~_?&c}#I{!lrck>c<j6-#+j!^p?WBr;s
zhyM1J-n4zS6NbQdpuWOi4a*q??CFPtST^Qk2Qd+~bpBGUP2IO9$p1~ZUH91}@sRK8
zgi6h!t?tCe=A6Dd6#fijaxeS~l!fnlU|ZCP?Knl5_Lx;XrzsXP3=@rEY;rt6DYfd<
zP<q!}`&jM}x>Z9X24{-xGn*F9fY_s%LOdu9qh{_0`XpR|&;U4G8}qih{Y%tZt4<7+
ztU(gY1?&cp*lYX8wh^xxmMRQ{C6PPsiFMppjXIa!q)QObeCy=rR)PV~>Sh^#5k7l3
z#b>EQVmiF^GMwR!dv!KIN^e_rqj=u0UR2|85E!n@0VEhQ631zJ!(zgN^<Y<=^A-}$
zqc<-~Gjjx(DB(%;JW~zRXe?2ZCcz7%AtWM<20VNbIRiG+{5)<pK{QXlVe6~=wr?K=
zRJ=6G;i-?qV8qf@4+7-21L~(4DC~8ALCbDX$3w3g(1&$?o~)~GMOS*$9Ib*kCr&F3
z>Ke^Rm!AFF!E5LZy<z<Aa#er~Ctn0_uZIp&ZDBO?>#)v}?e@J{;8|5Udq3(y-HAyk
zIU`|^MvQUSyy-d`;K-0C4mX0=p1m}AKmrzJ+=&DsrzVz>Ad0heJqOwz0-tHj;%vr(
z5HuV|B<7TbkkZ{7#i7#se+(g)@REKGhetsiCl{3ieLV^oNg0i3aDxL9Q<^Y_P6(%H
zZ$3_l6V7Qu16W4{bjD}~yYMy1c$T2YrG7IHwmATH-CSg$q=e3?0fRtJm4*Q^+WVJa
z{(@5Icg&M4y}`^5WRxc8XJp38Y)2u0N(sEz;R(UONtgj=JT}d6z@w=N7CHY0biC5M
zTtM(b{13tR2(+2Rz%VE=%0LAG!%#bsybx?zod^c}QwaKVrSgJb{J&$kH&pVNCg!GP
pB;rY!8X+4UTdWIA(6!@p=JxNDjFYti-=*ck-@)%<^W$Q3^%W9DJ5T@s

diff --git a/src/components/stage-header/stage-header.css b/src/components/stage-header/stage-header.css
index c491b82e9..2c2c30bed 100644
--- a/src/components/stage-header/stage-header.css
+++ b/src/components/stage-header/stage-header.css
@@ -23,21 +23,48 @@
     padding: $space;
 }
 
-.stage-zoom-icon {
-    text-align: right;
+.stage-size-row {
+    display: flex;
+}
+
+.stage-size-toggle-group {
+    display: flex;
+    margin-right: .2rem;
+}
+
+.stage-button {
+    display: block;
+    border: 1px solid $ui-pane-border;
+    border-radius: .25rem;
     box-sizing: content-box;
     width: 1.25rem;
     height: 1.25rem;
     padding: 0.375rem;
-    border-radius: 0.25rem;
     user-select: none;
     cursor: pointer;
-    transition: 0.2s ease-out;
 }
 
-.stage-zoom-icon:hover {
-    /* Scale icon image by 1.2, but keep background static */
-    width: 1.5rem;
-    height: 1.5rem;
-    padding: 0.25rem;
+.stage-button-icon {
+    width: 100%;
+    height: 100%;
+}
+
+.stage-button-right {
+    border-left: none;
+    border-top-left-radius: 0;
+    border-bottom-left-radius: 0;
+}
+
+.stage-button-left {
+    border-top-right-radius: 0;
+    border-bottom-right-radius: 0;
+}
+
+.stage-button-active {
+    background: #FFF;
+}
+
+.stage-button-disabled {
+    opacity: .5;
+    cursor: auto;
 }
diff --git a/src/components/stage-header/stage-header.jsx b/src/components/stage-header/stage-header.jsx
index 635d161ba..19f46e220 100644
--- a/src/components/stage-header/stage-header.jsx
+++ b/src/components/stage-header/stage-header.jsx
@@ -1,81 +1,157 @@
 import classNames from 'classnames';
+import {defineMessages, injectIntl, intlShape} from 'react-intl';
 import PropTypes from 'prop-types';
 import React from 'react';
 import VM from 'scratch-vm';
+
 import Box from '../box/box.jsx';
+import Button from '../button/button.jsx';
+import {ComingSoonTooltip} from '../coming-soon/coming-soon.jsx';
 import Controls from '../../containers/controls.jsx';
 
-import zoomIcon from './icon--zoom.svg';
-import unzoomIcon from './icon--unzoom.svg';
+import {STAGE_SIZES} from '../../reducers/stage-size';
+
+import fullScreenIcon from './icon--fullscreen.svg';
+import largeStageIcon from './icon--large-stage.svg';
+import smallStageIcon from './icon--small-stage.svg';
+import unFullScreenIcon from './icon--unfullscreen.svg';
+
 import styles from './stage-header.css';
 
+const messages = defineMessages({
+    largeStageSizeMessage: {
+        defaultMessage: 'Stage Size Toggle - Large',
+        description: 'Button to change stage size to large',
+        id: 'gui.gui.stageSizeLarge'
+    },
+    smallStageSizeMessage: {
+        defaultMessage: 'Stage Size Toggle - Small',
+        description: 'Button to change stage size to small',
+        id: 'gui.gui.stageSizeSmall'
+    },
+    fullStageSizeMessage: {
+        defaultMessage: 'Stage Size Toggle - Full Screen',
+        description: 'Button to change stage size to full screen',
+        id: 'gui.gui.stageSizeFull'
+    },
+    unFullStageSizeMessage: {
+        defaultMessage: 'Stage Size Toggle - Un-full screen',
+        description: 'Button to get out of full screen mode',
+        id: 'gui.gui.stageSizeUnFull'
+    }
+});
+
 const StageHeaderComponent = function (props) {
     const {
-        className,
-        height,
-        isZoomed,
-        onUnzoom,
-        onZoom,
-        titleZoomIcon,
-        vm,
-        width,
-        ...componentProps
+        stageSize,
+        isFullScreen,
+        onSetStageLarge,
+        onSetStageFull,
+        onSetStageUnFull,
+        vm
     } = props;
-    return isZoomed === false ? (
-        <Box className={styles.stageHeaderWrapper}>
-            <Box
-                className={styles.stageMenuWrapper}
-                height={height}
-                width={width}
-            >
-                <Controls vm={vm} />
-                <img
-                    className={classNames(
-                        className,
-                        styles.stageZoomIcon
-                    )}
-                    src={zoomIcon}
-                    title={titleZoomIcon}
-                    onClick={onZoom}
-                    {...componentProps}
-                />
+
+    let header = null;
+
+    if (isFullScreen) {
+        header = (
+            <Box className={styles.stageHeaderWrapperOverlay}>
+                <Box className={styles.stageMenuWrapper}>
+                    <Controls vm={vm} />
+                    <Button
+                        className={classNames(
+                            styles.stageButton,
+                            styles.stageButtonActive
+                        )}
+                        onClick={onSetStageUnFull}
+                    >
+                        <img
+                            alt={props.intl.formatMessage(messages.unFullStageSizeMessage)}
+                            className={styles.stageButtonIcon}
+                            src={unFullScreenIcon}
+                            title="Full Screen Control"
+                        />
+                    </Button>
+                </Box>
             </Box>
-        </Box>
-    ) : (
-        <Box className={styles.stageHeaderWrapperOverlay}>
-            <Box
-                className={styles.stageMenuWrapper}
-                height={'100%'}
-                width={'100%'}
-            >
-                <Controls vm={vm} />
-                <img
-                    className={classNames(
-                        className,
-                        styles.stageZoomIcon
-                    )}
-                    src={unzoomIcon}
-                    title={titleZoomIcon}
-                    onClick={onUnzoom}
-                    {...componentProps}
-                />
+        );
+    } else {
+        header = (
+            <Box className={styles.stageHeaderWrapper}>
+                <Box className={styles.stageMenuWrapper}>
+                    <Controls vm={vm} />
+                    <div className={styles.stageSizeRow}>
+                        <div className={styles.stageSizeToggleGroup}>
+                            <ComingSoonTooltip
+                                place="left"
+                                tooltipId="small-stage-button"
+                            >
+                                <div
+                                    disabled
+                                    className={classNames(
+                                        styles.stageButton,
+                                        styles.stageButtonLeft,
+                                        styles.stageButtonDisabled
+                                    )}
+                                    role="button"
+                                >
+                                    <img
+                                        disabled
+                                        alt={props.intl.formatMessage(messages.smallStageSizeMessage)}
+                                        className={styles.stageButtonIcon}
+                                        src={smallStageIcon}
+                                    />
+                                </div>
+                            </ComingSoonTooltip>
+                            <div>
+                                <Button
+                                    className={classNames(
+                                        styles.stageButton,
+                                        styles.stageButtonRight,
+                                        {
+                                            [styles.stageButtonActive]: stageSize === STAGE_SIZES.large
+                                        }
+                                    )}
+                                    onClick={onSetStageLarge}
+                                >
+                                    <img
+                                        alt={props.intl.formatMessage(messages.largeStageSizeMessage)}
+                                        className={styles.stageButtonIcon}
+                                        src={largeStageIcon}
+                                    />
+                                </Button>
+                            </div>
+                        </div>
+                        <div>
+                            <Button
+                                className={styles.stageButton}
+                                onClick={onSetStageFull}
+                            >
+                                <img
+                                    alt={props.intl.formatMessage(messages.fullStageSizeMessage)}
+                                    className={styles.stageButtonIcon}
+                                    src={fullScreenIcon}
+                                    title="Full Screen Control"
+                                />
+                            </Button>
+                        </div>
+                    </div>
+                </Box>
             </Box>
-        </Box>
-    );
+        );
+    }
+
+    return header;
 };
+
 StageHeaderComponent.propTypes = {
-    className: PropTypes.string,
-    height: PropTypes.number,
-    isZoomed: PropTypes.bool.isRequired,
-    onUnzoom: PropTypes.func.isRequired,
-    onZoom: PropTypes.func.isRequired,
-    titleZoomIcon: PropTypes.string,
-    vm: PropTypes.instanceOf(VM).isRequired,
-    width: PropTypes.number
+    intl: intlShape,
+    isFullScreen: PropTypes.bool.isRequired,
+    onSetStageFull: PropTypes.func.isRequired,
+    onSetStageLarge: PropTypes.func.isRequired,
+    onSetStageUnFull: PropTypes.func.isRequired,
+    stageSize: PropTypes.oneOf(Object.keys(STAGE_SIZES)).isRequired,
+    vm: PropTypes.instanceOf(VM).isRequired
 };
-StageHeaderComponent.defaultProps = {
-    width: 480,
-    height: 360,
-    titleZoomIcon: 'Zoom Control'
-};
-export default StageHeaderComponent;
+
+export default injectIntl(StageHeaderComponent);
diff --git a/src/components/stage/stage.jsx b/src/components/stage/stage.jsx
index 47981e04a..c8777a263 100644
--- a/src/components/stage/stage.jsx
+++ b/src/components/stage/stage.jsx
@@ -13,7 +13,7 @@ const StageComponent = props => {
         canvasRef,
         height,
         isColorPicking,
-        isZoomed,
+        isFullScreen,
         width,
         colorInfo,
         onDeactivateColorPicker,
@@ -26,7 +26,7 @@ const StageComponent = props => {
     let widthCorrectedAspect = width;
     const spacingBorderAdjustment = 9;
     const stageMenuHeightAdjustment = 40;
-    if (isZoomed) {
+    if (isFullScreen) {
         heightCorrectedAspect = window.innerHeight - stageMenuHeightAdjustment - spacingBorderAdjustment;
         widthCorrectedAspect = heightCorrectedAspect + (heightCorrectedAspect / 3);
         if (widthCorrectedAspect > window.innerWidth) {
@@ -38,15 +38,15 @@ const StageComponent = props => {
         <div>
             <Box
                 className={classNames({
-                    [styles.stageWrapper]: !isZoomed,
-                    [styles.stageWrapperOverlay]: isZoomed,
-                    [styles.withColorPicker]: !isZoomed && isColorPicking
+                    [styles.stageWrapper]: !isFullScreen,
+                    [styles.stageWrapperOverlay]: isFullScreen,
+                    [styles.withColorPicker]: !isFullScreen && isColorPicking
                 })}
             >
                 <Box
                     className={classNames(
                         styles.stage,
-                        {[styles.stageOverlayContent]: isZoomed}
+                        {[styles.stageOverlayContent]: isFullScreen}
                     )}
                     componentRef={canvasRef}
                     element="canvas"
@@ -95,7 +95,7 @@ StageComponent.propTypes = {
     colorInfo: Loupe.propTypes.colorInfo,
     height: PropTypes.number,
     isColorPicking: PropTypes.bool,
-    isZoomed: PropTypes.bool.isRequired,
+    isFullScreen: PropTypes.bool.isRequired,
     onDeactivateColorPicker: PropTypes.func,
     onQuestionAnswered: PropTypes.func,
     question: PropTypes.string,
diff --git a/src/containers/save-button.jsx b/src/containers/save-button.jsx
index 12585ab70..f2ae497de 100644
--- a/src/containers/save-button.jsx
+++ b/src/containers/save-button.jsx
@@ -4,6 +4,8 @@ import React from 'react';
 import {connect} from 'react-redux';
 
 import ButtonComponent from '../components/button/button.jsx';
+import {ComingSoonTooltip} from '../components/coming-soon/coming-soon.jsx';
+
 
 class SaveButton extends React.Component {
     constructor (props) {
@@ -38,12 +40,18 @@ class SaveButton extends React.Component {
             ...props
         } = this.props;
         return (
-            <ButtonComponent
-                onClick={this.handleClick}
-                {...props}
+            <ComingSoonTooltip
+                place="bottom"
+                tooltipId="save-button"
             >
-                Save
-            </ButtonComponent>
+                <ButtonComponent
+                    disabled
+                    onClick={this.handleClick}
+                    {...props}
+                >
+                    Save
+                </ButtonComponent>
+            </ComingSoonTooltip>
         );
     }
 }
diff --git a/src/containers/stage-header.jsx b/src/containers/stage-header.jsx
index d3acba94e..593851a41 100644
--- a/src/containers/stage-header.jsx
+++ b/src/containers/stage-header.jsx
@@ -1,7 +1,7 @@
 import PropTypes from 'prop-types';
 import React from 'react';
 import VM from 'scratch-vm';
-import {setZoomed} from '../reducers/zoom';
+import {setStageSize, setFullScreen, STAGE_SIZES} from '../reducers/stage-size';
 
 import {connect} from 'react-redux';
 
@@ -22,19 +22,20 @@ class StageHeader extends React.Component {
 }
 
 StageHeader.propTypes = {
-    height: PropTypes.number,
-    isZoomed: PropTypes.bool,
-    vm: PropTypes.instanceOf(VM).isRequired,
-    width: PropTypes.number
+    stageSize: PropTypes.oneOf(Object.keys(STAGE_SIZES)),
+    vm: PropTypes.instanceOf(VM).isRequired
 };
 
 const mapStateToProps = state => ({
-    isZoomed: state.isZoomed
+    stageSize: state.stageSize.stageSize,
+    isFullScreen: state.stageSize.isFullScreen
 });
 
 const mapDispatchToProps = dispatch => ({
-    onZoom: () => dispatch(setZoomed(true)),
-    onUnzoom: () => dispatch(setZoomed(false))
+    onSetStageLarge: () => dispatch(setStageSize(STAGE_SIZES.large)),
+    onSetStageSmall: () => dispatch(setStageSize(STAGE_SIZES.small)),
+    onSetStageFull: () => dispatch(setFullScreen(true)),
+    onSetStageUnFull: () => dispatch(setFullScreen(false))
 });
 
 export default connect(
diff --git a/src/containers/stage.jsx b/src/containers/stage.jsx
index 9f76aa7ab..cb2a38963 100644
--- a/src/containers/stage.jsx
+++ b/src/containers/stage.jsx
@@ -57,7 +57,7 @@ class Stage extends React.Component {
             this.props.height !== nextProps.height ||
             this.props.isColorPicking !== nextProps.isColorPicking ||
             this.state.colorInfo !== nextState.colorInfo ||
-            this.props.isZoomed !== nextProps.isZoomed ||
+            this.props.isFullScreen !== nextProps.isFullScreen ||
             this.state.question !== nextState.question;
     }
     componentDidUpdate (prevProps) {
@@ -279,7 +279,7 @@ class Stage extends React.Component {
 Stage.propTypes = {
     height: PropTypes.number,
     isColorPicking: PropTypes.bool,
-    isZoomed: PropTypes.bool,
+    isFullScreen: PropTypes.bool.isRequired,
     onActivateColorPicker: PropTypes.func,
     onDeactivateColorPicker: PropTypes.func,
     vm: PropTypes.instanceOf(VM).isRequired,
@@ -288,7 +288,7 @@ Stage.propTypes = {
 
 const mapStateToProps = state => ({
     isColorPicking: state.colorPicker.active,
-    isZoomed: state.isZoomed
+    isFullScreen: state.stageSize.isFullScreen
 });
 
 const mapDispatchToProps = dispatch => ({
diff --git a/src/css/colors.css b/src/css/colors.css
index d524795cd..e270217f9 100644
--- a/src/css/colors.css
+++ b/src/css/colors.css
@@ -16,4 +16,6 @@ $sound-tertiary: #A63FA6;
 
 $control-primary: #FFAB19;
 
+$data-primary: #FF8C1A;
+
 $form-border: #E9EEF2;
diff --git a/src/reducers/gui.js b/src/reducers/gui.js
index 83ede0203..d49144b4f 100644
--- a/src/reducers/gui.js
+++ b/src/reducers/gui.js
@@ -8,14 +8,14 @@ import monitorLayoutReducer from './monitor-layout';
 import targetReducer from './targets';
 import toolboxReducer from './toolbox';
 import vmReducer from './vm';
-import zoomReducer from './zoom';
+import stageSizeReducer from './stage-size';
 import {ScratchPaintReducer} from 'scratch-paint';
 
 export default combineReducers({
     colorPicker: colorPickerReducer,
     customProcedures: customProceduresReducer,
     intl: intlReducer,
-    isZoomed: zoomReducer,
+    stageSize: stageSizeReducer,
     modals: modalReducer,
     monitors: monitorReducer,
     monitorLayout: monitorLayoutReducer,
diff --git a/src/reducers/stage-size.js b/src/reducers/stage-size.js
new file mode 100644
index 000000000..ea2750e34
--- /dev/null
+++ b/src/reducers/stage-size.js
@@ -0,0 +1,55 @@
+const SET_STAGE_SIZE = 'scratch-gui/StageSize/SET_STAGE_SIZE';
+const SET_FULL_SCREEN = 'scratch-gui/StageSize/SET_FULL_SCREEN';
+
+const initialState = {
+    isFullScreen: false,
+    stageSize: 'large'
+};
+
+// stage size constants
+const STAGE_SIZES = {
+    small: 'small',
+    large: 'large'
+};
+
+const reducer = function (state, action) {
+    if (typeof state === 'undefined') state = initialState;
+    switch (action.type) {
+    case SET_STAGE_SIZE:
+        return {
+            isFullScreen: state.isFullScreen,
+            stageSize: action.stageSize
+        };
+    case SET_FULL_SCREEN:
+        return {
+            isFullScreen: action.isFullScreen,
+            stageSize: state.stageSize
+        };
+    default:
+        return state;
+    }
+};
+
+const setStageSize = function (stageSize) {
+    return {
+        type: SET_STAGE_SIZE,
+        stageSize: stageSize
+    };
+};
+
+// `isFullScreen` is a separate value because "stage size" does not
+// actually apply to full screen mode, so they are treated as separate
+// values to be assessed.
+const setFullScreen = function (isFullScreen) {
+    return {
+        type: SET_FULL_SCREEN,
+        isFullScreen: isFullScreen
+    };
+};
+
+export {
+    reducer as default,
+    setStageSize,
+    setFullScreen,
+    STAGE_SIZES
+};
diff --git a/src/reducers/zoom.js b/src/reducers/zoom.js
deleted file mode 100644
index 3cd0f5f7f..000000000
--- a/src/reducers/zoom.js
+++ /dev/null
@@ -1,23 +0,0 @@
-const SET_ZOOMED = 'scratch-gui/Zoomed/SET_ZOOMED';
-const defaultZoomed = false;
-const initialState = defaultZoomed;
-
-const reducer = function (state, action) {
-    if (typeof state === 'undefined') state = initialState;
-    switch (action.type) {
-    case SET_ZOOMED:
-        return action.isZoomed;
-    default:
-        return state;
-    }
-};
-const setZoomed = function (isZoomed) {
-    return {
-        type: SET_ZOOMED,
-        isZoomed: isZoomed
-    };
-};
-export {
-    reducer as default,
-    setZoomed
-};
diff --git a/test/integration/test.js b/test/integration/test.js
index 58b488ecd..8668fce2a 100644
--- a/test/integration/test.js
+++ b/test/integration/test.js
@@ -143,7 +143,7 @@ describe('costumes, sounds and variables', () => {
         const projectId = '96708228';
         await loadUri(`${uri}#${projectId}`);
         await new Promise(resolve => setTimeout(resolve, 2000));
-        await clickXpath('//img[@title="Zoom Control"]');
+        await clickXpath('//img[@title="Full Screen Control"]');
         await clickXpath('//img[@title="Go"]');
         await new Promise(resolve => setTimeout(resolve, 2000));
         await clickXpath('//img[@title="Stop"]');
@@ -235,7 +235,9 @@ describe('costumes, sounds and variables', () => {
         await expect(logs).toEqual([]);
     });
 
-    test('Localization', async () => {
+    // Skipped temporarily while the language selector is marked as
+    // "Coming Soon"
+    test.skip('Localization', async () => {
         await loadUri(uri);
         await clickText('Blocks');
         await clickText('Extensions');
-- 
GitLab