From 9bc0d371d3ff93acaa72dfcffa35922491e8f5bf Mon Sep 17 00:00:00 2001 From: fairlight <31534717+fairlighteth@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:45:49 +0000 Subject: [PATCH] feat: limit UI upgrade 5 (#5285) * 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 --- .../getOrderStatusTitleAndColor.ts | 4 +- .../ordersTable/pure/OrderStatusBox/index.tsx | 35 +++++++++- .../OrderRow/OrderWarning.tsx | 6 +- .../OrdersTableContainer/OrderRow/index.tsx | 64 +++++++++++++------ 4 files changed, 84 insertions(+), 25 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderStatusBox/getOrderStatusTitleAndColor.ts b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderStatusBox/getOrderStatusTitleAndColor.ts index 5a853d350b..1827145e21 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderStatusBox/getOrderStatusTitleAndColor.ts +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderStatusBox/getOrderStatusTitleAndColor.ts @@ -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})`, } } diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderStatusBox/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderStatusBox/index.tsx index ea2bdf0c78..87b9bb84b4 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderStatusBox/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderStatusBox/index.tsx @@ -2,7 +2,7 @@ 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' @@ -10,12 +10,23 @@ 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}; @@ -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` @@ -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} diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/OrderWarning.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/OrderWarning.tsx index d52aac3138..26ff6244c1 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/OrderWarning.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/OrderWarning.tsx @@ -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' @@ -104,11 +104,11 @@ export function WarningTooltip({ onApprove, showIcon = false, }: WarningTooltipProps) { - const withAllowanceWarning = hasEnoughAllowance === false + const withAllowanceWarning = !hasEnoughAllowance const tooltipContent = ( - {hasEnoughBalance === false && } + {!hasEnoughBalance && } {withAllowanceWarning && ( )} diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx index 2cd2fd549f..b833b3776b 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx @@ -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' @@ -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' @@ -166,17 +165,19 @@ export function OrderRow({ return 'Unfillable' } - const renderWarningTooltip = (showIcon?: boolean) => (props: { children: React.ReactNode }) => ( - orderActions.approveOrderToken(order.inputToken)} - showIcon={showIcon} - {...props} - /> - ) + const renderWarningTooltip = + (showIcon?: boolean) => + ({ children }: { children: React.ReactNode }) => ( + orderActions.approveOrderToken(order.inputToken)} + showIcon={showIcon} + children={children} + /> + ) const renderLimitPrice = () => ( @@ -435,12 +436,12 @@ export function OrderRow({ - {getIsFinalizedOrder(order) && order.status !== OrderStatus.EXPIRED ? '-' : expirationTimeAgo} + {shouldShowDashForExpiration(order) ? '-' : expirationTimeAgo} {isScheduledCreating ? 'Creating...' : creationTimeAgo} @@ -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 +}