Skip to content

Commit

Permalink
feat: limit UI upgrade 5 (#5285)
Browse files Browse the repository at this point in the history
* feat: meditating cow bg color

* feat: full amount on trimmed amounts

* feat: keep settings menu open

* feat: twap expiration logic display

* feat: cancelling and signing status styles

* fix: remove unused parameter

* chore: misc refactorings

---------

Co-authored-by: Leandro <[email protected]>
  • Loading branch information
fairlighteth and alfetopito authored Jan 16, 2025
1 parent 687454c commit 9bc0d37
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ export function getOrderStatusTitleAndColor(order: ParsedOrder): { title: string
if (order.isCancelling) {
return {
title: 'Cancelling...',
color: `var(${UI.COLOR_TEXT})`,
background: `var(${UI.COLOR_TEXT_OPACITY_10})`,
color: `var(${UI.COLOR_DANGER_TEXT})`,
background: `var(${UI.COLOR_DANGER_BG})`,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,31 @@ import orderPresignaturePending from '@cowprotocol/assets/cow-swap/order-presign
import { Command } from '@cowprotocol/types'

import SVG from 'react-inlinesvg'
import styled from 'styled-components/macro'
import styled, { css, keyframes } from 'styled-components/macro'

import { OrderStatus } from 'legacy/state/orders/actions'

import { ParsedOrder } from 'utils/orderUtils/parseOrder'

import { getOrderStatusTitleAndColor } from './getOrderStatusTitleAndColor'

const shimmerAnimation = keyframes`
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
`

const Wrapper = styled.div<{
color: string
background: string
withWarning?: boolean
widthAuto?: boolean
clickable?: boolean
isCancelling?: boolean
isSigning?: boolean
}>`
--height: 26px;
--statusColor: ${({ color }) => color};
Expand Down Expand Up @@ -46,6 +57,26 @@ const Wrapper = styled.div<{
z-index: 1;
border-radius: 16px;
}
${({ isCancelling, isSigning }) =>
(isCancelling || isSigning) &&
css`
overflow: hidden;
border-radius: 16px;
&::after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.3) 50%, transparent 100%);
animation: ${shimmerAnimation} 1.5s infinite;
z-index: 2;
border-radius: 16px;
}
`}
`

const StatusContent = styled.div`
Expand Down Expand Up @@ -95,6 +126,8 @@ export function OrderStatusBox({ order, widthAuto, withWarning, onClick, Warning
withWarning={withWarning}
clickable={!!onClick}
onClick={onClick}
isCancelling={order.isCancelling && !order.executionData.fullyFilled}
isSigning={order.status === OrderStatus.PRESIGNATURE_PENDING}
>
{content}
</Wrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'

import alertCircle from '@cowprotocol/assets/cow-swap/alert-circle.svg'
import { Command } from '@cowprotocol/types'
import { ButtonSecondary, TokenSymbol, UI, HoverTooltip } from '@cowprotocol/ui'
import { ButtonSecondary, HoverTooltip, TokenSymbol, UI } from '@cowprotocol/ui'

import SVG from 'react-inlinesvg'

Expand Down Expand Up @@ -104,11 +104,11 @@ export function WarningTooltip({
onApprove,
showIcon = false,
}: WarningTooltipProps) {
const withAllowanceWarning = hasEnoughAllowance === false
const withAllowanceWarning = !hasEnoughAllowance

const tooltipContent = (
<styledEl.WarningContent>
{hasEnoughBalance === false && <BalanceWarning symbol={inputTokenSymbol} isScheduled={isOrderScheduled} />}
{!hasEnoughBalance && <BalanceWarning symbol={inputTokenSymbol} isScheduled={isOrderScheduled} />}
{withAllowanceWarning && (
<AllowanceWarning approve={onApprove} symbol={inputTokenSymbol} isScheduled={isOrderScheduled} />
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'
import orderPresignaturePending from '@cowprotocol/assets/cow-swap/order-presignature-pending.svg'
import { ZERO_FRACTION } from '@cowprotocol/common-const'
import { useTimeAgo } from '@cowprotocol/common-hooks'
import { getAddress, getEtherscanLink, formatDateWithTimezone } from '@cowprotocol/common-utils'
import { formatDateWithTimezone, getAddress, getEtherscanLink } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { TokenLogo } from '@cowprotocol/tokens'
import { Command, UiOrderType } from '@cowprotocol/types'
import { Loader, TokenAmount, UI, HoverTooltip } from '@cowprotocol/ui'
import { PercentDisplay, percentIsAlmostHundred } from '@cowprotocol/ui'
import { HoverTooltip, Loader, PercentDisplay, percentIsAlmostHundred, TokenAmount, UI } from '@cowprotocol/ui'
import { useIsSafeWallet } from '@cowprotocol/wallet'
import { Currency, CurrencyAmount, Percent, Price } from '@uniswap/sdk-core'

import { Clock, Zap, Check, X } from 'react-feather'
import { Check, Clock, X, Zap } from 'react-feather'
import SVG from 'react-inlinesvg'

import { OrderStatus } from 'legacy/state/orders/actions'
Expand All @@ -21,9 +20,9 @@ import { PendingOrderPrices } from 'modules/orders/state/pendingOrdersPricesAtom
import { getIsEthFlowOrder } from 'modules/swap/containers/EthFlowStepper'

import {
PENDING_EXECUTION_THRESHOLD_PERCENTAGE,
GOOD_PRICE_THRESHOLD_PERCENTAGE,
FAIR_PRICE_THRESHOLD_PERCENTAGE,
GOOD_PRICE_THRESHOLD_PERCENTAGE,
PENDING_EXECUTION_THRESHOLD_PERCENTAGE,
} from 'common/constants/common'
import { useSafeMemo } from 'common/hooks/useSafeMemo'
import { RateInfo } from 'common/pure/RateInfo'
Expand Down Expand Up @@ -166,17 +165,19 @@ export function OrderRow({
return 'Unfillable'
}

const renderWarningTooltip = (showIcon?: boolean) => (props: { children: React.ReactNode }) => (
<WarningTooltip
hasEnoughBalance={hasEnoughBalance ?? false}
hasEnoughAllowance={hasEnoughAllowance ?? false}
inputTokenSymbol={inputTokenSymbol}
isOrderScheduled={isOrderScheduled}
onApprove={() => orderActions.approveOrderToken(order.inputToken)}
showIcon={showIcon}
{...props}
/>
)
const renderWarningTooltip =
(showIcon?: boolean) =>
({ children }: { children: React.ReactNode }) => (
<WarningTooltip
hasEnoughBalance={hasEnoughBalance ?? false}
hasEnoughAllowance={hasEnoughAllowance ?? false}
inputTokenSymbol={inputTokenSymbol}
isOrderScheduled={isOrderScheduled}
onApprove={() => orderActions.approveOrderToken(order.inputToken)}
showIcon={showIcon}
children={children}
/>
)

const renderLimitPrice = () => (
<styledEl.RateValue onClick={toggleIsInverted}>
Expand Down Expand Up @@ -435,12 +436,12 @@ export function OrderRow({
<styledEl.CellElement doubleRow>
<b
title={
expirationTime && !(getIsFinalizedOrder(order) && order.status !== OrderStatus.EXPIRED)
expirationTime && !shouldShowDashForExpiration(order)
? formatDateWithTimezone(expirationTime)
: undefined
}
>
{getIsFinalizedOrder(order) && order.status !== OrderStatus.EXPIRED ? '-' : expirationTimeAgo}
{shouldShowDashForExpiration(order) ? '-' : expirationTimeAgo}
</b>
<i title={creationTime && !isScheduledCreating ? formatDateWithTimezone(creationTime) : undefined}>
{isScheduledCreating ? 'Creating...' : creationTimeAgo}
Expand Down Expand Up @@ -585,3 +586,28 @@ function getActivityUrl(chainId: SupportedChainId, order: ParsedOrder): string |

return chainId && activityId ? getEtherscanLink(chainId, 'transaction', activityId) : undefined
}

function shouldShowDashForExpiration(order: ParsedOrder): boolean {
// Show dash for finalized orders that are not expired
if (getIsFinalizedOrder(order) && order.status !== OrderStatus.EXPIRED) {
return true
}

// For TWAP parent orders, show dash when all child orders are in a final state
if (getIsComposableCowParentOrder(order)) {
// If the parent order is fulfilled or cancelled, all child orders are finalized
if (order.status === OrderStatus.FULFILLED || order.status === OrderStatus.CANCELLED) {
return true
}

// For mixed states (some filled, some expired), check either condition:
// 1. fullyFilled: true when all non-expired parts are filled
// 2. status === EXPIRED: true when all remaining parts are expired
// Either condition indicates all child orders are in a final state
if (order.executionData.fullyFilled || order.status === OrderStatus.EXPIRED) {
return true
}
}

return false
}

0 comments on commit 9bc0d37

Please sign in to comment.