diff --git a/client/common/icons.jsx b/client/common/icons.jsx
index 624f9f31..215083a6 100644
--- a/client/common/icons.jsx
+++ b/client/common/icons.jsx
@@ -12,6 +12,7 @@ import Exit from '../images/exit.svg';
import DropdownArrow from '../images/down-filled-triangle.svg';
import Preferences from '../images/preferences.svg';
import Play from '../images/triangle-arrow-right.svg';
+import More from '../images/more.svg';
import Code from '../images/code.svg';
import Terminal from '../images/terminal.svg';
@@ -77,4 +78,6 @@ export const ExitIcon = withLabel(Exit);
export const DropdownArrowIcon = withLabel(DropdownArrow);
export const PreferencesIcon = withLabel(Preferences);
export const PlayIcon = withLabel(Play);
+export const MoreIcon = withLabel(More);
export const TerminalIcon = withLabel(Terminal);
+export const CodeIcon = withLabel(Code);
diff --git a/client/components/Dropdown.jsx b/client/components/Dropdown.jsx
new file mode 100644
index 00000000..bd2169b8
--- /dev/null
+++ b/client/components/Dropdown.jsx
@@ -0,0 +1,92 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Link } from 'react-router';
+import styled from 'styled-components';
+import { remSize, prop, common } from '../theme';
+import IconButton from './mobile/IconButton';
+import Button from '../common/Button';
+
+const DropdownWrapper = styled.ul`
+ background-color: ${prop('Modal.background')};
+ border: 1px solid ${prop('Modal.border')};
+ box-shadow: 0 0 18px 0 ${prop('shadowColor')};
+ color: ${prop('primaryTextColor')};
+
+ position: absolute;
+ right: ${props => (props.right ? 0 : 'initial')};
+ left: ${props => (props.left ? 0 : 'initial')};
+
+ ${props => (props.align === 'right' && 'right: 0;')}
+ ${props => (props.align === 'left' && 'left: 0;')}
+
+
+ text-align: left;
+ width: ${remSize(180)};
+ display: flex;
+ flex-direction: column;
+ height: auto;
+ z-index: 9999;
+ border-radius: ${remSize(6)};
+
+ & li:first-child { border-radius: ${remSize(5)} ${remSize(5)} 0 0; }
+ & li:last-child { border-radius: 0 0 ${remSize(5)} ${remSize(5)}; }
+
+ & li:hover {
+
+ background-color: ${prop('Button.hover.background')};
+ color: ${prop('Button.hover.foreground')};
+
+ & button, & a {
+ color: ${prop('Button.hover.foreground')};
+ }
+ }
+
+ li {
+ height: ${remSize(36)};
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+
+ & button,
+ & a {
+ color: ${prop('primaryTextColor')};
+ width: 100%;
+ text-align: left;
+ padding: ${remSize(8)} ${remSize(16)};
+ }
+ }
+`;
+
+// TODO: Add Icon to the left of the items in the menu
+// const MaybeIcon = (Element, label) => Element && ;
+
+const Dropdown = ({ items, align }) => (
+
+ {/* className="nav__items-left" */}
+ {items && items.map(({ title, icon, href }) => (
+
+
+ {/* {MaybeIcon(icon, `Navigate to ${title}`)} */}
+ {title}
+
+
+ ))
+ }
+
+);
+
+Dropdown.propTypes = {
+ align: PropTypes.oneOf(['left', 'right']),
+ items: PropTypes.arrayOf(PropTypes.shape({
+ action: PropTypes.func,
+ icon: PropTypes.func,
+ href: PropTypes.string
+ })),
+};
+
+Dropdown.defaultProps = {
+ items: [],
+ align: null
+};
+
+export default Dropdown;
diff --git a/client/components/OverlayManager.jsx b/client/components/OverlayManager.jsx
new file mode 100644
index 00000000..1b3b040c
--- /dev/null
+++ b/client/components/OverlayManager.jsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { createPortal } from 'react-dom';
+
+const OverlayManager = ({ overlay, hideOverlay }) => {
+ // const [visible, trigger, setRef] = useModalBehavior();
+
+ const jsx = (
+
+ {/*
+ {visible && }
+
*/}
+
+ );
+
+ return jsx && createPortal(jsx, document.body);
+};
+
+
+OverlayManager.propTypes = {
+ overlay: PropTypes.string,
+ hideOverlay: PropTypes.func.isRequired,
+};
+
+OverlayManager.defaultProps = { overlay: null };
+
+export default OverlayManager;
diff --git a/client/components/mobile/Header.jsx b/client/components/mobile/Header.jsx
index cf727b7c..ded0b3be 100644
--- a/client/components/mobile/Header.jsx
+++ b/client/components/mobile/Header.jsx
@@ -31,7 +31,9 @@ const HeaderDiv = styled.div`
const IconContainer = styled.div`
margin-left: ${props => (props.leftButton ? remSize(32) : remSize(4))};
+ list-style: none;
display: flex;
+ flex-direction: horizontal;
`;
diff --git a/client/components/useAsModal.jsx b/client/components/useAsModal.jsx
new file mode 100644
index 00000000..1afa0d30
--- /dev/null
+++ b/client/components/useAsModal.jsx
@@ -0,0 +1,10 @@
+import React from 'react';
+import { useModalBehavior } from '../utils/custom-hooks';
+
+export default (component) => {
+ const [visible, trigger, setRef] = useModalBehavior();
+
+ const wrapper = () =>
{visible && component}
; // eslint-disable-line
+
+ return [trigger, wrapper];
+};
diff --git a/client/images/more.svg b/client/images/more.svg
new file mode 100644
index 00000000..ee41de95
--- /dev/null
+++ b/client/images/more.svg
@@ -0,0 +1,5 @@
+
diff --git a/client/modules/App/App.jsx b/client/modules/App/App.jsx
index af441a9d..5f9adb6a 100644
--- a/client/modules/App/App.jsx
+++ b/client/modules/App/App.jsx
@@ -34,7 +34,8 @@ class App extends React.Component {
render() {
return (
- {this.state.isMounted && !window.devToolsExtension && getConfig('NODE_ENV') === 'development' && }
+ {/* FIXME: Remove false */}
+ {false && this.state.isMounted && !window.devToolsExtension && getConfig('NODE_ENV') === 'development' && }
{this.props.children}
);
diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx
index ddb6d55e..749caaaa 100644
--- a/client/modules/IDE/components/Console.jsx
+++ b/client/modules/IDE/components/Console.jsx
@@ -88,8 +88,6 @@ const Console = () => {
const cm = useRef({});
- useDidUpdate(() => { cm.current.scrollTop = cm.current.scrollHeight; });
-
const consoleClass = classNames({
'preview-console': true,
'preview-console--collapsed': !isExpanded
diff --git a/client/modules/IDE/pages/MobileIDEView.jsx b/client/modules/IDE/pages/MobileIDEView.jsx
index 43851092..badeda6b 100644
--- a/client/modules/IDE/pages/MobileIDEView.jsx
+++ b/client/modules/IDE/pages/MobileIDEView.jsx
@@ -7,6 +7,7 @@ import styled from 'styled-components';
// Imports to be Refactored
import { bindActionCreators } from 'redux';
+
import * as FileActions from '../actions/files';
import * as IDEActions from '../actions/ide';
import * as ProjectActions from '../actions/project';
@@ -19,7 +20,7 @@ import { getHTMLFile } from '../reducers/files';
// Local Imports
import Editor from '../components/Editor';
-import { PreferencesIcon, PlayIcon, ExitIcon } from '../../../common/icons';
+import { PlayIcon, ExitIcon, MoreIcon } from '../../../common/icons';
import IconButton from '../../../components/mobile/IconButton';
import Header from '../../../components/mobile/Header';
@@ -28,7 +29,11 @@ import Footer from '../../../components/mobile/Footer';
import IDEWrapper from '../../../components/mobile/IDEWrapper';
import Console from '../components/Console';
import { remSize } from '../../../theme';
+// import OverlayManager from '../../../components/OverlayManager';
import ActionStrip from '../../../components/mobile/ActionStrip';
+import useAsModal from '../../../components/useAsModal';
+import { PreferencesIcon } from '../../../common/icons';
+import Dropdown from '../../../components/Dropdown';
const isUserOwner = ({ project, user }) => (project.owner && project.owner.id === user.id);
@@ -37,17 +42,30 @@ const Expander = styled.div`
height: ${props => (props.expanded ? remSize(160) : remSize(27))};
`;
+const NavItem = styled.li`
+ position: relative;
+`;
+
+const headerNavOptions = [
+ { icon: PreferencesIcon, title: 'Preferences', href: '/mobile/preferences', },
+ { icon: PreferencesIcon, title: 'Examples', href: '/mobile/examples' },
+ { icon: PreferencesIcon, title: 'Original Editor', href: '/', },
+];
+
+
const MobileIDEView = (props) => {
const {
preferences, ide, editorAccessibility, project, updateLintMessage, clearLintMessage,
selectedFile, updateFileContent, files,
- closeEditorOptions, showEditorOptions, showKeyboardShortcutModal, setUnsavedChanges,
+ closeEditorOptions, showEditorOptions,
startRefreshSketch, stopSketch, expandSidebar, collapseSidebar, clearConsole, console,
showRuntimeErrorWarning, hideRuntimeErrorWarning, startSketch
} = props;
const [tmController, setTmController] = useState(null); // eslint-disable-line
- const [overlay, setOverlay] = useState(null); // eslint-disable-line
+
+
+ const [triggerNavDropdown, NavDropDown] = useAsModal();
return (
@@ -58,13 +76,17 @@ const MobileIDEView = (props) => {
}
>
- setOverlay('preferences')}
- icon={PreferencesIcon}
- aria-label="Open preferences menu"
- />
- { startSketch(); }} icon={PlayIcon} aria-label="Run sketch" />
+
+
+
+
+
+ { startSketch(); }} icon={PlayIcon} aria-label="Run sketch" />
+
@@ -82,9 +104,7 @@ const MobileIDEView = (props) => {
editorOptionsVisible={ide.editorOptionsVisible}
showEditorOptions={showEditorOptions}
closeEditorOptions={closeEditorOptions}
- showKeyboardShortcutModal={showKeyboardShortcutModal}
- setUnsavedChanges={setUnsavedChanges}
- isPlaying={ide.isPlaying}
+ showKeyboard={ide.isPlaying}
theme={preferences.theme}
startRefreshSketch={startRefreshSketch}
stopSketch={stopSketch}
@@ -103,6 +123,7 @@ const MobileIDEView = (props) => {
provideController={setTmController}
/>
+