Skip to content
Permalink
Browse files

Menu panel tweaks (#684)

Borders:
- Consistent colors + use of 1px border vs. height (browser engines round these differently).

Preferences button:
- The button is now always left aligned + its inner spacing fixed.

System apps toggle:
- The arrow is now:
  - Pointing in the opposite direction (direction of the action to be taken).
  - Next to the label.
  - Vertically aligned.
  - Animated.
- The toggle button has an active state.
- Transition: it now slides down instead of being revealed.
- Other transition + cosmetic tweaks.
  • Loading branch information...
bpierre committed Apr 10, 2019
1 parent a6b9990 commit 9334b199d5a7962bfe4456aea3a31e5327a726d8
Showing with 138 additions and 92 deletions.
  1. +114 −88 src/components/MenuPanel/MenuPanel.js
  2. +24 −4 src/components/MenuPanel/MenuPanelFooter.js
@@ -1,18 +1,10 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { Transition, Spring, animated } from 'react-spring'
import { Spring, animated } from 'react-spring'
import throttle from 'lodash.throttle'
import {
ButtonBase,
Button,
IconSettings,
Viewport,
breakpoint,
springs,
theme,
unselectable,
} from '@aragon/ui'
import color from 'onecolor'
import { ButtonBase, Viewport, springs, theme, unselectable } from '@aragon/ui'
import memoize from 'lodash.memoize'
import { AppType, AppsStatusType, DaoAddressType } from '../../prop-types'
import { staticApps } from '../../static-apps'
@@ -26,6 +18,7 @@ import IconArrow from '../../icons/IconArrow'

export const SHADOW_WIDTH = 15
export const MENU_WIDTH = 220
export const MENU_ITEM_HEIGHT = 40

const APP_APPS_CENTER = staticApps.get('apps').app
const APP_HOME = staticApps.get('home').app
@@ -63,6 +56,11 @@ const prepareAppGroups = apps =>
])
}, [])

// Interpolate the elevation of a toggle from which a drawer slides down.
// In / out example: [0, 0.25, 0.5, 0.75, 1] => [0, 0.5, 1, 0.5, 0]
const interpolateToggleElevation = (value, fn = v => v) =>
value.interpolate(v => fn(1 - Math.abs(v * 2 - 1)))

class MenuPanel extends React.PureComponent {
static propTypes = {
activeInstanceId: PropTypes.string,
@@ -171,69 +169,79 @@ class MenuPanel extends React.PureComponent {
: this.renderAppGroup(app, false)
)}
</div>
<SystemAppsToggle onClick={this.handleToggleSystemApps}>
<h1
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'flex-end',
}}
>
<span>System</span>
<span
css={`
transform: rotate(${systemAppsOpened ? 180 : 0}deg);
position: relative;
top: ${systemAppsOpened ? -5 : 0}px;
font-size: 7px;
opacity: 0.7;
`}
>
<IconArrow />
</span>
</h1>
</SystemAppsToggle>
<Transition
items={systemAppsOpened}
config={springs.swift}
from={{ height: 0 }}
enter={{ height: 'auto' }}
leave={{ height: 0 }}
<Spring
config={springs.smooth}
from={{ openProgress: 0 }}
to={{ openProgress: Number(systemAppsOpened) }}
immediate={!animate}
onFrame={this.updateScrollVisible}
native
>
{show =>
show &&
(props => (
<animated.div style={{ ...props, overflow: 'hidden' }}>
{systemApps.map(app => this.renderAppGroup(app, true))}
</animated.div>
))
}
</Transition>
{({ openProgress }) => (
<div>
<SystemAppsToggle onClick={this.handleToggleSystemApps}>
<SystemAppsToggleShadow
style={{
transform: interpolateToggleElevation(
openProgress,
v => `scale3d(${v}, 1, 1)`
),
opacity: interpolateToggleElevation(openProgress),
}}
/>
<h1
css={`
display: flex;
justify-content: flex-start;
align-items: flex-end;
`}
>
<span>System</span>
<SystemAppsToggleArrow
style={{
marginLeft: '5px',
transform: openProgress.interpolate(
v => `rotate(${(1 - v) * 180}deg)`
),
transformOrigin: '50% calc(50% - 0.5px)',
}}
/>
</h1>
</SystemAppsToggle>
<div css="overflow: hidden">
<animated.div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-end',
width: '100%',
opacity: openProgress,
height: openProgress.interpolate(
v => v * systemApps.length * MENU_ITEM_HEIGHT + 'px'
),
}}
>
{systemApps.map(app => this.renderAppGroup(app, true))}
</animated.div>
</div>
</div>
)}
</Spring>
</div>
</Content>
{scrollVisible && (
<div
css={`
width: 100%;
height: 1px;
background: ${theme.contentBorder};
height: 0;
border-bottom: 1px solid ${theme.contentBorder};
`}
/>
)}
<MenuPanelFooter connected={connected} />
<PreferencesWrap>
<StyledPreferencesButton
size="small"
mode="outline"
label="Preferences"
onClick={onOpenPreferences}
>
<IconSettings /> Preferences
</StyledPreferencesButton>
</PreferencesWrap>
<MenuPanelFooter
connected={connected}
onOpenPreferences={onOpenPreferences}
/>
</In>
</Main>
)
@@ -395,40 +403,58 @@ AnimatedMenuPanel.propTypes = {
}

