diff --git a/package.json b/package.json
index 2afbfba1a..6b1a6a5be 100644
--- a/package.json
+++ b/package.json
@@ -41,9 +41,8 @@
"react-container-dimensions": "^1.3.3",
"react-display-name": "^0.2.3",
"react-dom": "^16.3.2",
- "react-motion": "^0.5.2",
"react-onclickout": "^2.0.8",
- "react-spring": "^5.4.4",
+ "react-spring": "^6.1.8",
"resolve-pathname": "^2.2.0",
"styled-components": "^3.3.3",
"underscore": "1.8.3",
diff --git a/src/apps/Permissions/Permissions.js b/src/apps/Permissions/Permissions.js
index 89c8eed80..25a8f2a0e 100644
--- a/src/apps/Permissions/Permissions.js
+++ b/src/apps/Permissions/Permissions.js
@@ -28,7 +28,9 @@ class Permissions extends React.Component {
}
componentDidMount() {
- this.setState({ animateScreens: true })
+ setTimeout(() => {
+ this.setState({ animateScreens: true })
+ }, 0)
}
componentDidUpdate(prevProps) {
@@ -215,39 +217,50 @@ class Permissions extends React.Component {
}}
/>
-
- {location.screen === 'home' && (
-
- )}
-
-
-
- {['app', 'entity'].includes(location.screen) && (
-
- {location.screen === 'app' && (
-
- )}
- {location.screen === 'entity' && (
-
- )}
-
- )}
-
+
+
+ {location.screen === 'home' && (
+
+ )}
+
+
+
+ {['app', 'entity'].includes(location.screen) && (
+
+ {location.screen === 'app' && (
+
+ )}
+ {location.screen === 'entity' && (
+
+ )}
+
+ )}
+
+
(
- `translate3d(${t * 100}%, 0, 0)`),
- }}
- >
- {children}
-
-)
-
-Main.propTypes = {
- active: PropTypes.bool.isRequired,
- children: PropTypes.node.isRequired,
- left: PropTypes.object.isRequired,
- opacity: PropTypes.object.isRequired,
-}
-
const Screen = ({ position, children, animate }) => (
- {children && (props => )}
+ {children => children && (props => )}
)
@@ -45,7 +32,24 @@ Screen.propTypes = {
position: PropTypes.number.isRequired,
}
-const StyledMain = styled(Main)`
+const Main = ({ children, opacity, left }) => (
+ `translate3d(${t}%, 0, 0)`),
+ }}
+ >
+ {children}
+
+)
+
+Main.propTypes = {
+ children: PropTypes.node.isRequired,
+ left: PropTypes.object.isRequired,
+ opacity: PropTypes.object.isRequired,
+}
+
+const StyledMain = styled(animated.div)`
overflow: hidden;
position: absolute;
top: 0;
diff --git a/src/components/App/AppLoadingProgressBar.js b/src/components/App/AppLoadingProgressBar.js
index a22a7a411..b8c391b10 100644
--- a/src/components/App/AppLoadingProgressBar.js
+++ b/src/components/App/AppLoadingProgressBar.js
@@ -1,18 +1,21 @@
import React from 'react'
import styled from 'styled-components'
import ContainerDimensions from 'react-container-dimensions'
-import { spring, Motion } from 'react-motion'
-import { theme, spring as springConf } from '@aragon/ui'
+import { Spring, animated } from 'react-spring'
+import { theme } from '@aragon/ui'
+import springs from '../../springs'
const { accent } = theme
const AppLoadingProgressBar = ({ hide, percent, ...props }) => (
-
{({ opacity, percentProgress }) => (
@@ -20,7 +23,7 @@ const AppLoadingProgressBar = ({ hide, percent, ...props }) => (
`${(width * v) / 100}px`),
}}
{...props}
>
@@ -29,11 +32,11 @@ const AppLoadingProgressBar = ({ hide, percent, ...props }) => (
)}
)}
-
+
)
// Mimic nprogress with our own accent colour
-const StyledProgressBar = styled.div`
+const StyledProgressBar = styled(animated.div)`
position: absolute;
top: 0;
height: 2px;
diff --git a/src/components/ExpandableBox/ExpandableBox.js b/src/components/ExpandableBox/ExpandableBox.js
deleted file mode 100644
index 09c1424bc..000000000
--- a/src/components/ExpandableBox/ExpandableBox.js
+++ /dev/null
@@ -1,145 +0,0 @@
-import React from 'react'
-import { spring, Motion } from 'react-motion'
-import styled from 'styled-components'
-import throttle from 'lodash.throttle'
-import { theme, spring as springConf, unselectable, Text } from '@aragon/ui'
-
-import arrow from './assets/arrow.svg'
-
-class ExpandableBox extends React.Component {
- state = {
- selfExpanded: false,
- drawerHeight: 0,
- }
- componentDidMount() {
- this.updateDrawerHeight()
- window.addEventListener('resize', this.updateDrawerHeight)
- }
- componentWillUnmount() {
- window.removeEventListener('resize', this.updateDrawerHeight)
- }
-
- // Update the drawer height in the state
- updateDrawerHeight = throttle(() => {
- const rect = this.drawerElt.getBoundingClientRect()
- this.setState({ drawerHeight: rect.height })
- }, 150)
-
- toggle = () => {
- // Externally controlled toggle
- if (this.props.onRequestToggle) {
- this.props.onRequestToggle()
- return
- }
-
- // Self controlled toggle
- this.setState({ selfExpanded: !this.state.selfExpanded })
- }
-
- render() {
- const { title, summary, summaryFooter, expanded, children } = this.props
- const { selfExpanded, drawerHeight } = this.state
- const expandedFinal = expanded === undefined ? selfExpanded : expanded
- return (
-
- {({ openProgress }) => (
-
-
- 0.1}
- style={{
- boxShadow: `
- 0 7px 10px 0 rgba(101, 148, 170, ${0.08 * openProgress})
- `,
- }}
- >
-
-
-
- {title}
-
-
- {summary}
-
- {summaryFooter && {summaryFooter}}
-
-
- (this.drawerElt = elt)}
- style={{
- marginTop: `${-drawerHeight * (1 - openProgress)}px`,
- }}
- >
- {children}
-
-
-
- )}
-
- )
- }
-}
-
-const Main = styled.section`
- position: relative;
- border: 1px solid ${theme.contentBorder};
- border-radius: 3px;
- background: ${theme.contentBackground};
- ${unselectable};
-`
-
-const Arrow = styled.img`
- position: absolute;
- top: 30px;
- right: 20px;
-`
-
-const Summary = styled.div`
- position: relative;
- z-index: 1;
- border-bottom: 1px solid
- ${({ opened }) => (opened ? theme.contentBorder : theme.contentBackground)};
-`
-
-const SummaryTopArea = styled.div`
- position: relative;
- z-index: 1;
- cursor: pointer;
- padding: 20px;
- border-bottom: 1px solid
- ${({ opened }) => (opened ? theme.contentBorder : theme.contentBackground)};
-
- h1 {
- margin-bottom: 10px;
- }
-`
-
-const SummaryFooter = styled.div`
- padding: 0 20px 20px;
-`
-
-const DrawerWrapper = styled.div`
- overflow: hidden;
- position: relative;
-`
-
-const Drawer = styled.div`
- overflow: hidden;
- position: relative;
- padding: 30px 20px;
- background: #edf3f6;
-`
-
-const DrawerContent = styled.div``
-
-export default ExpandableBox
diff --git a/src/components/Home/Home.js b/src/components/Home/Home.js
index 4586e33ac..333267f45 100644
--- a/src/components/Home/Home.js
+++ b/src/components/Home/Home.js
@@ -1,10 +1,11 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
-import { spring, Motion } from 'react-motion'
-import { theme, AppBar, Text } from '@aragon/ui'
+import { Spring, animated } from 'react-spring'
+import { theme, AppView, Text } from '@aragon/ui'
import HomeCard from './HomeCard'
import { lerp } from '../../math-utils'
+import springs from '../../springs'
import logo from './assets/logo-background.svg'
@@ -13,12 +14,10 @@ import imgFinance from './assets/finance.svg'
import imgPayment from './assets/payment.svg'
import imgVote from './assets/vote.svg'
-const CARD_WIDTH = 220
-const CARD_HEIGHT = 200
+const CARD_WIDTH = 200
+const CARD_HEIGHT = 180
const CARD_MARGIN = 30
-const SPRING = { stiffness: 120, damping: 17, precision: 0.005 }
-
const actions = [
{
id: 'assign-tokens',
@@ -87,7 +86,7 @@ class Home extends React.Component {
}
}
render() {
- const { connected, apps, locator, appsLoading } = this.props
+ const { connected, apps, locator } = this.props
const { showApps } = this.state
const appActions = actions.filter(({ appName }) =>
@@ -95,13 +94,11 @@ class Home extends React.Component {
)
return (
-
-
-
-
-
-
+
+
{({ showAppsProgress }) => (
@@ -125,27 +122,16 @@ class Home extends React.Component {
: 'You are using Aragon 0.6 — Alba'}
- {appsLoading ||
- (appActions.length > 0 && (
-
-
- {showApps
- ? 'What do you want to do?'
- : 'Loading apps…'}
-
-
- ))}
-
+
+ {showApps ? 'What do you want to do?' : 'Loading apps…'}
+
+
+
@@ -160,12 +146,12 @@ class Home extends React.Component {
))}
-
+
)}
-
-
-
+
+
+
@@ -181,8 +167,6 @@ const Main = styled.div`
display: flex;
height: 100%;
flex-direction: column;
- align-items: stretch;
- justify-content: stretch;
background-color: ${theme.mainBackground};
background-image: url(${logo});
@@ -190,24 +174,11 @@ const Main = styled.div`
background-repeat: no-repeat;
`
-const AppBarWrapper = styled.div`
- flex-shrink: 0;
-`
-
-const ScrollWrapper = styled.div`
- display: flex;
- flex-direction: column;
- justify-content: stretch;
- overflow-y: scroll;
+const AppContent = styled.div`
flex-grow: 1;
-`
-
-const AppWrapper = styled.div`
- flex-grow: 1;
- min-height: min-content;
- display: flex;
- align-items: stretch;
- justify-content: space-between;
+ flex-shrink: 1;
+ min-height: 0;
+ height: calc(100% - 54px);
`
const AppFooter = styled.div`
@@ -220,24 +191,16 @@ const AppFooter = styled.div`
border-top: 1px solid ${theme.contentBorder};
`
-const ConnectionBullet = styled.span`
- width: 8px;
- height: 8px;
- margin-top: -2px;
- margin-right: 8px;
- border-radius: 50%;
- background: ${({ connected }) =>
- connected ? theme.positive : theme.negative};
-`
-
const Content = styled.div`
display: flex;
+ width: 100%;
+ flex-grow: 1;
flex-direction: column;
justify-content: center;
align-items: center;
- width: 100%;
+ padding-top: 40px;
+ padding-bottom: 40px;
text-align: center;
- padding: 40px;
`
const Title = styled.h1`
@@ -257,8 +220,18 @@ const CardWrap = styled.div`
flex-grow: 0;
width: ${CARD_WIDTH}px;
height: ${CARD_HEIGHT}px;
- margin-bottom: ${CARD_MARGIN}px;
+ margin-top: ${CARD_MARGIN}px;
margin-left: ${CARD_MARGIN}px;
`
+const ConnectionBullet = styled.span`
+ width: 8px;
+ height: 8px;
+ margin-top: -2px;
+ margin-right: 8px;
+ border-radius: 50%;
+ background: ${({ connected }) =>
+ connected ? theme.positive : theme.negative};
+`
+
export default Home
diff --git a/src/components/MenuPanel/MenuPanel.js b/src/components/MenuPanel/MenuPanel.js
index 4d236e9b1..ec2c20374 100644
--- a/src/components/MenuPanel/MenuPanel.js
+++ b/src/components/MenuPanel/MenuPanel.js
@@ -1,17 +1,8 @@
import React from 'react'
import PropTypes from 'prop-types'
-// import { spring, Motion } from 'react-motion'
import styled from 'styled-components'
-import {
- theme,
- unselectable,
- // spring as springConf,
- // IconWallet,
- // IconNotifications,
-} from '@aragon/ui'
-// import ClickOutHandler from 'react-onclickout'
-// import NotificationsPanel from '../NotificationsPanel/NotificationsPanel'
-// import { lerp } from '../../math-utils'
+import { theme, unselectable } from '@aragon/ui'
+import memoize from 'lodash.memoize'
import { appIconUrl } from '../../utils'
import { staticApps } from '../../static-apps'
import MenuPanelAppGroup from './MenuPanelAppGroup'
@@ -70,6 +61,7 @@ class MenuPanel extends React.PureComponent {
state = {
notificationsOpened: false,
}
+
handleNotificationsClick = event => {
// Prevent clickout events to trigger
event.nativeEvent.stopImmediatePropagation()
@@ -80,16 +72,13 @@ class MenuPanel extends React.PureComponent {
handleCloseNotifications = () => {
this.setState({ notificationsOpened: false })
}
+
+ getAppGroups = memoize(apps => prepareAppGroups(apps))
+
render() {
- const {
- apps,
- // notificationsObservable,
- // onClearAllNotifications,
- // onOpenNotification,
- } = this.props
- // const { notificationsOpened } = this.state
+ const { apps } = this.props
+ const appGroups = this.getAppGroups(apps)
- const appGroups = prepareAppGroups(apps)
const menuApps = [
APP_HOME,
appGroups,
@@ -103,13 +92,6 @@ class MenuPanel extends React.PureComponent {
- {/*
-
-
-
-
-
- */}
@@ -126,38 +108,11 @@ class MenuPanel extends React.PureComponent {
-
- {/*
-
- {({ openProgress }) => (
-
-
-
- )}
-
- */}
)
}
- renderAppGroup = (app, readyToExpand) => {
+
+ renderAppGroup(app) {
const { activeInstanceId, onOpenApp } = this.props
const { appId, name, icon, instances = [] } = app
@@ -173,25 +128,39 @@ class MenuPanel extends React.PureComponent {
icon={icon}
instances={instances}
active={isActive}
- expand={isActive && readyToExpand}
+ expand={isActive}
activeInstanceId={activeInstanceId}
onActivate={onOpenApp}
/>
)
}
- renderLoadedAppGroup = apps => {
- const { appsStatus, onRequestAppsReload } = this.props
+
+ renderLoadedAppGroup(appGroups) {
+ const { appsStatus, activeInstanceId, onRequestAppsReload } = this.props
+
+ // Used by the menu transition
+ const expandedInstancesCount = appGroups.reduce(
+ (height, { instances }) =>
+ instances.length > 1 &&
+ instances.findIndex(
+ ({ instanceId }) => instanceId === activeInstanceId
+ ) > -1
+ ? height + instances.length
+ : height,
+ 0
+ )
// Wrap the DAO apps in the loader
return (
- {done => apps.map(app => this.renderAppGroup(app, done))}
+ {() => appGroups.map(app => this.renderAppGroup(app))}
)
}
@@ -220,18 +189,6 @@ const In = styled.div`
box-shadow: 1px 0 15px rgba(0, 0, 0, 0.1);
`
-// const IconButton = styled.span`
-// cursor: pointer;
-// `
-
-// const NotificationsWrapper = styled.div`
-// position: fixed;
-// z-index: 1;
-// top: 0;
-// bottom: 0;
-// left: 220px;
-// `
-
const Header = styled.div`
flex-shrink: 0;
display: flex;
diff --git a/src/components/MenuPanel/MenuPanelAppGroup.js b/src/components/MenuPanel/MenuPanelAppGroup.js
index bf98e4865..ee8880373 100644
--- a/src/components/MenuPanel/MenuPanelAppGroup.js
+++ b/src/components/MenuPanel/MenuPanelAppGroup.js
@@ -1,15 +1,16 @@
import React from 'react'
import PropTypes from 'prop-types'
-import { spring, Motion } from 'react-motion'
import styled from 'styled-components'
-import { theme, spring as springConf, IconBlank } from '@aragon/ui'
-import MenuPanelInstance from './MenuPanelInstance'
+import { Spring, animated } from 'react-spring'
+import { theme, IconBlank } from '@aragon/ui'
import color from 'onecolor'
+import MenuPanelInstance from './MenuPanelInstance'
+import springs from '../../springs'
class MenuPanelAppGroup extends React.PureComponent {
static propTypes = {
active: PropTypes.bool.isRequired,
- activeInstanceId: PropTypes.string.isRequired,
+ activeInstanceId: PropTypes.string,
expand: PropTypes.bool.isRequired,
icon: PropTypes.object.isRequired,
instances: PropTypes.array.isRequired,
@@ -40,13 +41,10 @@ class MenuPanelAppGroup extends React.PureComponent {
} = this.props
const singleInstance = instances.length === 1
return (
-
{({ openProgress }) => (
@@ -55,7 +53,9 @@ class MenuPanelAppGroup extends React.PureComponent {
`translate3d(-${(1 - v) * 100}%, 0, 0)`
+ ),
}}
/>
@@ -71,11 +71,13 @@ class MenuPanelAppGroup extends React.PureComponent {
{instances.length > 1 && (
- `${(instances.length * 30 + 5) * v}px`
+ ),
+ paddingBottom: openProgress.interpolate(v => `${5 * v}px`),
}}
>
{instances.map(({ name, instanceId, identifier }) => {
@@ -91,11 +93,11 @@ class MenuPanelAppGroup extends React.PureComponent {
) : null
})}
-
+
)}
)}
-
+
)
}
}
@@ -165,7 +167,7 @@ const ActiveBackground = styled.div`
.cssa()};
`
-const MenuItemBar = styled.div`
+const MenuItemBar = styled(animated.div)`
position: absolute;
width: 4px;
height: 100%;
diff --git a/src/components/MenuPanel/MenuPanelAppsLoader.js b/src/components/MenuPanel/MenuPanelAppsLoader.js
index a583d9157..379988bce 100644
--- a/src/components/MenuPanel/MenuPanelAppsLoader.js
+++ b/src/components/MenuPanel/MenuPanelAppsLoader.js
@@ -2,10 +2,10 @@ import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { Spring, animated } from 'react-spring'
-import { IconError, Button, theme, springs } from '@aragon/ui'
+import { IconError, Button, theme } from '@aragon/ui'
import color from 'onecolor'
-import { lerp } from '../../math-utils'
import { noop } from '../../utils'
+import springs from '../../springs'
import LoadingRing from '../LoadingRing'
import {
APPS_STATUS_ERROR,
@@ -21,54 +21,94 @@ class MenuPanelAppsLoader extends React.Component {
APPS_STATUS_LOADING,
]).isRequired,
children: PropTypes.func.isRequired,
- itemsCount: PropTypes.number.isRequired,
+ expandedInstancesCount: PropTypes.number.isRequired,
+ appsCount: PropTypes.number.isRequired,
onRetry: PropTypes.func.isRequired,
}
static defaultProps = {
children: noop,
- itemsCount: 0,
appStatus: APPS_STATUS_LOADING,
onRetry: noop,
}
state = {
showApps: false,
+ transitionDone: false,
}
componentWillReceiveProps({ appsStatus }) {
if (appsStatus !== this.props.appsStatus) {
// Always set this to false to reinitialize the animation
- this.setState({ showApps: false })
+ this.setState({ showApps: false, transitionDone: false })
}
}
handleRest = () => {
+ const { showApps } = this.state
+
if (this.props.appsStatus === APPS_STATUS_READY) {
- setTimeout(() => {
- this.setState({ showApps: true })
- }, 0)
+ this.setState({
+ // `showApps: true` triggers the transition showing the apps.
+ showApps: true,
+
+ // The second time handleRest() is called, showApps is `true`, which
+ // means that we reached the end of the transition.
+ transitionDone: showApps,
+ })
+ }
+ }
+
+ getInstancesHeight() {
+ const { appsStatus, appsCount, expandedInstancesCount } = this.props
+ const { showApps, transitionDone } = this.state
+ if (transitionDone) {
+ return -1
}
+ if (appsStatus === APPS_STATUS_READY || showApps) {
+ return (
+ appsCount * 40 +
+ expandedInstancesCount * 30 +
+ (expandedInstancesCount > 0 ? 5 : 0)
+ )
+ }
+ return appsStatus === APPS_STATUS_ERROR ? 80 : 40
}
render() {
- const { children, itemsCount, appsStatus, onRetry } = this.props
- const { showApps } = this.state
+ const { children, appsStatus, onRetry } = this.props
+ const { showApps, transitionDone } = this.state
return (
- {({ afterLoadingMessageProgress, showAppsProgress }) => (
-
+ {({
+ afterLoadingMessageProgress,
+ showAppsProgress,
+ instancesHeight,
+ }) => (
+ (v === -1 ? 'auto' : `${v}px`)
+ ),
+ }}
+ >
-
+ 1 - v),
+ transform: showAppsProgress.interpolate(
+ v => `
+ translate3d(${v * 40}px, 0, 0)
+ `
+ ),
+ }}
+ >
@@ -120,22 +169,15 @@ class MenuPanelAppsLoader extends React.Component {
- `${lerp(
- v,
- 40,
- (appsStatus === APPS_STATUS_READY ? itemsCount : 2) * 40
- )}px`
- ),
+ opacity: showAppsProgress,
transform: showAppsProgress.interpolate(
v => `
- translate3d(-${(1 - Math.min(1, v)) * 100}%, 0, 0)
+ translate3d(-${(1 - v) * 60}px, 0, 0)
`
),
}}
>
- {children(showApps)}
+ {children()}
)}
@@ -154,7 +196,7 @@ const StatusIndicatorWrapper = styled.div`
margin-right: 15px;
`
-const Main = styled.div`
+const Main = styled(animated.div)`
position: relative;
overflow: hidden;
`
@@ -193,7 +235,7 @@ const IconErrorWrapper = styled(animated.div)`
justify-content: center;
`
-const StatusContent = styled.div`
+const StatusContent = styled(animated.div)`
display: flex;
align-items: center;
position: relative;
diff --git a/src/components/ModalManager/ModalManager.js b/src/components/ModalManager/ModalManager.js
index 0011224b9..411d920e3 100644
--- a/src/components/ModalManager/ModalManager.js
+++ b/src/components/ModalManager/ModalManager.js
@@ -1,7 +1,7 @@
import React from 'react'
import styled from 'styled-components'
import { Transition, animated } from 'react-spring'
-import { springs } from '@aragon/ui'
+import springs from '../../springs'
const ModalContext = React.createContext({
modalComponent: null,
@@ -43,14 +43,15 @@ const ModalView = () => (
{({ modalComponent: ModalComponent, modalComponentProps, hideModal }) => (
- {ModalComponent &&
+ {ModalComponent =>
+ ModalComponent &&
(({ opacity, enterProgress, blocking }) => (
v * 0.5) }} />
@@ -68,7 +69,8 @@ const ModalView = () => (
- ))}
+ ))
+ }
)}
diff --git a/src/components/SignerPanel/SignerPanel.js b/src/components/SignerPanel/SignerPanel.js
index 6443ee740..11f6ffbd6 100644
--- a/src/components/SignerPanel/SignerPanel.js
+++ b/src/components/SignerPanel/SignerPanel.js
@@ -1,7 +1,7 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
-import { SidePanel, springs } from '@aragon/ui'
+import { SidePanel } from '@aragon/ui'
import { Transition, animated } from 'react-spring'
import { addressesEqual } from '../../web3-utils'
import ConfirmTransaction from './ConfirmTransaction'
@@ -14,6 +14,8 @@ import {
STATUS_ERROR,
} from './signer-statuses'
+import springs from '../../springs'
+
const INITIAL_STATE = {
panelOpened: false,
intent: {},
@@ -167,57 +169,57 @@ class SignerPanel extends React.Component {
>
- {status === STATUS_CONFIRMING
- ? ({ enterProgress, signingEnabled }) => (
- `translate3d(${-100 * (1 - v)}%, 0, 0)`
- ),
- }}
- >
-
-
-
-
- )
- : ({ enterProgress, signError }) => (
- `translate3d(${100 * (1 - v)}%, 0, 0)`
- ),
- }}
- >
-
-
-
-
- )}
+ {confirming =>
+ confirming
+ ? ({ enterProgress }) => (
+
+
+
+
+
+ )
+ : ({ enterProgress }) => (
+
+
+
+
+
+ )
+ }
diff --git a/src/onboarding/Domain.js b/src/onboarding/Domain.js
index 542edfc5e..6ff9aa4e6 100644
--- a/src/onboarding/Domain.js
+++ b/src/onboarding/Domain.js
@@ -1,7 +1,7 @@
import React from 'react'
import styled from 'styled-components'
import { theme, Text, TextInput, IconCheck, IconCross } from '@aragon/ui'
-import { lerp } from '../math-utils'
+import { animated } from 'react-spring'
import { noop } from '../utils'
import LoadingRing from '../components/LoadingRing'
@@ -14,17 +14,14 @@ import {
class Domain extends React.Component {
static defaultProps = {
- positionProgress: 0,
+ screenPosition: 0,
domain: '',
domainCheckStatus: DomainCheckNone,
onDomainChange: noop,
onSubmit: noop,
}
- componentWillReceiveProps({ positionProgress }) {
- if (
- positionProgress === 0 &&
- positionProgress !== this.props.positionProgress
- ) {
+ componentWillReceiveProps({ forceFocus }) {
+ if (forceFocus && forceFocus !== this.props.forceFocus) {
this.focusEl.focus()
}
}
@@ -33,22 +30,16 @@ class Domain extends React.Component {
}
handleSubmit = event => {
event.preventDefault()
- this.focusEl.blur()
this.props.onSubmit()
}
handleFocusElRef = el => {
this.focusEl = el
}
render() {
- const { positionProgress, domain, domainCheckStatus } = this.props
+ const { domain, domainCheckStatus, screenTransitionStyles } = this.props
return (
-
+
+
)
@@ -39,7 +31,7 @@ class LaunchContent extends React.PureComponent {
}
}
-const Main = styled.div`
+const Main = styled(animated.div)`
display: flex;
align-items: center;
justify-content: center;
diff --git a/src/onboarding/Onboarding.js b/src/onboarding/Onboarding.js
index 3bb2cb3db..a80f3067b 100644
--- a/src/onboarding/Onboarding.js
+++ b/src/onboarding/Onboarding.js
@@ -1,11 +1,11 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
-import { Motion, spring } from 'react-motion'
-import { spring as springConf } from '@aragon/ui'
+import { Spring, animated } from 'react-spring'
import { noop } from '../utils'
import { getUnknownBalance } from '../web3-utils'
import { isNameAvailable } from '../aragonjs-wrapper'
+import springs from '../springs'
import * as Steps from './steps'
import Templates from './templates'
@@ -32,18 +32,6 @@ import {
DAO_CREATION_STATUS_ERROR,
} from '../symbols'
-const SPRING_SHOW = {
- stiffness: 120,
- damping: 17,
- precision: 0.001,
-}
-const SPRING_HIDE = {
- stiffness: 70,
- damping: 15,
- precision: 0.001,
-}
-const SPRING_SCREEN = springConf('slow')
-
const initialState = {
template: null,
templateData: {},
@@ -404,29 +392,30 @@ class Onboarding extends React.PureComponent {
const step = this.currentStep()
const steps = this.getSteps()
return (
-
{({ showProgress }) => (
`translate3d(0, ${110 * (1 - v)}%, 0)`
+ ),
+ opacity: showProgress,
}}
>
{banner}
-
{({ screenProgress }) => (
@@ -436,8 +425,9 @@ class Onboarding extends React.PureComponent {
{this.renderScreen(
screen,
- i - stepIndex,
- i - screenProgress
+ i,
+ screenProgress,
+ screen === step.screen
)}
))}
@@ -453,15 +443,15 @@ class Onboarding extends React.PureComponent {
/>
)}
-
+
)}
-
+
)
}
- renderScreen(screen, position, positionProgress) {
+ renderScreen(screen, screenIndex, positionProgress, isActive) {
const {
template,
domain,
@@ -480,9 +470,23 @@ class Onboarding extends React.PureComponent {
} = this.props
// No need to move the screens farther than one step
- positionProgress = Math.min(1, Math.max(-1, positionProgress))
+ const getPositionProgress = progress =>
+ Math.min(1, Math.max(-1, screenIndex - progress))
+
+ // used by every screen
+ const screenTransitionStyles = {
+ opacity: positionProgress.interpolate(
+ v => 1 - Math.abs(getPositionProgress(v))
+ ),
+ transform: positionProgress.interpolate(
+ v => `translateX(${getPositionProgress(v) * 50}%)`
+ ),
+ }
- const sharedProps = { positionProgress }
+ const sharedProps = {
+ screenTransitionStyles,
+ forceFocus: isActive,
+ }
if (screen === 'start') {
return (
@@ -558,7 +562,7 @@ class Onboarding extends React.PureComponent {
}
}
-const Main = styled.div`
+const Main = styled(animated.div)`
position: fixed;
z-index: 2;
top: 0;
diff --git a/src/onboarding/PrevNext.js b/src/onboarding/PrevNext.js
index 59c11e804..ebc8ad752 100644
--- a/src/onboarding/PrevNext.js
+++ b/src/onboarding/PrevNext.js
@@ -1,8 +1,9 @@
import React from 'react'
import styled from 'styled-components'
-import { Motion, spring } from 'react-motion'
-import { spring as springConf, Button } from '@aragon/ui'
+import { Spring, animated } from 'react-spring'
+import { Button } from '@aragon/ui'
import { lerp } from '../math-utils'
+import springs from '../springs'
class PrevNext extends React.Component {
render() {
@@ -16,10 +17,10 @@ class PrevNext extends React.Component {
isSigningNext,
} = this.props
return (
-
{({ showProgress }) => (
`translateY(${lerp(v, 40, 0)}px)`
+ )
: 'none',
opacity: showProgress,
}}
@@ -41,7 +44,7 @@ class PrevNext extends React.Component {
/>
)}
-
+
)
}
}
@@ -69,7 +72,7 @@ class PrevNextContent extends React.PureComponent {
}
}
-const Main = styled.div`
+const Main = styled(animated.div)`
position: absolute;
left: 0;
right: 0;
diff --git a/src/onboarding/Sign.js b/src/onboarding/Sign.js
index 321944a20..63569cef0 100644
--- a/src/onboarding/Sign.js
+++ b/src/onboarding/Sign.js
@@ -1,7 +1,7 @@
import React from 'react'
import styled from 'styled-components'
import { theme, Text, Button } from '@aragon/ui'
-import { lerp } from '../math-utils'
+import { animated } from 'react-spring'
import { noop } from '../utils'
import imgPending from '../assets/transaction-pending.svg'
@@ -15,20 +15,14 @@ import {
class Sign extends React.Component {
static defaultProps = {
- positionProgress: 0,
daoCreationStatus: DAO_CREATION_STATUS_NONE,
onTryAgain: noop,
}
render() {
- const { positionProgress, daoCreationStatus, onTryAgain } = this.props
+ const { daoCreationStatus, onTryAgain, screenTransitionStyles } = this.props
return (
-
+
-
+
+
-1
return (
- 0 ? spring(stepIndex, springConf('fast')) : 0,
+ 0 ? stepIndex : 0,
}}
>
{({ showProgress, stepProgress }) => (
@@ -61,7 +62,7 @@ class ProgressBar extends React.Component {
)}
-
+
)
}
}
diff --git a/src/onboarding/Template.js b/src/onboarding/Template.js
index 1ae1bf0b2..2ec14a02f 100644
--- a/src/onboarding/Template.js
+++ b/src/onboarding/Template.js
@@ -1,28 +1,22 @@
import React from 'react'
import styled from 'styled-components'
import { theme, Text } from '@aragon/ui'
+import { animated } from 'react-spring'
import { noop } from '../utils'
-import { lerp } from '../math-utils'
import TemplateCard from './TemplateCard'
class Template extends React.Component {
static defaultProps = {
- positionProgress: 0,
onSelect: noop,
}
handleTemplateSelect = template => {
this.props.onSelect(template)
}
render() {
- const { positionProgress, templates, activeTemplate } = this.props
+ const { templates, activeTemplate, screenTransitionStyles } = this.props
return (
-
+
{
event.preventDefault()
- this.formEl.elements[0].blur()
this.props.onSubmit()
}
handleFormRef = el => {
this.formEl = el
}
render() {
- const { positionProgress, fields } = this.props
+ const { fields, screenTransitionStyles } = this.props
return (
-
+
(
)
-const Main = styled.div`
+const Main = styled(animated.div)`
display: flex;
align-items: flex-start;
justify-content: center;
diff --git a/src/onboarding/templates/democracy/ConfigureVotingDefaults.js b/src/onboarding/templates/democracy/ConfigureVotingDefaults.js
index 7f745644d..7cea0da4c 100644
--- a/src/onboarding/templates/democracy/ConfigureVotingDefaults.js
+++ b/src/onboarding/templates/democracy/ConfigureVotingDefaults.js
@@ -1,12 +1,11 @@
import React from 'react'
import styled from 'styled-components'
import { Field, TextInput, Text, theme } from '@aragon/ui'
-import { lerp } from '../../../math-utils'
+import { animated } from 'react-spring'
import { noop } from '../../../utils'
class ConfigureVotingDefaults extends React.Component {
static defaultProps = {
- positionProgress: 0,
onFieldUpdate: noop,
onSubmit: noop,
fields: {},
@@ -17,11 +16,8 @@ class ConfigureVotingDefaults extends React.Component {
this.handleMinQuorumChange = this.createChangeHandler('minQuorum')
this.handleVoteDurationChange = this.createChangeHandler('voteDuration')
}
- componentWillReceiveProps({ positionProgress }) {
- if (
- positionProgress === 0 &&
- positionProgress !== this.props.positionProgress
- ) {
+ componentWillReceiveProps({ forceFocus }) {
+ if (forceFocus && forceFocus !== this.props.forceFocus) {
this.formEl.elements[0].focus()
}
}
@@ -33,21 +29,15 @@ class ConfigureVotingDefaults extends React.Component {
}
handleSubmit = event => {
event.preventDefault()
- this.formEl.elements[0].blur()
this.props.onSubmit()
}
handleFormRef = el => {
this.formEl = el
}
render() {
- const { positionProgress, fields } = this.props
+ const { fields, screenTransitionStyles } = this.props
return (
-
+
(
)
-const Main = styled.div`
+const Main = styled(animated.div)`
display: flex;
align-items: flex-start;
justify-content: center;
diff --git a/src/onboarding/templates/multisig/ConfigureMultisigAddresses.js b/src/onboarding/templates/multisig/ConfigureMultisigAddresses.js
index 2333dd2d1..c70476c3d 100644
--- a/src/onboarding/templates/multisig/ConfigureMultisigAddresses.js
+++ b/src/onboarding/templates/multisig/ConfigureMultisigAddresses.js
@@ -1,21 +1,17 @@
import React from 'react'
import styled, { css } from 'styled-components'
import { Field, Button, TextInput, Text, DropDown, theme } from '@aragon/ui'
-import { lerp } from '../../../math-utils'
+import { animated } from 'react-spring'
import { noop } from '../../../utils'
class ConfigureMultisigAddresses extends React.Component {
static defaultProps = {
- positionProgress: 0,
onFieldUpdate: noop,
onSubmit: noop,
fields: {},
}
- componentWillReceiveProps({ positionProgress }) {
- if (
- positionProgress === 0 &&
- positionProgress !== this.props.positionProgress
- ) {
+ componentWillReceiveProps({ forceFocus }) {
+ if (forceFocus && forceFocus !== this.props.forceFocus) {
this.formEl.elements[0].focus()
}
}
@@ -47,21 +43,15 @@ class ConfigureMultisigAddresses extends React.Component {
}
handleSubmit = event => {
event.preventDefault()
- this.formEl.elements[0].blur()
this.props.onSubmit()
}
handleFormRef = el => {
this.formEl = el
}
render() {
- const { positionProgress, fields } = this.props
+ const { fields, screenTransitionStyles } = this.props
return (
-
+
(
)
-const Main = styled.div`
+const Main = styled(animated.div)`
display: flex;
align-items: flex-start;
justify-content: center;
diff --git a/src/onboarding/templates/multisig/ConfigureMultisigToken.js b/src/onboarding/templates/multisig/ConfigureMultisigToken.js
index 1b4745dff..218316f3a 100644
--- a/src/onboarding/templates/multisig/ConfigureMultisigToken.js
+++ b/src/onboarding/templates/multisig/ConfigureMultisigToken.js
@@ -1,12 +1,11 @@
import React from 'react'
import styled from 'styled-components'
import { Field, TextInput, Text, theme } from '@aragon/ui'
-import { lerp } from '../../../math-utils'
+import { animated } from 'react-spring'
import { noop } from '../../../utils'
class ConfigureTokenName extends React.Component {
static defaultProps = {
- positionProgress: 0,
onFieldUpdate: noop,
onSubmit: noop,
fields: {},
@@ -16,11 +15,8 @@ class ConfigureTokenName extends React.Component {
this.handleTokenNameChange = this.createChangeHandler('tokenName')
this.handleTokenSymbolChange = this.createChangeHandler('tokenSymbol')
}
- componentWillReceiveProps({ positionProgress }) {
- if (
- positionProgress === 0 &&
- positionProgress !== this.props.positionProgress
- ) {
+ componentWillReceiveProps({ forceFocus }) {
+ if (forceFocus && forceFocus !== this.props.forceFocus) {
this.formEl.elements[0].focus()
}
}
@@ -32,21 +28,15 @@ class ConfigureTokenName extends React.Component {
}
handleSubmit = event => {
event.preventDefault()
- this.formEl.elements[0].blur()
this.props.onSubmit()
}
handleFormRef = el => {
this.formEl = el
}
render() {
- const { positionProgress, fields } = this.props
+ const { fields, screenTransitionStyles } = this.props
return (
-
+
(
)
-const Main = styled.div`
+const Main = styled(animated.div)`
display: flex;
align-items: flex-start;
justify-content: center;
diff --git a/src/springs.js b/src/springs.js
new file mode 100644
index 000000000..63c77a9b0
--- /dev/null
+++ b/src/springs.js
@@ -0,0 +1,13 @@
+// TODO: remove when upgrading to the next version of Aragon UI.
+// From https://github.com/aragon/aragon-ui/blob/ec45bb4fc5d764879d473434719bea8517ff06c1/src/utils/styles/spring.js
+
+export default {
+ // Slow spring, can be used to move large things (e.g. a side panel).
+ lazy: { mass: 1, tension: 120, friction: 20, precision: 0.01 },
+
+ // Medium speed spring, can be used to move small objects.
+ smooth: { mass: 0.7, tension: 300, friction: 25, precision: 0.01 },
+
+ // Fast speed spring, for actions that need to feel almost instant.
+ swift: { mass: 0.5, tension: 400, friction: 30, precision: 0.01 },
+}