diff options
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | ui/app/app.js | 2 | ||||
-rw-r--r-- | ui/app/components/account-dropdowns.js | 1 | ||||
-rw-r--r-- | ui/app/components/dropdown.js | 6 | ||||
-rw-r--r-- | ui/app/components/menu-droppo.js | 137 |
5 files changed, 145 insertions, 3 deletions
diff --git a/package.json b/package.json index 98066a172..60987559e 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,6 @@ "inject-css": "^0.1.1", "jazzicon": "^1.2.0", "loglevel": "^1.4.1", - "menu-droppo": "2.0.1", "metamask-logo": "^2.1.2", "mississippi": "^1.2.0", "mkdirp": "^0.5.1", @@ -109,6 +108,7 @@ "pumpify": "^1.3.4", "qrcode-npm": "0.0.3", "react": "^15.0.2", + "react-addons-css-transition-group": "^15.6.0", "react-dom": "^15.5.4", "react-hyperscript": "^2.2.2", "react-markdown": "^2.3.0", diff --git a/ui/app/app.js b/ui/app/app.js index 0592496fc..620b4617a 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -218,6 +218,7 @@ App.prototype.renderNetworkDropdown = function () { const isOpen = state.isNetworkMenuOpen return h(Dropdown, { + useCssTransition: true, isOpen, onClickOutside: (event) => { const { classList } = event.target @@ -355,6 +356,7 @@ App.prototype.renderDropdown = function () { const isOpen = state.isMainMenuOpen return h(Dropdown, { + useCssTransition: true, isOpen: isOpen, zIndex: 11, onClickOutside: (event) => { diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js index da92619e1..b23600e9b 100644 --- a/ui/app/components/account-dropdowns.js +++ b/ui/app/components/account-dropdowns.js @@ -65,6 +65,7 @@ class AccountDropdowns extends Component { return h( Dropdown, { + useCssTransition: true, // Hardcoded because account selector is temporarily in app-header style: { marginLeft: '-238px', marginTop: '38px', diff --git a/ui/app/components/dropdown.js b/ui/app/components/dropdown.js index 8cdfc13e8..34c7149ee 100644 --- a/ui/app/components/dropdown.js +++ b/ui/app/components/dropdown.js @@ -1,14 +1,14 @@ const Component = require('react').Component const PropTypes = require('react').PropTypes const h = require('react-hyperscript') -const MenuDroppo = require('menu-droppo') +const MenuDroppo = require('./menu-droppo') const extend = require('xtend') const noop = () => {} class Dropdown extends Component { render () { - const { isOpen, onClickOutside, style, innerStyle, children } = this.props + const { isOpen, onClickOutside, style, innerStyle, children, useCssTransition } = this.props const innerStyleDefaults = extend({ borderRadius: '4px', @@ -20,6 +20,7 @@ class Dropdown extends Component { return h( MenuDroppo, { + useCssTransition, isOpen, zIndex: 11, onClickOutside, @@ -43,6 +44,7 @@ class Dropdown extends Component { Dropdown.defaultProps = { isOpen: false, onClick: noop, + useCssTransition: false, } Dropdown.propTypes = { diff --git a/ui/app/components/menu-droppo.js b/ui/app/components/menu-droppo.js new file mode 100644 index 000000000..a9370a7c8 --- /dev/null +++ b/ui/app/components/menu-droppo.js @@ -0,0 +1,137 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const findDOMNode = require('react-dom').findDOMNode +const ReactCSSTransitionGroup = require('react-addons-css-transition-group') + +module.exports = MenuDroppoComponent + + +inherits(MenuDroppoComponent, Component) +function MenuDroppoComponent() { + Component.call(this) +} + +MenuDroppoComponent.prototype.render = function() { + + const speed = this.props.speed || '300ms' + const useCssTransition = this.props.useCssTransition + const zIndex = ('zIndex' in this.props) ? this.props.zIndex : 0 + + this.manageListeners() + + let style = this.props.style || {} + if (!('position' in style)) { + style.position = 'fixed' + } + style.zIndex = zIndex + + return ( + h('.menu-droppo-container', { + style, + }, [ + h('style', ` + .menu-droppo-enter { + transition: transform ${speed} ease-in-out; + transform: translateY(-200%); + } + + .menu-droppo-enter.menu-droppo-enter-active { + transition: transform ${speed} ease-in-out; + transform: translateY(0%); + } + + .menu-droppo-leave { + transition: transform ${speed} ease-in-out; + transform: translateY(0%); + } + + .menu-droppo-leave.menu-droppo-leave-active { + transition: transform ${speed} ease-in-out; + transform: translateY(-200%); + } + `), + + !!useCssTransition + ? h(ReactCSSTransitionGroup, { + className: 'css-transition-group', + transitionName: 'menu-droppo', + transitionEnterTimeout: parseInt(speed), + transitionLeaveTimeout: parseInt(speed), + }, this.renderPrimary()) + : this.renderPrimary() + ]) + ) +} + +MenuDroppoComponent.prototype.renderPrimary = function() { + const isOpen = this.props.isOpen + if (!isOpen) { + return null + return h('span', { + key: 'menu-droppo-null', + style: { + height: '0px', + } + }) + } + + let innerStyle = this.props.innerStyle || {} + + return ( + h('.menu-droppo', { + key: 'menu-droppo-drawer', + style: innerStyle, + }, + [ this.props.children ]) + ) +} + +MenuDroppoComponent.prototype.manageListeners = function() { + const isOpen = this.props.isOpen + const onClickOutside = this.props.onClickOutside + + if (isOpen) { + this.outsideClickHandler = onClickOutside + } else if (isOpen) { + this.outsideClickHandler = null + } +} + +MenuDroppoComponent.prototype.componentDidMount = function() { + if (this && document.body) { + this.globalClickHandler = this.globalClickOccurred.bind(this); + document.body.addEventListener('click', this.globalClickHandler) + var container = findDOMNode(this) + this.container = container + } +} + +MenuDroppoComponent.prototype.componentWillUnmount = function() { + if (this && document.body) { + document.body.removeEventListener('click', this.globalClickHandler) + } +} + +MenuDroppoComponent.prototype.globalClickOccurred = function(event) { + const target = event.target + const container = findDOMNode(this) + const isOpen = this.props.isOpen + + if (target !== container && + !isDescendant(this.container, event.target) && + this.outsideClickHandler) { + this.outsideClickHandler(event) + } +} + +function isDescendant(parent, child) { + var node = child.parentNode; + while (node != null) { + if (node == parent) { + return true; + } + node = node.parentNode; + } + return false; +} |