Skip to content

Commit 4c10763

Browse files
authored
Merge pull request #6460 from cowprotocol/release/03-11-2025
Release/03 11 2025
2 parents 7b8c07e + a033304 commit 4c10763

File tree

84 files changed

+8346
-725
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+8346
-725
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ apps/cowswap-frontend/public/robots.txt
6868
CLAUDE.md
6969
.claude/
7070

71+
# Agents context files (local only)
72+
.agents/
73+
7174
# Serena project files
7275
.serena/
7376

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import { ReactNode } from 'react'
2+
3+
import { UI } from '@cowprotocol/ui'
4+
5+
import styled, { keyframes } from 'styled-components/macro'
6+
7+
const VIEWBOX_SIZE = 44
8+
const HEAD_OFFSET_X = 4
9+
const HEAD_OFFSET_Y = 10
10+
const EYE_RADIUS = 2.4
11+
12+
const eyeJump = keyframes`
13+
0%, 10% {
14+
transform: translateY(0);
15+
}
16+
20% {
17+
transform: translateY(-0.9px);
18+
}
19+
30% {
20+
transform: translateY(-1.9px);
21+
}
22+
38% {
23+
transform: translateY(-2.5px);
24+
}
25+
44% {
26+
transform: translateY(-2.7px);
27+
}
28+
52% {
29+
transform: translateY(-1.7px);
30+
}
31+
60% {
32+
transform: translateY(-0.8px);
33+
}
34+
68% {
35+
transform: translateY(0.35px);
36+
}
37+
76% {
38+
transform: translateY(-0.2px);
39+
}
40+
86% {
41+
transform: translateY(0.1px);
42+
}
43+
94%, 100% {
44+
transform: translateY(0);
45+
}
46+
`
47+
48+
const Svg = styled.svg<{ $size: number }>`
49+
width: ${({ $size }) => `${$size}px`};
50+
height: ${({ $size }) => `${$size}px`};
51+
display: block;
52+
`
53+
54+
const Background = styled.rect.attrs({ x: 0, y: 0, width: VIEWBOX_SIZE, height: VIEWBOX_SIZE, rx: 12 })<{
55+
$fill: string
56+
}>`
57+
fill: ${({ $fill }) => $fill};
58+
`
59+
60+
const Head = styled.path.attrs({ transform: `translate(${HEAD_OFFSET_X} ${HEAD_OFFSET_Y})` })<{
61+
$fill: string
62+
}>`
63+
fill: ${({ $fill }) => $fill};
64+
`
65+
66+
const Eye = styled.circle<{ $delay?: number; $fill: string }>`
67+
fill: ${({ $fill }) => $fill};
68+
animation-name: ${eyeJump};
69+
animation-duration: 1s;
70+
animation-iteration-count: infinite;
71+
animation-delay: ${({ $delay }) => `${$delay ?? 0}ms`};
72+
animation-timing-function: cubic-bezier(0.25, 0.15, 0.25, 1);
73+
transform-origin: center;
74+
transform-box: fill-box;
75+
will-change: transform;
76+
77+
@media (prefers-reduced-motion: reduce) {
78+
animation: none;
79+
}
80+
`
81+
82+
export interface CowLoadingIconProps {
83+
size?: number
84+
className?: string
85+
isDarkMode?: boolean
86+
}
87+
88+
export function CowLoadingIcon({ size = 36, className, isDarkMode = false }: CowLoadingIconProps = {}): ReactNode {
89+
const palette = isDarkMode
90+
? {
91+
background: `var(${UI.COLOR_PAPER_DARKER})`,
92+
head: `var(${UI.COLOR_TEXT})`,
93+
eyes: `var(${UI.COLOR_PAPER_DARKER})`,
94+
}
95+
: {
96+
background: `var(${UI.COLOR_BLUE_900_PRIMARY})`,
97+
head: `var(${UI.COLOR_PAPER})`,
98+
eyes: `var(${UI.COLOR_BLUE_900_PRIMARY})`,
99+
}
100+
101+
return (
102+
<Svg
103+
viewBox={`0 0 ${VIEWBOX_SIZE} ${VIEWBOX_SIZE}`}
104+
xmlns="http://www.w3.org/2000/svg"
105+
focusable="false"
106+
aria-hidden="true"
107+
className={className}
108+
$size={size}
109+
>
110+
<Background $fill={palette.background} />
111+
<Head
112+
fillRule="evenodd"
113+
clipRule="evenodd"
114+
d="M13.653 24C12.802 24.0009 11.9729 23.731 11.2854 23.2294C10.598 22.7279 10.0879 22.0206 9.829 21.21L7.11 12.666H5.44C4.58874 12.667 3.75924 12.3971 3.07158 11.8953C2.38392 11.3936 1.87377 10.686 1.615 9.875L0 4.8H6.058L2.863 0H33.137L29.942 4.8H36L34.385 9.876C34.126 10.6868 33.6158 11.3942 32.9282 11.8957C32.2405 12.3973 31.4111 12.6671 30.56 12.666H28.89L26.17 21.21C25.9111 22.0206 25.401 22.7279 24.7136 23.2294C24.0261 23.731 23.197 24.0009 22.346 24H13.653Z"
115+
$fill={palette.head}
116+
/>
117+
<Eye cx={13.756 + HEAD_OFFSET_X} cy={10.333 + HEAD_OFFSET_Y} r={EYE_RADIUS} $delay={0} $fill={palette.eyes} />
118+
<Eye cx={22.244 + HEAD_OFFSET_X} cy={10.333 + HEAD_OFFSET_Y} r={EYE_RADIUS} $delay={160} $fill={palette.eyes} />
119+
</Svg>
120+
)
121+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './CowLoadingIcon'

apps/cowswap-frontend/src/common/pure/CurrencyArrowSeparator/index.cosmos.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { CurrencyArrowSeparator, CurrencyArrowSeparatorProps } from 'common/pure
22

33
const defaultProps: CurrencyArrowSeparatorProps = {
44
isLoading: false,
5+
isDarkMode: false,
56
onSwitchTokens() {
67
//
78
},

apps/cowswap-frontend/src/common/pure/CurrencyArrowSeparator/index.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
1-
import React from 'react'
1+
import { ReactNode } from 'react'
22

3-
import loadingCowWebp from '@cowprotocol/assets/cow-swap/cow-load.webp'
43
import { isInjectedWidget } from '@cowprotocol/common-utils'
54

5+
import { CowLoadingIcon } from 'common/pure/CowLoadingIcon'
6+
67
import * as styledEl from './styled'
78

89
export interface CurrencyArrowSeparatorProps {
910
isLoading: boolean
1011
disabled?: boolean
1112
hasSeparatorLine?: boolean
1213
isCollapsed?: boolean
14+
isDarkMode?: boolean
1315
onSwitchTokens(): void
1416
}
1517

16-
// TODO: Add proper return type annotation
17-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
18-
export function CurrencyArrowSeparator(props: CurrencyArrowSeparatorProps) {
19-
const { isLoading, onSwitchTokens, isCollapsed = true, hasSeparatorLine, disabled = false } = props
18+
export function CurrencyArrowSeparator(props: CurrencyArrowSeparatorProps): ReactNode {
19+
const {
20+
isLoading,
21+
onSwitchTokens,
22+
isCollapsed = true,
23+
hasSeparatorLine,
24+
disabled = false,
25+
isDarkMode = false,
26+
} = props
2027
const isInjectedWidgetMode = isInjectedWidget()
2128

2229
return (
2330
<styledEl.Box isCollapsed={isCollapsed} hasSeparatorLine={hasSeparatorLine} disabled={disabled}>
2431
<styledEl.LoadingWrapper isLoading={isLoading} onClick={disabled ? undefined : onSwitchTokens}>
2532
{!isInjectedWidgetMode && isLoading ? (
26-
<styledEl.CowImg src={loadingCowWebp} alt="loading" />
33+
<CowLoadingIcon size={26} isDarkMode={isDarkMode} />
2734
) : (
2835
<styledEl.ArrowDownIcon disabled={disabled} />
2936
)}

apps/cowswap-frontend/src/common/pure/CurrencyArrowSeparator/styled.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ export const LoadingWrapper = styled.div<{ isLoading: boolean }>`
5656
margin: auto;
5757
5858
&:hover {
59-
transform: translateY(-2px);
59+
${({ isLoading }) =>
60+
!isLoading &&
61+
css`
62+
transform: translateY(-2px);
63+
`}
6064
}
6165
6266
${({ isLoading }) => isLoading && loadingAnimationMixin}
@@ -73,9 +77,3 @@ export const ArrowDownIcon = styled(ArrowDown)<{ disabled: boolean }>`
7377
cursor: ${({ disabled }) => (disabled ? 'inherit' : 'pointer')};
7478
color: inherit;
7579
`
76-
77-
export const CowImg = styled.img`
78-
width: 100%;
79-
border-radius: 10px;
80-
background-color: ${({ theme }) => theme.paperCustom};
81-
`

apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/styled.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ export const CurrencyInputBox = styled.div<{ isInvalid?: boolean }>`
4545
gap: 8px;
4646
}
4747
48+
${Media.upToTiny()} {
49+
grid-template-columns: repeat(1, auto);
50+
grid-template-rows: max-content;
51+
}
52+
4853
> div {
4954
display: flex;
5055
align-items: center;

0 commit comments

Comments
 (0)