Merge branch 'saumya1906-issue266'

This commit is contained in:
Cassie Tarakajian 2017-11-14 17:18:44 -05:00
commit f6b42e0c41
7 changed files with 639 additions and 518 deletions

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<g>
<path d="M76.002,52.608c0,14.32-11.681,26.001-26.001,26.001c-14.4,0-26-11.681-26-26.001c0-14.4,11.6-26,26-26
C64.321,26.608,76.002,38.208,76.002,52.608z M54.641,39.168c0-2.48-2-4.48-4.56-4.48c-2.56,0-4.56,2-4.56,4.48
c0,2.56,2,4.64,4.56,4.64C52.641,43.808,54.641,41.808,54.641,39.168z M54.001,45.968h-7.76v22.481h7.76V45.968z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 828 B

View File

@ -1,15 +1,14 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import InlineSVG from 'react-inlinesvg'; import InlineSVG from 'react-inlinesvg';
import classNames from 'classnames'; import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
// import { bindActionCreators } from 'redux'; // import { bindActionCreators } from 'redux';
// import { connect } from 'react-redux'; // import { connect } from 'react-redux';
// import * as PreferencesActions from '../actions/preferences'; // import * as PreferencesActions from '../actions/preferences';
const exitUrl = require('../../../images/exit.svg');
const plusUrl = require('../../../images/plus.svg'); const plusUrl = require('../../../images/plus.svg');
const minusUrl = require('../../../images/minus.svg'); const minusUrl = require('../../../images/minus.svg');
const beepUrl = require('../../../sounds/audioAlert.mp3'); const beepUrl = require('../../../sounds/audioAlert.mp3');
// import { debounce } from 'lodash'; const infoUrl = require('../../../images/information.svg');
class Preferences extends React.Component { class Preferences extends React.Component {
constructor(props) { constructor(props) {
@ -48,264 +47,289 @@ class Preferences extends React.Component {
render() { render() {
const beep = new Audio(beepUrl); const beep = new Audio(beepUrl);
const preferencesContainerClass = classNames({
'preferences': true,
'preferences--selected': this.props.isVisible
});
return ( return (
<section className={preferencesContainerClass} tabIndex="0" title="preference-menu"> <section className="preferences" tabIndex="0" title="preference-menu">
<div className="preferences__heading"> <Tabs>
<h2 className="preferences__title">Preferences</h2> <TabList>
<button <div className="preference__subheadings">
className="preferences__exit-button" <Tab><h4 className="preference__subheading">General Settings</h4></Tab>
onClick={this.props.closePreferences} <Tab><h4 className="preference__subheading">Sketch Settings</h4></Tab>
title="exit" <Tab><h4 className="preference__subheading">Accessibility</h4></Tab>
aria-label="exit preferences" </div>
> </TabList>
<InlineSVG src={exitUrl} alt="Exit Preferences" /> <TabPanel>
</button> <div className="preference">
</div> <h4 className="preference__title">Theme</h4>
<div className="preference__options">
<input
type="radio"
onChange={() => this.props.setTheme('light')}
aria-label="light theme on"
name="light theme"
id="light-theme-on"
className="preference__radio-button"
value="light"
checked={this.props.theme === 'light'}
/>
<label htmlFor="light-theme-on" className="preference__option">Light</label>
<input
type="radio"
onChange={() => this.props.setTheme('dark')}
aria-label="dark theme on"
name="dark theme"
id="dark-theme-on"
className="preference__radio-button"
value="dark"
checked={this.props.theme === 'dark'}
/>
<label htmlFor="dark-theme-on" className="preference__option">Dark</label>
<input
type="radio"
onChange={() => this.props.setTheme('contrast')}
aria-label="high contrast theme on"
name="high contrast theme"
id="high-contrast-theme-on"
className="preference__radio-button"
value="contrast"
checked={this.props.theme === 'contrast'}
/>
<label htmlFor="high-contrast-theme-on" className="preference__option">High Contrast</label>
</div>
</div>
<div className="preference">
<h4 className="preference__title">Text size</h4>
<button
className="preference__minus-button"
onClick={() => this.props.setFontSize(this.props.fontSize - 2)}
aria-label="decrease font size"
>
<InlineSVG src={minusUrl} alt="Decrease Font Size" />
<h6 className="preference__label">Decrease</h6>
</button>
<input
className="preference__value"
aria-live="polite"
aria-atomic="true"
role="status"
value={this.props.fontSize}
onChange={this.handleUpdateFont}
ref={(element) => { this.fontSizeInput = element; }}
onClick={() => {
this.fontSizeInput.select();
}}
>
</input>
<button
className="preference__plus-button"
onClick={() => this.props.setFontSize(this.props.fontSize + 2)}
aria-label="increase font size"
>
<InlineSVG src={plusUrl} alt="Increase Font Size" />
<h6 className="preference__label">Increase</h6>
</button>
</div>
<div className="preference">
<h4 className="preference__title">Indentation amount</h4>
<button
className="preference__minus-button"
onClick={() => this.props.setIndentation(this.props.indentationAmount - 2)}
aria-label="decrease indentation amount"
>
<InlineSVG src={minusUrl} alt="DecreaseIndentation Amount" />
<h6 className="preference__label">Decrease</h6>
</button>
<input
className="preference__value"
aria-live="polite"
aria-atomic="true"
role="status"
value={this.props.indentationAmount}
onChange={this.handleUpdateIndentation}
ref={(element) => { this.indentationInput = element; }}
onClick={() => {
this.indentationInput.select();
}}
>
</input>
<button
className="preference__plus-button"
onClick={() => this.props.setIndentation(this.props.indentationAmount + 2)}
aria-label="increase indentation amount"
>
<InlineSVG src={plusUrl} alt="IncreaseIndentation Amount" />
<h6 className="preference__label">Increase</h6>
</button>
<input
type="radio"
onChange={this.props.indentWithSpace}
aria-label="indentation with space"
name="indentation"
id="indentation-space"
className="preference__radio-button"
value="Spaces"
checked={!this.props.isTabIndent}
/>
<label
htmlFor="indentation-space"
className="preference__option preference__whitespace-button"
>
Spaces
</label>
<input
type="radio"
onChange={this.props.indentWithTab}
aria-label="indentation with tab"
name="indentation"
id="indentation-tab"
className="preference__radio-button"
value="Tabs"
checked={this.props.isTabIndent}
/>
<label htmlFor="indentation-tab" className="preference__option preference__whitespace-button">Tabs</label>
</div>
<div className="preference">
<h4 className="preference__title">Autosave</h4>
<div className="preference__options">
<input
type="radio"
onChange={() => this.props.setAutosave(true)}
aria-label="autosave on"
name="autosave"
id="autosave-on"
className="preference__radio-button"
value="On"
checked={this.props.autosave}
/>
<label htmlFor="autosave-on" className="preference__option">On</label>
<input
type="radio"
onChange={() => this.props.setAutosave(false)}
aria-label="autosave off"
name="autosave"
id="autosave-off"
className="preference__radio-button"
value="Off"
checked={!this.props.autosave}
/>
<label htmlFor="autosave-off" className="preference__option">Off</label>
</div>
</div>
</TabPanel>
<TabPanel>
{/* <div className="preference">
<h4 className="preference__title">Add a p5.js or an external library</h4>
</div> */}
<div className="preference">
<h4 className="preference__title">Security Protocol</h4>
<div className="preference__serve-secure">
<input
id="serve-secure"
type="checkbox"
checked={this.props.serveSecure || false}
onChange={(event) => {
this.props.setServeSecure(event.target.checked);
}}
/>
<label htmlFor="serve-secure">Serve over HTTPS</label>
<span
className="serve-secture__tooltip tooltipped tooltipped-n tooltipped-no-delay tooltipped-multiline"
aria-label={'Choose HTTPS if you need to \n • access a microphone or webcam \n'
+ '• access an API served over HTTPS \n\n'
+ 'Choose HTTP if you need to \n'
+ '• access an API served over HTTP'}
>
<InlineSVG src={infoUrl} className="serve-secure__icon" />
</span>
</div>
</div>
</TabPanel>
<TabPanel>
<div className="preference">
<h4 className="preference__title">Lint warning sound</h4>
<div className="preference__options">
<input
type="radio"
onChange={() => this.props.setLintWarning(true)}
aria-label="lint warning on"
name="lint warning"
id="lint-warning-on"
className="preference__radio-button"
value="On"
checked={this.props.lintWarning}
/>
<label htmlFor="lint-warning-on" className="preference__option">On</label>
<input
type="radio"
onChange={() => this.props.setLintWarning(false)}
aria-label="lint warning off"
name="lint warning"
id="lint-warning-off"
className="preference__radio-button"
value="Off"
checked={!this.props.lintWarning}
/>
<label htmlFor="lint-warning-off" className="preference__option">Off</label>
<button
className="preference__preview-button"
onClick={() => beep.play()}
aria-label="preview sound"
>
Preview sound
</button>
</div>
</div>
<div className="preference">
<h4 className="preference__title">Accessible text-based canvas</h4>
<h6 className="preference__subtitle">Used with screen reader</h6>
<div className="preference"> <div className="preference__options">
<h4 className="preference__title">Text size</h4> <input
<button type="checkbox"
className="preference__minus-button" onChange={(event) => {
onClick={() => this.props.setFontSize(this.props.fontSize - 2)} this.props.setTextOutput(event.target.checked);
aria-label="decrease font size" }}
> aria-label="text output on"
<InlineSVG src={minusUrl} alt="Decrease Font Size" /> name="text output"
<h6 className="preference__label">Decrease</h6> id="text-output-on"
</button> value="On"
<input checked={(this.props.textOutput)}
className="preference__value" />
aria-live="polite" <label htmlFor="text-output-on" className="preference__option preference__canvas">Plain-text</label>
aria-atomic="true" <input
role="status" type="checkbox"
value={this.props.fontSize} onChange={(event) => {
onChange={this.handleUpdateFont} this.props.setGridOutput(event.target.checked);
ref={(element) => { this.fontSizeInput = element; }} }}
onClick={() => { aria-label="table output on"
this.fontSizeInput.select(); name="table output"
}} id="table-output-on"
> value="On"
</input> checked={(this.props.gridOutput)}
<button />
className="preference__plus-button" <label htmlFor="table-output-on" className="preference__option preference__canvas">Table-text</label>
onClick={() => this.props.setFontSize(this.props.fontSize + 2)} <input
aria-label="increase font size" type="checkbox"
> onChange={(event) => {
<InlineSVG src={plusUrl} alt="Increase Font Size" /> this.props.setSoundOutput(event.target.checked);
<h6 className="preference__label">Increase</h6> }}
</button> aria-label="sound output on"
</div> name="sound output"
id="sound-output-on"
<div className="preference"> value="On"
<h4 className="preference__title">Indentation amount</h4> checked={(this.props.soundOutput)}
<button />
className="preference__minus-button" <label htmlFor="sound-output-on" className="preference__option preference__canvas">Sound</label>
onClick={() => this.props.setIndentation(this.props.indentationAmount - 2)} </div>
aria-label="decrease indentation amount" </div>
> </TabPanel>
<InlineSVG src={minusUrl} alt="DecreaseIndentation Amount" /> </Tabs>
<h6 className="preference__label">Decrease</h6>
</button>
<input
className="preference__value"
aria-live="polite"
aria-atomic="true"
role="status"
value={this.props.indentationAmount}
onChange={this.handleUpdateIndentation}
ref={(element) => { this.indentationInput = element; }}
onClick={() => {
this.indentationInput.select();
}}
>
</input>
<button
className="preference__plus-button"
onClick={() => this.props.setIndentation(this.props.indentationAmount + 2)}
aria-label="increase indentation amount"
>
<InlineSVG src={plusUrl} alt="IncreaseIndentation Amount" />
<h6 className="preference__label">Increase</h6>
</button>
<div className="preference__vertical-list">
<input
type="radio"
onChange={this.props.indentWithSpace}
aria-label="indentation with space"
name="indentation"
id="indentation-space"
className="preference__radio-button"
value="Spaces"
checked={!this.props.isTabIndent}
/>
<label htmlFor="indentation-space" className="preference__option">Spaces</label>
<input
type="radio"
onChange={this.props.indentWithTab}
aria-label="indentation with tab"
name="indentation"
id="indentation-tab"
className="preference__radio-button"
value="Tabs"
checked={this.props.isTabIndent}
/>
<label htmlFor="indentation-tab" className="preference__option">Tabs</label>
</div>
</div>
<div className="preference">
<h4 className="preference__title">Autosave</h4>
<div className="preference__options">
<input
type="radio"
onChange={() => this.props.setAutosave(true)}
aria-label="autosave on"
name="autosave"
id="autosave-on"
className="preference__radio-button"
value="On"
checked={this.props.autosave}
/>
<label htmlFor="autosave-on" className="preference__option">On</label>
<input
type="radio"
onChange={() => this.props.setAutosave(false)}
aria-label="autosave off"
name="autosave"
id="autosave-off"
className="preference__radio-button"
value="Off"
checked={!this.props.autosave}
/>
<label htmlFor="autosave-off" className="preference__option">Off</label>
</div>
</div>
<div className="preference">
<h4 className="preference__title">Theme</h4>
<div className="preference__options">
<input
type="radio"
onChange={() => this.props.setTheme('light')}
aria-label="light theme on"
name="light theme"
id="light-theme-on"
className="preference__radio-button"
value="light"
checked={this.props.theme === 'light'}
/>
<label htmlFor="light-theme-on" className="preference__option">Light</label>
<input
type="radio"
onChange={() => this.props.setTheme('dark')}
aria-label="dark theme on"
name="dark theme"
id="dark-theme-on"
className="preference__radio-button"
value="dark"
checked={this.props.theme === 'dark'}
/>
<label htmlFor="dark-theme-on" className="preference__option">Dark</label>
<input
type="radio"
onChange={() => this.props.setTheme('contrast')}
aria-label="contrast theme on"
name="contrast theme"
id="contrast-theme-on"
className="preference__radio-button"
value="contrast"
checked={this.props.theme === 'contrast'}
/>
<label htmlFor="contrast-theme-on" className="preference__option">High contrast</label>
</div>
</div>
<div className="preference">
<h4 className="preference__title">Lint warning sound</h4>
<div className="preference__options">
<input
type="radio"
onChange={() => this.props.setLintWarning(true)}
aria-label="lint warning on"
name="lint warning"
id="lint-warning-on"
className="preference__radio-button"
value="On"
checked={this.props.lintWarning}
/>
<label htmlFor="lint-warning-on" className="preference__option">On</label>
<input
type="radio"
onChange={() => this.props.setLintWarning(false)}
aria-label="lint warning off"
name="lint warning"
id="lint-warning-off"
className="preference__radio-button"
value="Off"
checked={!this.props.lintWarning}
/>
<label htmlFor="lint-warning-off" className="preference__option">Off</label>
<button
className="preference__preview-button"
onClick={() => beep.play()}
aria-label="preview sound"
>
Preview sound
</button>
</div>
</div>
<div className="preference">
<h4 className="preference__title">Accessible text-based canvas</h4>
<h6 className="preference__subtitle">Used with screen reader</h6>
<div className="preference__options">
<input
type="checkbox"
onChange={(event) => {
this.props.setTextOutput(event.target.checked);
}}
aria-label="text output on"
name="text output"
id="text-output-on"
value="On"
checked={(this.props.textOutput)}
/>
<label htmlFor="text-output-on" className="preference__option preference__canvas">Plain-text</label>
<input
type="checkbox"
onChange={(event) => {
this.props.setGridOutput(event.target.checked);
}}
aria-label="table output on"
name="table output"
id="table-output-on"
value="On"
checked={(this.props.gridOutput)}
/>
<label htmlFor="table-output-on" className="preference__option preference__canvas">Table-text</label>
<input
type="checkbox"
onChange={(event) => {
this.props.setSoundOutput(event.target.checked);
}}
aria-label="sound output on"
name="sound output"
id="sound-output-on"
value="On"
checked={(this.props.soundOutput)}
/>
<label htmlFor="sound-output-on" className="preference__option preference__canvas">Sound</label>
</div>
</div>
</section> </section>
); );
} }
} }
Preferences.propTypes = { Preferences.propTypes = {
isVisible: PropTypes.bool.isRequired,
closePreferences: PropTypes.func.isRequired,
fontSize: PropTypes.number.isRequired, fontSize: PropTypes.number.isRequired,
indentationAmount: PropTypes.number.isRequired, indentationAmount: PropTypes.number.isRequired,
setIndentation: PropTypes.func.isRequired, setIndentation: PropTypes.func.isRequired,
@ -324,7 +348,13 @@ Preferences.propTypes = {
lintWarning: PropTypes.bool.isRequired, lintWarning: PropTypes.bool.isRequired,
setLintWarning: PropTypes.func.isRequired, setLintWarning: PropTypes.func.isRequired,
theme: PropTypes.string.isRequired, theme: PropTypes.string.isRequired,
serveSecure: PropTypes.bool.isRequired,
setServeSecure: PropTypes.func.isRequired,
setTheme: PropTypes.func.isRequired setTheme: PropTypes.func.isRequired
}; };
Preferences.defaultProps = {
currentUser: undefined
};
export default Preferences; export default Preferences;

View File

@ -246,29 +246,37 @@ class IDEView extends React.Component {
currentUser={this.props.user.username} currentUser={this.props.user.username}
showHelpModal={this.props.showHelpModal} showHelpModal={this.props.showHelpModal}
/> />
<Preferences {this.props.ide.preferencesIsVisible &&
isVisible={this.props.ide.preferencesIsVisible} <Overlay
closePreferences={this.props.closePreferences} title="Settings"
fontSize={this.props.preferences.fontSize} ariaLabel="settings"
indentationAmount={this.props.preferences.indentationAmount} closeOverlay={this.props.closePreferences}
setIndentation={this.props.setIndentation} >
indentWithSpace={this.props.indentWithSpace} <Preferences
indentWithTab={this.props.indentWithTab} fontSize={this.props.preferences.fontSize}
isTabIndent={this.props.preferences.isTabIndent} indentationAmount={this.props.preferences.indentationAmount}
setFontSize={this.props.setFontSize} setIndentation={this.props.setIndentation}
autosave={this.props.preferences.autosave} indentWithSpace={this.props.indentWithSpace}
setAutosave={this.props.setAutosave} indentWithTab={this.props.indentWithTab}
lintWarning={this.props.preferences.lintWarning} isTabIndent={this.props.preferences.isTabIndent}
setLintWarning={this.props.setLintWarning} setFontSize={this.props.setFontSize}
textOutput={this.props.preferences.textOutput} autosave={this.props.preferences.autosave}
gridOutput={this.props.preferences.gridOutput} setAutosave={this.props.setAutosave}
soundOutput={this.props.preferences.soundOutput} lintWarning={this.props.preferences.lintWarning}
setTextOutput={this.props.setTextOutput} setLintWarning={this.props.setLintWarning}
setGridOutput={this.props.setGridOutput} textOutput={this.props.preferences.textOutput}
setSoundOutput={this.props.setSoundOutput} gridOutput={this.props.preferences.gridOutput}
theme={this.props.preferences.theme} soundOutput={this.props.preferences.soundOutput}
setTheme={this.props.setTheme} setTextOutput={this.props.setTextOutput}
/> setGridOutput={this.props.setGridOutput}
setSoundOutput={this.props.setSoundOutput}
theme={this.props.preferences.theme}
setTheme={this.props.setTheme}
serveSecure={this.props.project.serveSecure}
setServeSecure={this.props.setServeSecure}
/>
</Overlay>
}
<div className="editor-preview-container"> <div className="editor-preview-container">
<SplitPane <SplitPane
split="vertical" split="vertical"
@ -361,25 +369,23 @@ class IDEView extends React.Component {
<div className="preview-frame-overlay" ref={(element) => { this.overlay = element; }}> <div className="preview-frame-overlay" ref={(element) => { this.overlay = element; }}>
</div> </div>
<div> <div>
{(() => { {(
if (
( (
(this.props.preferences.textOutput || (this.props.preferences.textOutput ||
this.props.preferences.gridOutput || this.props.preferences.gridOutput ||
this.props.preferences.soundOutput this.props.preferences.soundOutput
) && this.props.ide.isPlaying ) &&
) || this.props.ide.isAccessibleOutputPlaying) { this.props.ide.isPlaying
return ( ) ||
<AccessibleOutput this.props.ide.isAccessibleOutputPlaying
isPlaying={this.props.ide.isPlaying} ) &&
previewIsRefreshing={this.props.ide.previewIsRefreshing} <AccessibleOutput
textOutput={this.props.preferences.textOutput} isPlaying={this.props.ide.isPlaying}
gridOutput={this.props.preferences.gridOutput} previewIsRefreshing={this.props.ide.previewIsRefreshing}
/> textOutput={this.props.preferences.textOutput}
); gridOutput={this.props.preferences.gridOutput}
} />
return ''; }
})()}
</div> </div>
<PreviewFrame <PreviewFrame
htmlFile={this.props.htmlFile} htmlFile={this.props.htmlFile}
@ -405,131 +411,93 @@ class IDEView extends React.Component {
</SplitPane> </SplitPane>
</SplitPane> </SplitPane>
</div> </div>
{(() => { { this.props.ide.modalIsVisible &&
if (this.props.ide.modalIsVisible) { <NewFileModal
return ( canUploadMedia={this.props.user.authenticated}
<NewFileModal closeModal={this.props.closeNewFileModal}
canUploadMedia={this.props.user.authenticated} createFile={this.props.createFile}
closeModal={this.props.closeNewFileModal} />
createFile={this.props.createFile} }
/> { this.props.ide.newFolderModalVisible &&
); <NewFolderModal
} closeModal={this.props.closeNewFolderModal}
return ''; createFolder={this.props.createFolder}
})()} />
{(() => { }
if (this.props.ide.newFolderModalVisible) { { this.props.location.pathname.match(/sketches$/) &&
return ( <Overlay
<NewFolderModal ariaLabel="project list"
closeModal={this.props.closeNewFolderModal} title="Open a Sketch"
createFolder={this.props.createFolder} previousPath={this.props.ide.previousPath}
/> >
); <SketchList
} username={this.props.params.username}
return ''; user={this.props.user}
})()} />
{(() => { // eslint-disable-line </Overlay>
if (this.props.location.pathname.match(/sketches$/)) { }
return ( { this.props.location.pathname.match(/assets$/) &&
<Overlay <Overlay
ariaLabel="project list" title="Assets"
title="Open a Sketch" ariaLabel="asset list"
previousPath={this.props.ide.previousPath} previousPath={this.props.ide.previousPath}
> >
<SketchList <AssetList
username={this.props.params.username} username={this.props.params.username}
user={this.props.user} user={this.props.user}
/> />
</Overlay> </Overlay>
); }
} { this.props.location.pathname === '/about' &&
})()} <Overlay
{(() => { // eslint-disable-line previousPath={this.props.ide.previousPath}
if (this.props.location.pathname.match(/assets$/)) { title="Welcome"
return ( ariaLabel="about"
<Overlay >
title="Assets" <About previousPath={this.props.ide.previousPath} />
ariaLabel="asset list" </Overlay>
previousPath={this.props.ide.previousPath} }
> { this.props.ide.shareModalVisible &&
<AssetList <Overlay
username={this.props.params.username} title="Share This Sketch"
user={this.props.user} ariaLabel="share"
/> closeOverlay={this.props.closeShareModal}
</Overlay> >
); <ShareModal
} projectId={this.props.project.id}
})()} projectName={this.props.project.name}
{(() => { // eslint-disable-line ownerUsername={this.props.project.owner.username}
if (this.props.location.pathname === '/about') { />
return ( </Overlay>
<Overlay }
previousPath={this.props.ide.previousPath} { this.props.ide.keyboardShortcutVisible &&
title="Welcome" <Overlay
ariaLabel="about" title="Keyboard Shortcuts"
> ariaLabel="keyboard shortcuts"
<About previousPath={this.props.ide.previousPath} /> closeOverlay={this.props.closeKeyboardShortcutModal}
</Overlay> >
); <KeyboardShortcutModal />
} </Overlay>
})()} }
{(() => { // eslint-disable-line { this.props.ide.errorType &&
if (this.props.ide.shareModalVisible) { <Overlay
return ( title="Error"
<Overlay ariaLabel="error"
title="Share This Sketch" closeOverlay={this.props.hideErrorModal}
ariaLabel="share" >
closeOverlay={this.props.closeShareModal} <ErrorModal
> type={this.props.ide.errorType}
<ShareModal />
projectId={this.props.project.id} </Overlay>
projectName={this.props.project.name} }
ownerUsername={this.props.project.owner.username} { this.props.ide.helpType &&
/> <Overlay
</Overlay> title="Serve over HTTPS"
); closeOverlay={this.props.hideHelpModal}
} >
})()} <HTTPSModal />
{(() => { // eslint-disable-line </Overlay>
if (this.props.ide.keyboardShortcutVisible) { }
return (
<Overlay
title="Keyboard Shortcuts"
ariaLabel="keyboard shortcuts"
closeOverlay={this.props.closeKeyboardShortcutModal}
>
<KeyboardShortcutModal />
</Overlay>
);
}
})()}
{(() => { // eslint-disable-line
if (this.props.ide.errorType) {
return (
<Overlay
title="Error"
ariaLabel="error"
closeOverlay={this.props.hideErrorModal}
>
<ErrorModal
type={this.props.ide.errorType}
/>
</Overlay>
);
}
})()}
{(() => { // eslint-disable-line
if (this.props.ide.helpType) {
return (
<Overlay
title="Serve over HTTPS"
closeOverlay={this.props.hideHelpModal}
>
<HTTPSModal />
</Overlay>
);
}
})()}
</div> </div>
); );
} }

View File

@ -40,7 +40,7 @@
color: getThemifyVariable('button-hover-color'); color: getThemifyVariable('button-hover-color');
} }
font-family: Montserrat, sans-serif; font-family: Montserrat, sans-serif;
font-size: #{14 / $base-font-size}rem; font-size: #{12 / $base-font-size}rem;
} }
.tooltipped-n::before, .tooltipped-n::before,

