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.
No files matched your search
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
@@ -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;
|
||||
|
||||
@@ -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 => (
|
||||
|
||||
@@ -1,72 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 300 300" enable-background="new 0 0 300 300" xml:space="preserve">
|
||||
<g>
|
||||
<polygon fill="#999999" points="148.7,59.1 68,30.6 68,206.1 148.7,180 "/>
|
||||
<polygon fill="#FFFFFF" points="146.7,59 230.5,30.5 230.5,206 146.7,180 "/>
|
||||
<polygon fill="#FFFFFF" points="47.1,236.9 146.7,203.7 146.7,58.9 47.1,92.2 "/>
|
||||
<polygon fill="#999999" points="192.1,239.1 206.2,262.3 213.7,240.7 "/>
|
||||
<g>
|
||||
<path fill="#999999" d="M81,108.8c-0.5-0.5,0.7,4.2,2.4,6c3,3,5.4,3.4,6.6,3.5c2.8,0.1,6.2-0.7,8.2-1.5c2-0.8,5.4-2.6,6.7-5.2
|
||||
c0.3-0.5,1-1.5,0.6-3.7c-0.4-1.7-1.5-2.4-2.8-2.3c-1.4,0.1-5.5,1.2-7.4,1.8c-2,0.6-6.1,1.8-7.9,2.2C85.5,110,81.6,109.4,81,108.8z
|
||||
"/>
|
||||
<path fill="#999999" d="M131.2,165.8c-0.8-0.3-17-7-19.3-8.1c-1.9-0.9-6.5-2.9-8.7-3.7c6.1-9.4,10-16.6,10.5-17.7
|
||||
c1-2,7.4-14.7,7.6-15.4c0.1-0.8,0.3-3.7,0.2-4.4c-0.1-0.7-2.5,0.7-5.7,1.7c-3.2,1.1-9.4,5.1-11.7,5.6c-2.4,0.5-10,3.4-13.9,4.7
|
||||
c-3.9,1.3-11.3,3.5-14.3,4.4c-3,0.8-5.7,0.9-7.4,1.4c0,0,0.2,2.4,0.7,3.1c0.4,0.7,2.1,2.5,3.9,2.9c1.9,0.5,5,0.3,6.4,0
|
||||
c1.4-0.3,3.8-1.5,4.2-2c0.3-0.5-0.2-2.2,0.4-2.6c0.6-0.5,8-2.2,10.8-3.1c2.8-0.9,13.5-4.6,15-4.4c-0.5,1.5-9.1,18.6-11.9,23.7
|
||||
c-2.8,5.1-18.9,27.5-22.3,31.4c-2.6,3-8.9,10.7-11.1,12.4c0.6,0.2,4.5-0.2,5.2-0.6c4.4-2.7,11.8-11.9,14.2-14.7
|
||||
c7.1-8.3,13.3-17,18.2-24.5h0c1,0.4,8.7,6.7,10.8,8.1c2,1.4,10,5.9,11.8,6.6c1.7,0.7,8.4,3.8,8.7,2.8
|
||||
C133.5,172.2,132,166.1,131.2,165.8z"/>
|
||||
</g>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#999999" d="M93.7,250.4c1.6,1,3,1.7,4.7,2.5c3.3,1.6,7,3.4,10.5,4.7
|
||||
c4.8,1.8,9.7,3.3,14.5,4.4c2.7,0.6,5.6,1.1,8.5,1.6c0.3,0,8,1,9.5,1h7.8c3-0.3,5.9-0.4,8.9-0.9c2.4-0.3,5.1-0.8,7.7-1.4
|
||||
c1.9-0.4,3.9-0.9,5.8-1.5c1.8-0.5,3.9-1.2,5.9-1.9c1.3-0.4,2.7-1,4.1-1.6c1.1-0.5,2.5-1.1,3.8-1.6c1.6-0.7,3.4-1.6,5.1-2.5
|
||||
c1.4-0.7,2.9-1.6,4.4-2.4c1.1-0.6,3.7-2.6,5.1-2.6c1.6,0,2.6,1.4,2.6,2.6c0,2.5-3.4,3.3-4.9,4.4c-1.6,1.1-3.6,2-5.4,2.9
|
||||
c-3.5,1.8-7,3.4-10.4,4.7c-4.4,1.6-9.3,3.2-13.6,4.2c-1.6,0.3-3.3,0.8-4.9,1c-0.9,0.2-9.9,1.6-12.4,1.6h-11.4c-3-0.3-6.2-0.6-9.3-1
|
||||
c-2.7-0.4-5.5-1-8.2-1.6c-2.1-0.4-4.3-1-6.3-1.6c-3.5-1-6.8-2.2-10.1-3.5c-6-2.2-12.2-5.2-18.1-9.1c-1-0.7-1.1-1.4-1.1-2.2
|
||||
c0-1.3,1-2.5,2.5-2.5C90.4,248.2,93.2,250.1,93.7,250.4z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#999999" d="M144,201.7l-94.3,31.4v-139L144,62.7V201.7z M149.3,58.6v145.3
|
||||
c-0.1,0.4-0.3,0.9-0.6,1.3c-0.2,0.3-0.5,0.6-0.8,0.7c-2.2,0.9-99.5,33.6-100.8,33.6c-1,0-2-0.7-2.5-1.8c0-0.1-0.1-0.2-0.1-0.3V91.9
|
||||
c0.2-0.4,0.3-1,0.6-1.4c0.7-1,1.9-1.1,2.7-1.4c1.5-0.5,97.4-32.7,98.8-32.7C147.4,56.4,149.3,57.1,149.3,58.6z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#999999" d="M227.8,202.4L149.4,178V60.9l78.4-26.6V202.4z M233.1,30.8v174.9
|
||||
c-0.1,2-1.5,2.9-2.8,2.9c-1.1,0-9.3-2.8-10.6-3.2c-10.9-3.4-21.9-6.7-32.7-10.1c-2.4-0.8-4.9-1.6-7.3-2.3c-2.1-0.6-4.3-1.3-6.4-2
|
||||
c-9.3-2.9-18.7-5.7-27.9-8.8c-0.3-0.1-1.2-1.3-1.2-1.6V58.4c0.2-0.4,0.3-1,0.8-1.3c0.7-0.8,30.4-10.6,42-14.5
|
||||
c3.1-1.1,42.1-14.5,43.3-14.5C231.9,28,233.1,29.1,233.1,30.8z"/>
|
||||
<polygon fill="#999999" points="253,239.1 148.2,205.7 148.7,60.3 253,93.5 "/>
|
||||
<g>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M200.2,125.2l-10.3,24.9l18.9,5.7L200.2,125.2z M194,101.8
|
||||
l13.5,4.1l24.6,88.6l-13.9-4.2l-5-18.2l-28.7-8.7l-6.2,14.8l-13.9-4.2L194,101.8z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Language</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" opacity="0.25" stroke-linejoin="round">
|
||||
<g id="Language" stroke="#000000" stroke-width="1.25">
|
||||
<g transform="translate(2.000000, 2.000000)">
|
||||
<path d="M15.6352,8.11294118 C15.6352,12.2682353 12.2667294,15.6357647 8.11237647,15.6357647 C3.95708235,15.6357647 0.588611765,12.2682353 0.588611765,8.11294118 C0.588611765,3.95764706 3.95708235,0.589176471 8.11237647,0.589176471 C12.2667294,0.589176471 15.6352,3.95764706 15.6352,8.11294118 Z" id="Stroke-1"></path>
|
||||
<path d="M11.9808,8.11661176 C11.9808,9.74955294 11.7153882,11.2601412 11.2542118,12.4921412 C10.5558588,14.3933176 9.40762353,15.6347294 8.11068235,15.6347294 C6.81374118,15.6347294 5.66927059,14.3933176 4.96715294,12.4921412 C4.51068235,11.2601412 4.24432941,9.74955294 4.24432941,8.11661176 C4.24432941,6.48272941 4.51068235,4.97308235 4.96715294,3.74108235 C5.66927059,1.82955294 6.81374118,0.588141176 8.11068235,0.588141176 C9.40762353,0.588141176 10.5558588,1.82955294 11.2542118,3.74108235 C11.7153882,4.97308235 11.9808,6.48272941 11.9808,8.11661176 Z" id="Stroke-3"></path>
|
||||
<path d="M0.955011765,10.2811294 L15.2684235,10.2811294" id="Stroke-5"></path>
|
||||
<path d="M0.955011765,5.94663529 L15.2684235,5.94663529" id="Stroke-7"></path>
|
||||
<path d="M8.11218824,0.590023529 L8.11218824,15.6375529" id="Stroke-9"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="8px" height="5px" viewBox="0 0 8 5" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 48.1 (47250) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>dropdown-caret-gray</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="dropdown-caret-gray" fill="#575E75">
|
||||
<path d="M4,5 C3.72520708,5 3.45163006,4.89695045 3.24127973,4.68965311 L0.314613572,1.80666227 C-0.104871191,1.39326583 -0.104871191,0.724642023 0.314613572,0.310047331 C0.732882438,-0.10334911 7.26711756,-0.10334911 7.68538643,0.310047331 C8.10487119,0.723443772 8.10487119,1.39326583 7.68538643,1.80666227 L4.75993617,4.68965311 C4.54958583,4.89695045 4.27600882,5 4,5" id="dropdown-caret"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 950 B |
@@ -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;
|
||||
}
|
||||
@@ -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}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Fullscreen</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Fullscreen" fill="#575E75">
|
||||
<g id="fullscreen" transform="translate(3.000000, 3.000000)">
|
||||
<path d="M13.338093,4.35035264 L12.4488644,3.45883199 L9.31483512,5.83342741 C8.95713791,6.10825708 8.4389784,6.03619808 8.1648553,5.66752413 C7.94254816,5.37090918 7.94756261,4.96201625 8.1648553,4.6821592 L10.5333457,1.54005165 L9.66584641,0.668640487 C9.41679554,0.418947674 9.59397267,0.00502737208 9.93495506,0.00502737208 L13.6122161,0 C13.8244944,0.00502737208 14,0.180985395 14,0.388783441 L14,4.08055034 C14,4.42241164 13.5821294,4.59501808 13.338093,4.35035264" id="Fill-1"></path>
|
||||
<path d="M0.661906989,9.64928834 L1.55113557,10.5408826 L4.68516488,8.16609118 C5.04286209,7.89123882 5.5610216,7.9649797 5.8351447,8.33200815 C6.05745184,8.62864758 6.05243739,9.03757425 5.8351447,9.3174544 L3.4649828,12.4598213 L4.33415359,13.3313043 C4.58320446,13.5810178 4.40602733,13.9949722 4.06504494,13.9949722 L0.387783893,14 C0.175505641,13.9949722 0,13.8189997 0,13.6111845 L0,9.9191129 C0,9.57722339 0.417870574,9.4046027 0.661906989,9.64928834" id="Fill-3"></path>
|
||||
<path d="M0.661906989,4.35035264 L1.55113557,3.45883199 L4.68516488,5.83342741 C5.04286209,6.10825708 5.5610216,6.03619808 5.8351447,5.66752413 C6.05745184,5.37090918 6.05243739,4.96201625 5.8351447,4.6821592 L3.4649828,1.54005165 L4.33415359,0.668640487 C4.58320446,0.418947674 4.40602733,0.00502737208 4.06504494,0.00502737208 L0.387783893,0 C0.175505641,0.00502737208 0,0.180985395 0,0.388783441 L0,4.08055034 C0,4.42241164 0.417870574,4.59501808 0.661906989,4.35035264" id="Fill-5"></path>
|
||||
<path d="M13.338093,9.64928834 L12.4488644,10.5408826 L9.31483512,8.16609118 C8.95713791,7.89123882 8.4389784,7.9649797 8.1648553,8.33200815 C7.94254816,8.62864758 7.94756261,9.03757425 8.1648553,9.3174544 L10.5333457,12.4598213 L9.66584641,13.3313043 C9.41679554,13.5810178 9.59397267,13.9949722 9.93495506,13.9949722 L13.6122161,14 C13.8244944,13.9949722 14,13.8189997 14,13.6111845 L14,9.9191129 C14,9.57722339 13.5821294,9.4046027 13.338093,9.64928834" id="Fill-7"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Large Stage (active)</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||
<g id="Large-Stage-(active)" stroke="#4C97FF">
|
||||
<g id="large-stage-(inactive)" transform="translate(3.000000, 4.000000)">
|
||||
<path d="M1,0 L7,0 L7,12 L1,12 L1,12 C0.44771525,12 6.76353751e-17,11.5522847 0,11 L0,1 L0,1 C-6.76353751e-17,0.44771525 0.44771525,1.01453063e-16 1,0 Z" id="Rectangle"></path>
|
||||
<path d="M7,0 L13,0 L13,0 C13.5522847,-1.01453063e-16 14,0.44771525 14,1 L14,5.25 L7,5.25 L7,0 Z" id="Rectangle" fill="#4C97FF"></path>
|
||||
<path d="M7,5 L14,5 L14,11 L14,11 C14,11.5522847 13.5522847,12 13,12 L7,12 L7,5 Z" id="Rectangle-Copy"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Small Stage (inactive)</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||
<g id="Small-Stage-(inactive)" stroke="#575E75">
|
||||
<g id="small-stage-(inactive)" transform="translate(3.000000, 4.000000)">
|
||||
<path d="M1,0 L10,0 L10,12 L1,12 L1,12 C0.44771525,12 6.76353751e-17,11.5522847 0,11 L0,1 L0,1 C-6.76353751e-17,0.44771525 0.44771525,1.01453063e-16 1,0 Z" id="Rectangle"></path>
|
||||
<path d="M10,0 L13,0 L13,0 C13.5522847,-1.01453063e-16 14,0.44771525 14,1 L14,3 L10,3 L10,0 Z" id="Rectangle" fill="#575E75"></path>
|
||||
<path d="M10,3 L14,3 L14,11 L14,11 C14,11.5522847 13.5522847,12 13,12 L10,12 L10,3 Z" id="Rectangle-Copy"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 48.1 (47250) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>un-fullscreen</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="un-fullscreen" fill="#575E75">
|
||||
<g transform="translate(2.000000, 2.000000)">
|
||||
<path d="M15.338093,4.35035264 L14.4488644,3.45883199 L11.3148351,5.83342741 C10.9571379,6.10825708 10.4389784,6.03619808 10.1648553,5.66752413 C9.94254816,5.37090918 9.94756261,4.96201625 10.1648553,4.6821592 L12.5333457,1.54005165 L11.6658464,0.668640487 C11.4167955,0.418947674 11.5939727,0.00502737208 11.9349551,0.00502737208 L15.6122161,0 C15.8244944,0.00502737208 16,0.180985395 16,0.388783441 L16,4.08055034 C16,4.42241164 15.5821294,4.59501808 15.338093,4.35035264" id="Fill-1" transform="translate(13.000000, 3.000000) rotate(180.000000) translate(-13.000000, -3.000000) "></path>
|
||||
<path d="M0.661906989,11.6492883 L1.55113557,12.5408826 L4.68516488,10.1660912 C5.04286209,9.89123882 5.5610216,9.9649797 5.8351447,10.3320081 C6.05745184,10.6286476 6.05243739,11.0375743 5.8351447,11.3174544 L3.4649828,14.4598213 L4.33415359,15.3313043 C4.58320446,15.5810178 4.40602733,15.9949722 4.06504494,15.9949722 L0.387783893,16 C0.175505641,15.9949722 0,15.8189997 0,15.6111845 L0,11.9191129 C0,11.5772234 0.417870574,11.4046027 0.661906989,11.6492883" id="Fill-3" transform="translate(3.000000, 13.000000) rotate(180.000000) translate(-3.000000, -13.000000) "></path>
|
||||
<path d="M0.661906989,4.35035264 L1.55113557,3.45883199 L4.68516488,5.83342741 C5.04286209,6.10825708 5.5610216,6.03619808 5.8351447,5.66752413 C6.05745184,5.37090918 6.05243739,4.96201625 5.8351447,4.6821592 L3.4649828,1.54005165 L4.33415359,0.668640487 C4.58320446,0.418947674 4.40602733,0.00502737208 4.06504494,0.00502737208 L0.387783893,0 C0.175505641,0.00502737208 0,0.180985395 0,0.388783441 L0,4.08055034 C0,4.42241164 0.417870574,4.59501808 0.661906989,4.35035264" id="Fill-5" transform="translate(3.000000, 3.000000) rotate(180.000000) translate(-3.000000, -3.000000) "></path>
|
||||
<path d="M15.338093,11.6492883 L14.4488644,12.5408826 L11.3148351,10.1660912 C10.9571379,9.89123882 10.4389784,9.9649797 10.1648553,10.3320081 C9.94254816,10.6286476 9.94756261,11.0375743 10.1648553,11.3174544 L12.5333457,14.4598213 L11.6658464,15.3313043 C11.4167955,15.5810178 11.5939727,15.9949722 11.9349551,15.9949722 L15.6122161,16 C15.8244944,15.9949722 16,15.8189997 16,15.6111845 L16,11.9191129 C16,11.5772234 15.5821294,11.4046027 15.338093,11.6492883" id="Fill-7" transform="translate(13.000000, 13.000000) rotate(180.000000) translate(-13.000000, -13.000000) "></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -1,89 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 32 32"
|
||||
sodipodi:docname="icon--unzoom.svg"
|
||||
inkscape:version="0.92+devel unknown">
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs6" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
inkscape:document-rotation="0"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="981"
|
||||
id="namedview4"
|
||||
showgrid="false"
|
||||
inkscape:measure-start="41.6688,16.2381"
|
||||
inkscape:measure-end="0,0"
|
||||
inkscape:zoom="20.275"
|
||||
inkscape:cx="20.257873"
|
||||
inkscape:cy="15.103245"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g10" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Image"
|
||||
id="g10"
|
||||
transform="translate(0,12)">
|
||||
<rect
|
||||
style="fill:#4c97ff;fill-opacity:1;stroke-width:0.94703782"
|
||||
id="rect4271"
|
||||
width="15.349942"
|
||||
height="12.743591"
|
||||
x="8.2659235"
|
||||
y="-2.3098626" />
|
||||
<path
|
||||
style="fill:#4c97ff;fill-opacity:1;stroke:none;stroke-width:1.25366771"
|
||||
d="m 23.810503,-11.600711 v 7.9999999 h 8 v -2.220703 h -5.787109 v -5.7792969 z"
|
||||
id="rect4356"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#4c97ff;fill-opacity:1;stroke:none;stroke-width:1.25366771"
|
||||
d="M 0.27627954,-3.6685866 H 8.2762798 v -8.0000004 h -2.220703 v 5.7871094 H 0.27627954 Z"
|
||||
id="rect4356-5"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#4c97ff;fill-opacity:1;stroke:none;stroke-width:1.25366771"
|
||||
d="m 31.7603,11.59536 h -8 v 8 h 2.220703 V 13.808251 H 31.7603 Z"
|
||||
id="rect4356-6"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#4c97ff;fill-opacity:1;stroke:none;stroke-width:1.25366771"
|
||||
d="m 8.2260788,19.527481 v -8 h -8 v 2.220703 h 5.787109 v 5.779297 z"
|
||||
id="rect4356-7"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -1,89 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 32 32"
|
||||
sodipodi:docname="icon--zoom.svg"
|
||||
inkscape:version="0.92+devel unknown">
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs6" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
inkscape:document-rotation="0"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="981"
|
||||
id="namedview4"
|
||||
showgrid="false"
|
||||
inkscape:measure-start="41.6688,16.2381"
|
||||
inkscape:measure-end="0,0"
|
||||
inkscape:zoom="20.275"
|
||||
inkscape:cx="20.257873"
|
||||
inkscape:cy="15.103245"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g10" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Image"
|
||||
id="g10"
|
||||
transform="translate(0,12)">
|
||||
<rect
|
||||
style="fill:#4c97ff;fill-opacity:1;stroke-width:1.43851125"
|
||||
id="rect4271"
|
||||
width="23.315924"
|
||||
height="19.356985"
|
||||
x="4.2786169"
|
||||
y="-5.6201425" />
|
||||
<path
|
||||
style="fill:#4c97ff;fill-opacity:1;stroke:none;stroke-width:1.25366771"
|
||||
d="m 31.810503,-3.600711 v -8 h -8 v 2.220703 h 5.787109 v 5.779297 z"
|
||||
id="rect4356"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#4c97ff;fill-opacity:1;stroke:none;stroke-width:1.25366771"
|
||||
d="M 8.2762798,-11.668587 H 0.27627954 v 8.0000004 H 2.4969826 v -5.7871095 h 5.7792972 z"
|
||||
id="rect4356-5"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#4c97ff;fill-opacity:1;stroke:none;stroke-width:1.25366771"
|
||||
d="m 23.7603,19.59536 h 8 v -8 h -2.220703 v 5.787109 H 23.7603 Z"
|
||||
id="rect4356-6"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#4c97ff;fill-opacity:1;stroke:none;stroke-width:1.25366771"
|
||||
d="m 0.2260788,11.527481 v 8 h 8 v -2.220703 h -5.787109 v -5.779297 z"
|
||||
id="rect4356-7"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 => ({
|
||||
|
||||
@@ -16,4 +16,6 @@ $sound-tertiary: #A63FA6;
|
||||
|
||||
$control-primary: #FFAB19;
|
||||
|
||||
$data-primary: #FF8C1A;
|
||||
|
||||
$form-border: #E9EEF2;
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
@@ -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');
|
||||
|
||||