const SystemAppsToggle = styled(ButtonBase)`
position: relative;
width: 100%;
padding: 0;
margin: 0;
margin-top: 20px;
margin: 20px 0 0;
background: none;
border: none;
cursor: pointer;
width: 100%;
text-align: left;
outline: none;
&:active {
background: ${color(theme.secondaryBackground)
.alpha(0.3)
.cssa()};
}
`

const PreferencesWrap = styled.div`
text-align: left;
${breakpoint(
'medium',
`
text-align: center;
`
)}
`

const StyledPreferencesButton = styled(Button)`
display: inline-flex;
margin: 0 16px 16px 16px;
align-items: center;
${breakpoint(
'medium',
`
margin: 0 0 16px 0;
`
)}
`
const SystemAppsToggleArrow = props => (
<animated.div {...props}>
<div
css={`
display: flex;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
`}
>
<IconArrow />
</div>
</animated.div>
)

const SystemAppsToggleShadow = props => (
<div
css={`
position: absolute;
left: 20px;
right: 20px;
bottom: 0;
`}
>
<animated.div {...props}>
<div
css={`
height: 1px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
`}
/>
</animated.div>
</div>
)

const Overlay = styled(animated.div)`
position: absolute;
@@ -461,7 +487,7 @@ const In = styled.div`
height: 100%;
flex-shrink: 1;
background: #fff;
border-right: 1px solid #e8e8e8;
border-right: 1px solid ${theme.contentBorder};
box-shadow: 1px 0 ${SHADOW_WIDTH}px rgba(0, 0, 0, 0.1);
`

@@ -472,7 +498,7 @@ const Header = styled.div`
align-items: center;
padding: 0 20px;
height: 64px;
border-bottom: 1px solid #e8e8e8;
border-bottom: 1px solid ${theme.contentBorder};
.actions {
display: flex;
@@ -1,19 +1,39 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { Text, theme } from '@aragon/ui'
import { Button, IconSettings, Text, theme } from '@aragon/ui'

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

MenuPanelFooter.propTypes = {
connected: PropTypes.bool,
onOpenPreferences: PropTypes.func.isRequired,
}

const PreferencesButton = ({ onClick }) => (
<div css="margin-top: 12px">
<Button size="small" mode="outline" label="Preferences" onClick={onClick}>
<span
css={`
display: flex;
align-items: center;
`}
>
<IconSettings css="margin: 0 6px 0 -3px" />
<span>Preferences</span>
</span>
</Button>
</div>
)
PreferencesButton.propTypes = {
onClick: PropTypes.func.isRequired,
}

const ConnectionBullet = styled.span`

0 comments on commit 9334b19

Please sign in to comment.
You can’t perform that action at this time.