View File

@ -29,7 +29,7 @@
.overlay__header { .overlay__header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding: #{30 / $base-font-size}rem #{20 / $base-font-size}rem #{30 / $base-font-size}rem #{20 / $base-font-size}rem; padding: #{20 / $base-font-size}rem;
flex: 1 0 auto; flex: 1 0 auto;
} }

View File

@ -1,153 +1,264 @@
.preferences { .preferences {
@extend %modal; width: 100%;
position: absolute; width: #{640 / $base-font-size}rem;
top: #{51 / $base-font-size}rem; max-width: 100%;
right: #{29 / $base-font-size}rem; min-height: #{460 / $base-font-size}rem;
width: #{288 / $base-font-size}rem; max-height: 100%;
display: none; z-index: 9999;
padding: #{14 / $base-font-size}rem #{20 / $base-font-size}rem #{2 / $base-font-size}rem #{20 / $base-font-size}rem ; padding: 0 #{20 / $base-font-size}rem #{2 / $base-font-size}rem #{20 / $base-font-size}rem ;
&--selected { display: flex;
display: flex; flex-direction: column;
flex-direction: column; outline: none;
}
@include themify() {
background-color: getThemifyVariable('editor-gutter-color');
}
outline: none;
} }
.preferences__exit-button { .preferences__exit-button {
@include icon(); @include icon();
padding-top: #{5 / $base-font-size}rem; padding-top: #{5 / $base-font-size}rem;
margin-right: #{-6 / $base-font-size}rem; margin-right: #{-6 / $base-font-size}rem;
} }
.preference__minus-button, .preference__minus-button,
.preference__plus-button { .preference__plus-button {
@include themify() { @include themify() {
@extend %preferences-button; @extend %preferences-button;
width: #{32 / $base-font-size}rem; width: #{32 / $base-font-size}rem;
height: #{32 / $base-font-size}rem; height: #{32 / $base-font-size}rem;
margin-left: #{6 / $base-font-size}rem; margin-left: #{6 / $base-font-size}rem;
line-height: #{40 / $base-font-size}rem; margin-right: #{10 / $base-font-size}rem;
& svg { line-height: #{40 / $base-font-size}rem;
width: #{10 / $base-font-size}rem; & svg {
} width: #{10 / $base-font-size}rem;
} }
}
}
.serve__over__https {
text-align: center;
margin-left: #{9 / $base-font-size}rem;
font-width: #{108 / $base-font-size}rem;
font-height: #{15 / $base-font-size}rem;
font-family: Montserrat;
font-size: #{12 / $base-font-size}rem;
margin-top: #{2 / $base-font-size}rem;
} }
.preferences__heading { .preferences__heading {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
margin-bottom: #{20 / $base-font-size}rem; @include themify() {
@include themify() { color: getThemifyVariable('heading-text-color');
color: getThemifyVariable('heading-text-color'); }
} }
.preferences__title{
width: #{90 / $base-font-size}rem;
height: #{25 / $base-font-size}rem;
font-family: Montserrat;
font-size: #{21 / $base-font-size}rem;
font-weight: bold;
text-align: left;
}
.preference__subheadings {
display: flex;
flex-wrap: wrap;
padding-bottom: #{0.1 / $base-font-size}rem;
@include themify() {
border-bottom: 1px solid getThemifyVariable('button-border-color');
}
} }
.preference { .preference {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
padding-bottom: #{12 / $base-font-size}rem; padding-bottom: #{12 / $base-font-size}rem;
& + & { & + & {
@include themify() { @include themify() {
border-top: 1px dashed getThemifyVariable('button-border-color'); border-top: 1px dashed getThemifyVariable('button-border-color');
} }
} }
} }
.preference__title { .preference__title {
width: 100%; width: 100%;
font-size: #{16 / $base-font-size}rem; font-size: #{16 / $base-font-size}rem;
margin-top: #{13 / $base-font-size}rem; margin-top: #{13 / $base-font-size}rem;
margin-bottom: #{7 / $base-font-size}rem; margin-bottom: #{7 / $base-font-size}rem;
@include themify() { @include themify() {
color: getThemifyVariable('heading-text-color'); color: getThemifyVariable('heading-text-color');
} }
} }
.preference__subtitle { .preference__subtitle {
@include themify() { @include themify() {
color: getThemifyVariable('inactive-text-color'); color: getThemifyVariable('inactive-text-color');
} }
width: 100%; width: 100%;
margin-bottom: #{10 / $base-font-size}rem; margin-bottom: #{10 / $base-font-size}rem;
margin-top: 0; margin-top: 0;
} }
.preference__value { .preference__value {
@include themify() { @include themify() {
border: #{1 / $base-font-size}rem solid getThemifyVariable('button-border-color'); border: #{1 / $base-font-size}rem solid getThemifyVariable('button-border-color');
background-color: getThemifyVariable('button-background-color'); background-color: getThemifyVariable('button-background-color');
color: getThemifyVariable('input-text-color'); color: getThemifyVariable('input-text-color');
} }
text-align: center; text-align: center;
border-radius: 0%; border-radius: 0%;
outline: none; outline: none;
width: #{44 / $base-font-size}rem; width: #{44 / $base-font-size}rem;
height: #{40 / $base-font-size}rem; height: #{40 / $base-font-size}rem;
margin: 0 #{26 / $base-font-size}rem; margin: 0 #{20 / $base-font-size}rem;
padding: 0; padding: 0;
font-size: #{16 / $base-font-size}rem; font-size: #{16 / $base-font-size}rem;
font-family: Inconsolata; font-family: Inconsolata;
} }
.preference__label { .preference__label {
@include themify() { @include themify() {
color: getThemifyVariable('inactive-text-color'); color: getThemifyVariable('inactive-text-color');
&:hover { &:hover {
color: getThemifyVariable('primary-text-color'); color: getThemifyVariable('primary-text-color');
} }
}
margin: #{-15 / $base-font-size}rem 0 0 #{-5 / $base-font-size}rem; }
font-size: #{9 / $base-font-size}rem; margin: #{-15 / $base-font-size}rem 0 0 #{-5 / $base-font-size}rem;
width: #{44 / $base-font-size}rem; font-size: #{9 / $base-font-size}rem;
width: #{44 / $base-font-size}rem;
}
.react-tabs__tab--selected {
@include themify() {
border-bottom: #{4 / $base-font-size}rem solid getThemifyVariable('button-background-hover-color');
}
}
.react-tabs__tab--selected .preference__subheading {
@include themify() {
color: getThemifyVariable('primary-text-color');
}
}
.react-tabs__tab {
text-align: center;
color: black;
display: flex;
align-items: center;
border-bottom: #{4 / $base-font-size}rem solid transparent;
& + & {
margin-left: #{45 / $base-font-size}rem;
}
}
.preference__subheading {
@include themify() {
color: getThemifyVariable('inactive-text-color');
&:hover, &:focus{
color: getThemifyVariable('primary-text-color');
cursor: pointer;
}
&:focus {
color: getThemifyVariable('primary-text-color');
cursor: pointer;
}
}
font-size: #{12 / $base-font-size}rem;
height: #{20 / $base-font-size}rem;
width: 100%;
margin: 0;
padding: 0 #{5 /$base-font-size}rem;
} }
.preference__vertical-list { .preference__vertical-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: #{44 / $base-font-size}rem; width: #{44 / $base-font-size}rem;
padding-left: #{25 / $base-font-size}rem; padding-left: #{25 / $base-font-size}rem;
}
.preference__add__resource {
font-size: #{14 / $base-font-size}rem;
line-height: 1.43;
text-align: left;
margin-left: #{5 / $base-font-size}rem;
margin-top: #{40 / $base-font-size}rem;
margin-bottom: #{10 / $base-font-size}rem;
@include themify() {
color: getThemifyVariable('inactive-text-color');
border-bottom: 1px dashed getThemifyVariable('button-border-color');
}
} }
.preference__radio-button { .preference__radio-button {
@extend %hidden-element; @extend %hidden-element;
} }
.preference__option { .preference__option {
@include themify() { @include themify() {
@extend %preference-option; @extend %preference-option;
padding-right: #{44 / $base-font-size}rem; margin-right: #{25 / $base-font-size}rem;
} }
display: flex;
flex-wrap: wrap;
flex-direction: row;
} }
.preference__option:last-child { .preference__option:last-child {
padding-right: 0; margin-right: 0;
} }
.preference__preview-button { .preference__preview-button {
@include themify() { @include themify() {
@extend %preference-option; @extend %preference-option;
} &:hover {
color: getThemifyVariable('button-background-hover-color');
}
}
margin-left: #{30 / $base-font-size}rem;
}
.preference__option.preference__whitespace-button {
padding-top: #{8 / $base-font-size}rem;
margin-right: 0;
margin-left: #{25 / $base-font-size}rem;
} }
.preference__options { .preference__options {
display: flex; display: flex;
justify-content: center;
} }
.preference__radio-button:checked + .preference__option { .preference__radio-button:checked + .preference__option {
@include themify() { @include themify() {
//for some reason this won't work for getThemifyVariable //for some reason this won't work for getThemifyVariable
color: map-get($theme-map, 'primary-text-color'); color: map-get($theme-map, 'primary-text-color');
} }
} }
.preference--hidden { .preference--hidden {
@extend %hidden-element; @extend %hidden-element;
} }
.preference__option.preference__canvas:not(:last-child) { .preference__option.preference__canvas:not(:last-child) {
padding-right: #{14 / $base-font-size}rem; padding-right: #{14 / $base-font-size}rem;
}
.preference__serve-secure {
display: flex;
align-items: center;
}
.serve-secure__icon {
@include icon();
& svg {
height: #{24 / $base-font-size}rem;
width: #{24 / $base-font-size}rem;
}
}
.serve-secture__tooltip:after {
text-align: left;
font-size: #{12 / $base-font-size}rem;
} }

View File

@ -111,6 +111,7 @@
"react-redux": "^4.4.5", "react-redux": "^4.4.5",
"react-router": "^2.6.0", "react-router": "^2.6.0",
"react-split-pane": "^0.1.44", "react-split-pane": "^0.1.44",
"react-tabs": "^1.1.0",
"redux": "^3.5.2", "redux": "^3.5.2",
"redux-devtools": "^3.3.1", "redux-devtools": "^3.3.1",
"redux-devtools-dock-monitor": "^1.1.1", "redux-devtools-dock-monitor": "^1.1.1",