Skip to content

Commit

Permalink
Visuals: Add loading proposal microinteractions (aragon#14)
Browse files Browse the repository at this point in the history
* Add loading proposal microinteractions

* Add animation on proposal enter / leave
  • Loading branch information
Evalir authored Sep 4, 2020
1 parent 01f8059 commit 8bef50b
Show file tree
Hide file tree
Showing 4 changed files with 285 additions and 231 deletions.
3 changes: 0 additions & 3 deletions src/components/MainView.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable no-unused-vars */
import React from 'react'
import { animated, useTransition } from 'react-spring'
import { GU, useTheme, useViewport } from '@aragon/ui'
Expand Down Expand Up @@ -30,7 +29,6 @@ function MainView({ children }) {
position: relative;
z-index: 1;
width: 100%;
min-height: 100vh;
background: ${theme.background};
`}
>
Expand All @@ -47,7 +45,6 @@ function MainView({ children }) {
<div
css={`
min-height: 100vh;
height: 100%;
`}
>
<Layout>{children}</Layout>
Expand Down
194 changes: 111 additions & 83 deletions src/components/ProposalsView.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState, useCallback, useMemo } from 'react'
import { useHistory } from 'react-router-dom'
import { useTransition, animated } from 'react-spring'
import styled from 'styled-components'
import { useViewport } from 'use-viewport'
import {
Expand All @@ -13,9 +14,13 @@ import {
GU,
RADIUS,
} from '@aragon/ui'

import { ConvictionBar } from './ConvictionVisuals'
import IdentityBadge from './IdentityBadge'
import { Amount } from '../screens/ProposalDetail'

import { useAppState } from '../providers/AppState'

import { ZERO_ADDR } from '../constants'

const PROPOSALS_PER_PAGE = 10
Expand All @@ -25,9 +30,21 @@ function ProposalsView({ proposals, requestToken }) {
const theme = useTheme()
const history = useHistory()
const { below } = useViewport()
const { isLoading } = useAppState()

const compactMode = below(1400)

const loadingSwapTransitions = useTransition(isLoading, null, {
config: { mass: 1, tension: 200, friction: 20 },
from: { opacity: 0, transform: `translate3d(0, ${0.5 * GU}px, 0)` },
enter: { opacity: 1, transform: `translate3d(0, 0, 0)` },
leave: {
opacity: 0,
position: 'absolute',
transform: `translate3d(0, -${0.5 * GU}px, 0)`,
},
})

const handleSelectProposal = useCallback(
id => {
history.push(`/proposal/${id}`)
Expand All @@ -51,98 +68,109 @@ function ProposalsView({ proposals, requestToken }) {
return (
<div
css={`
position: relative;
width: 100%;
`}
>
{shownProposals.map(proposal => (
<ProposalCard
key={proposal.id}
background={theme.surface}
onClick={() => handleSelectProposal(proposal.id)}
focusRingRadius={RADIUS}
css={`
text-align: left;
word-wrap: break-word;
text-overflow: ellipsis;
`}
>
<div
css={`
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr;
justify-items: start;
${compactMode &&
`
{loadingSwapTransitions.map(
({ item: loading, key, props }) =>
!loading && (
<animated.div style={props} key={key}>
{shownProposals.map(proposal => (
<ProposalCard
key={proposal.id}
background={theme.surface}
onClick={() => handleSelectProposal(proposal.id)}
focusRingRadius={RADIUS}
css={`
text-align: left;
word-wrap: break-word;
text-overflow: ellipsis;
`}
>
<div
css={`
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr;
justify-items: start;
${compactMode &&
`
display: flex;
flex-direction: column;
`}
`}
>
<ProposalProperty
title="Proposal Title"
css={`
grid-column-start: 0;
margin-top: ${2 * GU}px;
`}
>
<ProposalTitleLink
handleSelectProposal={handleSelectProposal}
title={proposal.name}
id={proposal.id}
/>
</ProposalProperty>
{proposal.beneficiary === ZERO_ADDR ? (
<SignalingIndicator />
) : (
<Amount
requestedAmount={proposal.requestedAmount}
requestToken={requestToken}
hasTopSpacing={compactMode}
/>
)}
<div
css={`
display: flex;
${!compactMode && `margin-left: ${10 * GU}px;`}
`}
>
{proposal.status.toLowerCase() === 'executed' ? (
<ExecutedIndicator />
) : proposal.status.toLowerCase() !== 'cancelled' ? (
<ProposalProperty title="Submitted by">
<p
`}
>
<ProposalProperty
title="Proposal Title"
css={`
grid-column-start: 0;
margin-top: ${2 * GU}px;
`}
>
<ProposalTitleLink
handleSelectProposal={handleSelectProposal}
title={proposal.name}
id={proposal.id}
/>
</ProposalProperty>
{proposal.beneficiary === ZERO_ADDR ? (
<SignalingIndicator />
) : (
<Amount
requestedAmount={proposal.requestedAmount}
requestToken={requestToken}
hasTopSpacing={compactMode}
/>
)}
<div
css={`
display: flex;
${!compactMode && `margin-left: ${10 * GU}px;`}
`}
>
{proposal.status.toLowerCase() === 'executed' ? (
<ExecutedIndicator />
) : proposal.status.toLowerCase() !== 'cancelled' ? (
<ProposalProperty title="Submitted by">
<p
css={`
${textStyle('body2')}
`}
>
<IdentityBadge
entity={proposal.creator}
badgeOnly
/>
</p>
</ProposalProperty>
) : (
<CancelledIndicator />
)}
</div>
</div>
<h2
css={`
${textStyle('body2')}
${textStyle('body4')}
text-transform: uppercase;
color: ${theme.contentSecondary};
margin-top: ${4 * GU}px;
margin-bottom: ${1 * GU}px;
`}
>
<IdentityBadge entity={proposal.creator} badgeOnly />
</p>
</ProposalProperty>
) : (
<CancelledIndicator />
)}
</div>
</div>
<h2
css={`
${textStyle('body4')}
text-transform: uppercase;
color: ${theme.contentSecondary};
margin-top: ${4 * GU}px;
margin-bottom: ${1 * GU}px;
`}
>
Conviction Progress
</h2>
<ConvictionBar
hideSeparator={proposal.beneficiary === ZERO_ADDR}
proposal={proposal}
withThreshold={proposal.status !== 'Cancelled'}
/>
</ProposalCard>
))}
Conviction Progress
</h2>
<ConvictionBar
hideSeparator={proposal.beneficiary === ZERO_ADDR}
proposal={proposal}
withThreshold={proposal.status !== 'Cancelled'}
/>
</ProposalCard>
))}
</animated.div>
)
)}
<Pagination pages={pages} selected={page} onChange={setPage} />
</div>
)
Expand Down
3 changes: 1 addition & 2 deletions src/components/ScrollTop.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ export default function ScrollToTop() {
const { pathname } = useLocation()

useEffect(() => {
document.querySelector('body').scrollY = 0
window.scrollY = 0
window.scrollTo(0, 0)
}, [pathname])

return null
Expand Down
Loading

0 comments on commit 8bef50b

Please sign in to comment.