From c87c6c66043846274364e49555ae3e7ec03c8d9a Mon Sep 17 00:00:00 2001 From: Pierre Bertet Date: Thu, 28 Mar 2019 19:04:50 +0100 Subject: [PATCH 1/2] Menu panel footer separator --- src/components/MenuPanel/MenuPanel.js | 88 ++++++++++++++------- src/components/MenuPanel/MenuPanelFooter.js | 25 ++++++ 2 files changed, 83 insertions(+), 30 deletions(-) create mode 100644 src/components/MenuPanel/MenuPanelFooter.js diff --git a/src/components/MenuPanel/MenuPanel.js b/src/components/MenuPanel/MenuPanel.js index 504a17224..e37ba1c5f 100644 --- a/src/components/MenuPanel/MenuPanel.js +++ b/src/components/MenuPanel/MenuPanel.js @@ -2,9 +2,9 @@ import React from 'react' import PropTypes from 'prop-types' import styled from 'styled-components' import { Transition, Spring, animated } from 'react-spring' +import throttle from 'lodash.throttle' import { ButtonBase, - Text, Viewport, breakpoint, springs, @@ -14,6 +14,7 @@ import { import memoize from 'lodash.memoize' import { AppType, AppsStatusType, DaoAddressType } from '../../prop-types' import { staticApps } from '../../static-apps' +import MenuPanelFooter from './MenuPanelFooter' import MenuPanelAppGroup from './MenuPanelAppGroup' import MenuPanelAppsLoader from './MenuPanelAppsLoader' import NotificationAlert from '../Notifications/NotificationAlert' @@ -66,21 +67,51 @@ class MenuPanel extends React.PureComponent { connected: PropTypes.bool.isRequired, daoAddress: DaoAddressType.isRequired, notifications: PropTypes.number, - onOpenApp: PropTypes.func.isRequired, onNotificationClicked: PropTypes.func.isRequired, + onOpenApp: PropTypes.func.isRequired, onRequestAppsReload: PropTypes.func.isRequired, + viewportHeight: PropTypes.number, } + _animateTimer = -1 + _contentRef = React.createRef() + _innerContentRef = React.createRef() + state = { notifications: [], systemAppsOpened: systemAppsOpenedState.isOpen(), animate: false, + scrollVisible: false, } componentDidMount() { - setTimeout(() => this.setState({ animate: true }), 0) + this._animateTimer = setTimeout(() => this.setState({ animate: true }), 0) + } + componentWillUnmount() { + clearTimeout(this._animateTimer) + } + componentDidUpdate(prevProps) { + if (prevProps.viewportHeight !== this.props.viewportHeight) { + this.updateScrollVisible() + } } + // ResizeObserver is still not supported everywhere, so… this method checks + // if the height of the content is higher than the height of the container, + // which means that there is a scrollbar displayed. + // It is called in two cases: when the viewport’s height changes, and when + // the system menu open / close transition is running. + updateScrollVisible = throttle(() => { + const content = this._contentRef.current + const innerContent = this._innerContentRef.current + this.setState({ + scrollVisible: + content && + innerContent && + innerContent.clientHeight > content.clientHeight, + }) + }, 100) + getAppGroups = memoize(apps => prepareAppGroups(apps)) handleToggleSystemApps = () => { @@ -100,7 +131,7 @@ class MenuPanel extends React.PureComponent { onNotificationClicked, notifications, } = this.props - const { animate, systemAppsOpened } = this.state + const { animate, scrollVisible, systemAppsOpened } = this.state const appGroups = this.getAppGroups(apps) const menuApps = [APP_HOME, appGroups] @@ -122,8 +153,8 @@ class MenuPanel extends React.PureComponent { onClick={onNotificationClicked} /> - -
+ +

Apps

@@ -164,6 +195,7 @@ class MenuPanel extends React.PureComponent { enter={{ height: 'auto' }} leave={{ height: 0 }} immediate={!animate} + onFrame={this.updateScrollVisible} native > {show => @@ -177,12 +209,16 @@ class MenuPanel extends React.PureComponent {
- - - - {connected ? 'Connected to the network' : 'Not connected'} - - + {scrollVisible && ( +
+ )} + ) @@ -299,17 +335,24 @@ class AnimatedMenuPanel extends React.Component { ) ` ), - opacity: progress.interpolate(v => (v > 0 ? 1 : 0)), + opacity: progress.interpolate(v => Number(v > 0)), }} > - + + {({ height }) => ( + + )} + )} {({ below }) => below('medium') && ( - + ) } @@ -432,19 +475,4 @@ const Content = styled.nav` } ` -const ConnectionWrapper = styled.div` - margin: 15px 20px; -` - -const ConnectionBullet = styled.span` - width: 8px; - height: 8px; - margin-top: -2px; - margin-right: 8px; - border-radius: 50%; - display: inline-block; - background: ${({ connected }) => - connected ? theme.positive : theme.negative}; -` - export default AnimatedMenuPanel diff --git a/src/components/MenuPanel/MenuPanelFooter.js b/src/components/MenuPanel/MenuPanelFooter.js new file mode 100644 index 000000000..962538913 --- /dev/null +++ b/src/components/MenuPanel/MenuPanelFooter.js @@ -0,0 +1,25 @@ +import React from 'react' +import styled from 'styled-components' +import { Text, theme } from '@aragon/ui' + +const MenuPanelFooter = ({ connected }) => ( +
+ + + {connected ? 'Connected to the network' : 'Not connected'} + +
+) + +const ConnectionBullet = styled.span` + width: 8px; + height: 8px; + margin-top: -2px; + margin-right: 8px; + border-radius: 50%; + display: inline-block; + background: ${({ connected }) => + connected ? theme.positive : theme.negative}; +` + +export default MenuPanelFooter From 47ef89d59e0d77552caf1d7d7d43ad5d94bd71a1 Mon Sep 17 00:00:00 2001 From: Pierre Bertet Date: Fri, 29 Mar 2019 16:24:15 +0100 Subject: [PATCH 2/2] ESLint fixes --- src/components/LocalIdentityModal/LocalIdentityModal.js | 9 ++++++--- src/components/MenuPanel/MenuPanel.js | 3 +-- src/components/MenuPanel/MenuPanelFooter.js | 5 +++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/components/LocalIdentityModal/LocalIdentityModal.js b/src/components/LocalIdentityModal/LocalIdentityModal.js index 38d7f3dc8..ecacabaee 100644 --- a/src/components/LocalIdentityModal/LocalIdentityModal.js +++ b/src/components/LocalIdentityModal/LocalIdentityModal.js @@ -14,9 +14,12 @@ import EscapeOutside from '../EscapeOutside/EscapeOutside' const LocalIdentityModal = ({ opened, ...props }) => { const { showModal, hideModal } = React.useContext(ModalContext) - React.useEffect(() => { - opened ? showModal(Modal, props) : hideModal() - }, [opened]) + React.useEffect( + () => { + opened ? showModal(Modal, props) : hideModal() + }, + [opened] + ) return null } diff --git a/src/components/MenuPanel/MenuPanel.js b/src/components/MenuPanel/MenuPanel.js index b0df8969a..1a1c69aac 100644 --- a/src/components/MenuPanel/MenuPanel.js +++ b/src/components/MenuPanel/MenuPanel.js @@ -69,10 +69,9 @@ class MenuPanel extends React.PureComponent { connected: PropTypes.bool.isRequired, daoAddress: DaoAddressType.isRequired, notifications: PropTypes.number, - onOpenApp: PropTypes.func.isRequired, - onOpenPreferences: PropTypes.func.isRequired, onNotificationClicked: PropTypes.func.isRequired, onOpenApp: PropTypes.func.isRequired, + onOpenPreferences: PropTypes.func.isRequired, onRequestAppsReload: PropTypes.func.isRequired, viewportHeight: PropTypes.number, } diff --git a/src/components/MenuPanel/MenuPanelFooter.js b/src/components/MenuPanel/MenuPanelFooter.js index 962538913..f7dd59ffd 100644 --- a/src/components/MenuPanel/MenuPanelFooter.js +++ b/src/components/MenuPanel/MenuPanelFooter.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import styled from 'styled-components' import { Text, theme } from '@aragon/ui' @@ -11,6 +12,10 @@ const MenuPanelFooter = ({ connected }) => (
) +MenuPanelFooter.propTypes = { + connected: PropTypes.bool, +} + const ConnectionBullet = styled.span` width: 8px; height: 8px;