Skip to content

Commit

Permalink
feat: add confirmation step to the StatusDialog flow (Uniswap#408)
Browse files Browse the repository at this point in the history
* feat: add confirmation step to the StatusDialog flow

* fix: timing constant variable
  • Loading branch information
just-toby authored Jan 18, 2023
1 parent 81f5711 commit 8b14e27
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 22 deletions.
5 changes: 5 additions & 0 deletions src/assets/svg/large_arrow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 14 additions & 11 deletions src/components/ActionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export interface Action {
onClick?: () => void
color?: Color
children?: ReactNode
hideButton?: boolean
}

type ActionButtonColor = keyof Pick<Colors, 'accent' | 'accentSoft' | 'warningSoft' | 'interactive' | 'critical'>
Expand Down Expand Up @@ -114,17 +115,19 @@ export default function ActionButton({

return (
<Overlay data-testid="action-button" hasAction={Boolean(action)} flex align="stretch" {...wrapperProps}>
<StyledButton
color={color}
disabled={disabled}
shouldUseDisabledColor={shouldUseDisabledColor}
onClick={action?.onClick || onClick}
{...rest}
>
<ThemedText.TransitionButton buttonSize={action ? 'medium' : 'large'} color={textColor}>
{action?.children || children}
</ThemedText.TransitionButton>
</StyledButton>
{!action?.hideButton && (
<StyledButton
color={color}
disabled={disabled}
shouldUseDisabledColor={shouldUseDisabledColor}
onClick={action?.onClick || onClick}
{...rest}
>
<ThemedText.TransitionButton buttonSize={action ? 'medium' : 'large'} color={textColor}>
{action?.children || children}
</ThemedText.TransitionButton>
</StyledButton>
)}
{action && (
<ActionRow gap={0.5} color={action.color ?? 'primary'}>
{action.tooltipContent ? (
Expand Down
2 changes: 1 addition & 1 deletion src/components/Error/ErrorDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ interface StatusHeaderProps {
children: ReactNode
}

export function StatusHeader({ icon: Icon, iconColor, iconSize = 4, children }: StatusHeaderProps) {
export function StatusHeader({ icon: Icon, iconColor, iconSize = 5, children }: StatusHeaderProps) {
return (
<>
<Column flex style={{ flexGrow: 1 }}>
Expand Down
30 changes: 25 additions & 5 deletions src/components/Swap/Status/StatusDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import ErrorDialog, { StatusHeader } from 'components/Error/ErrorDialog'
import EtherscanLink from 'components/EtherscanLink'
import Row from 'components/Row'
import SwapSummary from 'components/Swap/Summary'
import { LargeCheck, LargeSpinner } from 'icons'
import { useMemo } from 'react'
import { DialogAnimationLengthMs } from 'components/Widget'
import { MS_IN_SECOND } from 'constants/misc'
import { LargeArrow, LargeCheck, LargeSpinner } from 'icons'
import { useEffect, useMemo, useState } from 'react'
import { Transaction, TransactionType } from 'state/transactions'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
Expand All @@ -28,19 +30,37 @@ interface TransactionStatusProps {
}

function TransactionStatus({ tx, onClose }: TransactionStatusProps) {
const [showConfirmation, setShowConfirmation] = useState(true)
const Icon = useMemo(() => {
if (showConfirmation) {
return LargeArrow
}
return tx.receipt?.status ? LargeCheck : LargeSpinner
}, [tx.receipt?.status])
}, [showConfirmation, tx.receipt?.status])

useEffect(() => {
// We should show the confirmation for 1 second,
// which should start after the entrance animation is complete.
const handle = setTimeout(() => {
setShowConfirmation(false)
}, MS_IN_SECOND + DialogAnimationLengthMs)
return () => {
clearTimeout(handle)
}
}, [])

const heading = useMemo(() => {
if (tx.info.type === TransactionType.SWAP) {
if (showConfirmation) {
return <Trans>Transaction submitted</Trans>
} else if (tx.info.type === TransactionType.SWAP) {
return tx.receipt?.status ? <Trans>Success</Trans> : <Trans>Swap pending</Trans>
} else if (tx.info.type === TransactionType.WRAP) {
return tx.receipt?.status ? <Trans>Success</Trans> : <Trans>Unwrap pending</Trans>
} else if (tx.info.type === TransactionType.UNWRAP) {
return tx.receipt?.status ? <Trans>Success</Trans> : <Trans>Unwrap pending</Trans>
}
return tx.receipt?.status ? <Trans>Success</Trans> : <Trans>Transaction pending</Trans>
}, [tx.info, tx.receipt?.status])
}, [showConfirmation, tx.info.type, tx.receipt?.status])

const subheading = useMemo(() => {
if (tx.receipt?.status) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/Swap/Summary/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function ConfirmButton({

const action = useMemo((): Action | undefined => {
if (isPending) {
return { message: <Trans>Confirm in your wallet</Trans>, icon: Spinner }
return { message: <Trans>Confirm in your wallet</Trans>, icon: Spinner, hideButton: true }
} else if (doesTradeDiffer) {
return {
color: 'accent',
Expand Down
4 changes: 3 additions & 1 deletion src/components/Swap/SwapActionButton/WrapButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ export default function WrapButton({ disabled }: { disabled: boolean }) {

const actionProps = useMemo(
() =>
isPending ? { action: { message: <Trans>Confirm in your wallet</Trans>, icon: Spinner } } : { onClick: onWrap },
isPending
? { action: { message: <Trans>Confirm in your wallet</Trans>, icon: Spinner, hideButton: true } }
: { onClick: onWrap },
[isPending, onWrap]
)

Expand Down
8 changes: 5 additions & 3 deletions src/components/Widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const slideOutRight = keyframes`
}
`

export const DialogAnimationLengthMs = 250

export const DialogWrapper = styled.div`
border: ${({ theme }) => `1px solid ${theme.outline}`};
Expand All @@ -52,13 +54,13 @@ export const DialogWrapper = styled.div`
}
${Modal} {
animation: ${slideInLeft} 0.25s ease-in;
animation: ${slideInLeft} ${DialogAnimationLengthMs}ms ease-in;
&.${Animation.PAGING} {
animation: ${slideOutLeft} 0.25s ease-in;
animation: ${slideOutLeft} ${DialogAnimationLengthMs}ms ease-in;
}
&.${Animation.CLOSING} {
animation: ${slideOutRight} 0.25s ease-out;
animation: ${slideOutRight} ${DialogAnimationLengthMs}ms ease-out;
}
}
`
Expand Down
2 changes: 2 additions & 0 deletions src/constants/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export const NetworkContextName = 'NETWORK'

export const IS_IN_IFRAME = window.parent !== window

export const MS_IN_SECOND = 1000

// 30 minutes, denominated in seconds
export const DEFAULT_DEADLINE_FROM_NOW = 60 * 30
export const L2_DEADLINE_FROM_NOW = 60 * 5
Expand Down
5 changes: 5 additions & 0 deletions src/icons/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ReactComponent as RouterIcon } from 'assets/svg/auto_router.svg'
import { ReactComponent as CheckIcon } from 'assets/svg/check.svg'
import { ReactComponent as ExpandoIcon } from 'assets/svg/expando.svg'
import { ReactComponent as GasIcon } from 'assets/svg/gasIcon.svg'
import { ReactComponent as LargeArrowIcon } from 'assets/svg/large_arrow.svg'
import { ReactComponent as LargeCheckIcon } from 'assets/svg/large_check.svg'
import { ReactComponent as LargeSpinnerIcon } from 'assets/svg/large_spinner.svg'
import { ReactComponent as LogoIcon } from 'assets/svg/logo.svg'
Expand Down Expand Up @@ -152,6 +153,10 @@ export const LargeSpinner = styled(icon(LargeSpinnerIcon))<{ color?: Color }>`
stroke: ${({ color = 'primary', theme }) => theme[color]};
`

export const LargeArrow = styled(icon(LargeArrowIcon))<{ color?: Color }>`
stroke: ${({ color = 'primary', theme }) => theme[color]};
`

export const Gas = styled(icon(GasIcon))<{ color?: Color }>`
fill: ${({ color = 'active', theme }) => theme[color]};
stroke: ${({ color = 'active', theme }) => theme[color]};
Expand Down

0 comments on commit 8b14e27

Please sign in to comment.