Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Menu panel footer separator #666

Merged
merged 3 commits into from
Mar 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/components/LocalIdentityModal/LocalIdentityModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
94 changes: 58 additions & 36 deletions src/components/MenuPanel/MenuPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ 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,
Button,
IconSettings,
Text,
Viewport,
breakpoint,
springs,
Expand All @@ -16,6 +16,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'
Expand Down Expand Up @@ -68,22 +69,52 @@ class MenuPanel extends React.PureComponent {
connected: PropTypes.bool.isRequired,
daoAddress: DaoAddressType.isRequired,
notifications: PropTypes.number,
onNotificationClicked: PropTypes.func.isRequired,
onOpenApp: PropTypes.func.isRequired,
onOpenPreferences: PropTypes.func.isRequired,
onNotificationClicked: 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)
Copy link
Contributor

@AquiGorka AquiGorka Mar 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've been doing this often, maybe we need to send a PR to react-spring with a new don't_animate_on_first_render_prop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just adding the clearTimeout() because it was missing, but I think there are ways to achieve what we want without using setTimeout already. I’ll investigate 🕵️‍♂️

}
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 = () => {
Expand All @@ -104,7 +135,7 @@ class MenuPanel extends React.PureComponent {
onOpenPreferences,
notifications,
} = this.props
const { animate, systemAppsOpened } = this.state
const { animate, scrollVisible, systemAppsOpened } = this.state
const appGroups = this.getAppGroups(apps)

const menuApps = [APP_HOME, appGroups]
Expand All @@ -126,14 +157,8 @@ class MenuPanel extends React.PureComponent {
onClick={onNotificationClicked}
/>
</Header>
<Content>
<div
className="in"
css={`
overflow-y: auto;
height: 100%;
`}
>
<Content ref={this._contentRef}>
<div className="in" ref={this._innerContentRef}>
<h1>Apps</h1>

<div>
Expand Down Expand Up @@ -173,6 +198,7 @@ class MenuPanel extends React.PureComponent {
enter={{ height: 'auto' }}
leave={{ height: 0 }}
immediate={!animate}
onFrame={this.updateScrollVisible}
native
>
{show =>
Expand All @@ -186,12 +212,16 @@ class MenuPanel extends React.PureComponent {
</Transition>
</div>
</Content>
<ConnectionWrapper>
<ConnectionBullet connected={connected} />
<Text size="xsmall">
{connected ? 'Connected to the network' : 'Not connected'}
</Text>
</ConnectionWrapper>
{scrollVisible && (
<div
css={`
width: 100%;
height: 1px;
background: ${theme.contentBorder};
`}
/>
)}
<MenuPanelFooter connected={connected} />
<PreferencesWrap>
<StyledPreferencesButton
size="small"
Expand Down Expand Up @@ -318,17 +348,24 @@ class AnimatedMenuPanel extends React.Component {
)
`
),
opacity: progress.interpolate(v => (v > 0 ? 1 : 0)),
opacity: progress.interpolate(v => Number(v > 0)),
}}
>
<MenuPanel {...props} />
<Viewport>
{({ height }) => (
<MenuPanel viewportHeight={height} {...props} />
)}
</Viewport>
</Wrap>
)}
</Spring>
<Viewport>
{({ below }) =>
below('medium') && (
<Overlay opened={!!openProgress} onClick={onCloseMenuPanel} />
<Overlay
opened={Boolean(openProgress)}
onClick={onCloseMenuPanel}
/>
)
}
</Viewport>
Expand Down Expand Up @@ -475,19 +512,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
30 changes: 30 additions & 0 deletions src/components/MenuPanel/MenuPanelFooter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { Text, theme } from '@aragon/ui'

const MenuPanelFooter = ({ connected }) => (
<div css="margin: 15px 20px;">
<ConnectionBullet connected={connected} />
<Text size="xsmall">
{connected ? 'Connected to the network' : 'Not connected'}
</Text>
</div>
)

MenuPanelFooter.propTypes = {
connected: PropTypes.bool,
}

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