diff --git a/apps/cowswap-frontend/public/halloween.css b/apps/cowswap-frontend/public/halloween.css
deleted file mode 100644
index e319eae830..0000000000
--- a/apps/cowswap-frontend/public/halloween.css
+++ /dev/null
@@ -1,14 +0,0 @@
-@keyframes blinker {
- 50% {
- background: black;
- }
-
- 100% {
- background: white;
- }
-}
-
-body.lightning {
- filter: invert(1) grayscale(1);
- animation: blinker 333ms linear infinite;
-}
diff --git a/libs/assets/src/cow-swap/fortune-cookie.png b/apps/cowswap-frontend/src/assets/images/fortune-cookie.png
similarity index 100%
rename from libs/assets/src/cow-swap/fortune-cookie.png
rename to apps/cowswap-frontend/src/assets/images/fortune-cookie.png
diff --git a/apps/cowswap-frontend/src/assets/images/fortuneCookieHalloween.svg b/apps/cowswap-frontend/src/assets/images/fortuneCookieHalloween.svg
new file mode 100644
index 0000000000..7a628d55b1
--- /dev/null
+++ b/apps/cowswap-frontend/src/assets/images/fortuneCookieHalloween.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/cowswap-frontend/src/common/constants/theme.ts b/apps/cowswap-frontend/src/common/constants/theme.ts
index 47cfd98680..e1e22b85ce 100644
--- a/apps/cowswap-frontend/src/common/constants/theme.ts
+++ b/apps/cowswap-frontend/src/common/constants/theme.ts
@@ -1,3 +1,9 @@
+import fortuneCookieRegular from 'assets/images/fortune-cookie.png'
+import fortuneCookieHalloween from 'assets/images/fortuneCookieHalloween.svg'
+
+// Enable to activate halloween theme elements for dark mode
+export const HALLOWEEN_MODE = true
+
export enum UI {
// Colors
COLOR_WHITE = '--cow-color-white',
@@ -15,13 +21,13 @@ export enum UI {
COLOR_BORDER = '--cow-color-border',
COLOR_CONTAINER_BG_01 = '--cow-container-bg-01',
COLOR_CONTAINER_BG_02 = '--cow-container-bg-02',
-
+
// Misc
MODAL_BACKDROP = '--cow-modal-backdrop',
BORDER_RADIUS_NORMAL = '--cow-border-radius-normal',
PADDING_NORMAL = '--cow-padding-normal',
BOX_SHADOW_NORMAL = '--cow-box-shadow-normal',
-
+
// Icons
ICON_SIZE_NORMAL = '--cow-icon-size-normal',
ICON_SIZE_SMALL = '--cow-icon-size-small',
@@ -65,3 +71,130 @@ export enum UI {
FONT_SIZE_LARGER = '--cow-font-size-larger',
FONT_SIZE_LARGEST = '--cow-font-size-largest',
}
+
+export function cowSwapLogo(darkMode: boolean): string {
+ // Halloween version
+ const halloweenModeLogo = `
+ `
+
+ // Regular Dark mode logo
+ const darkModeLogo = `
+
+ `
+
+ // Regular Light mode logo
+ const lightModeLogo = ``
+
+ return darkMode && HALLOWEEN_MODE ? halloweenModeLogo : darkMode ? darkModeLogo : lightModeLogo
+}
+
+// Footer cows image
+export function footerImage(darkMode: boolean): string {
+ const lightModeImage = ``
+
+ const darkModeImage = `
+ `
+
+ const halloweenImage = ``
+
+ return darkMode && HALLOWEEN_MODE ? halloweenImage : darkMode ? darkModeImage : lightModeImage
+}
+
+// Fortune cookie image
+export function fortuneCookieImage(darkMode: boolean): string {
+ const lightModeImage = fortuneCookieRegular
+ const darkModeImage = fortuneCookieRegular
+ const halloweenImage = fortuneCookieHalloween
+
+ return darkMode && HALLOWEEN_MODE ? halloweenImage : darkMode ? darkModeImage : lightModeImage
+}
diff --git a/apps/cowswap-frontend/src/legacy/components/Footer/index.tsx b/apps/cowswap-frontend/src/legacy/components/Footer/index.tsx
index d3df8aa993..538f7a2b90 100644
--- a/apps/cowswap-frontend/src/legacy/components/Footer/index.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Footer/index.tsx
@@ -3,7 +3,8 @@ import styled from 'styled-components/macro'
import { Polling } from 'legacy/components/Header/Polling'
import { useIsDarkMode } from 'legacy/state/user/hooks'
-import { footerImage } from 'legacy/theme/cowSwapAssets'
+
+import { footerImage } from 'common/constants/theme'
import { Version } from '../Version'
diff --git a/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx b/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx
index 5b4efb71ec..6e6b0951b6 100644
--- a/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx
+++ b/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx
@@ -1,5 +1,6 @@
import { PropsWithChildren } from 'react'
+import SpiderRag from '@cowprotocol/assets/cow-swap/halloween-spider.svg'
import { Row, RowFixed } from '@cowprotocol/ui'
import useScrollPosition from '@react-hook/window-scroll'
@@ -9,6 +10,7 @@ import styled, { css } from 'styled-components/macro'
import { MenuFlyout, MenuSection, Content as MenuContent, MenuTitle } from 'legacy/components/MenuDropdown/styled'
+import { HALLOWEEN_MODE } from 'common/constants/theme'
import { UI } from 'common/constants/theme'
const activeClassName = 'active'
@@ -199,6 +201,27 @@ export const HeaderElement = styled(HeaderElementUni)`
export const Wrapper = styled.div<{ isMobileMenuOpen: boolean }>`
width: 100%;
+ // Halloween spider rag
+ ${({ theme }) =>
+ HALLOWEEN_MODE &&
+ theme.darkMode &&
+ css`
+ &::after {
+ content: '';
+ display: block;
+ background: url(${SpiderRag}) no-repeat center/contain;
+ height: 200px;
+ width: 200px;
+ position: fixed;
+ right: -42px;
+ top: 90px;
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ display: none;
+ content: none;
+ `};
+ }
+ `}
+
${HeaderFrame} {
padding: 16px;
display: flex;
@@ -209,7 +232,7 @@ export const Wrapper = styled.div<{ isMobileMenuOpen: boolean }>`
${
isMobileMenuOpen &&
css`
- position: absolute;
+ position: fixed;
top: 0;
z-index: 3;
@@ -373,11 +396,11 @@ export const HeaderLinks = styled(HeaderLinksMod)<{ isMobileMenuOpen: boolean }>
padding: 60px 8px;
overflow-y: scroll;
-webkit-overflow-scrolling: touch; // iOS scroll fix
- transform: translate3d(0,0,0); // iOS scroll fix
+ transform: translate3d(0,0,0); // iOS scroll fix
flex-flow: column nowrap;
justify-content: flex-start;
align-items: flex-start;
- `};
+`};
`
export const TwitterLink = styled(StyledMenuButton)`
diff --git a/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts b/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts
index 89852f3350..a1212abec9 100644
--- a/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts
+++ b/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts
@@ -19,6 +19,9 @@ export const cowTokenMiddleware: Middleware, AppState> =
const { chainId, hash } = action.payload
const transaction = store.getState().transactions[chainId][hash]
+ const { userDarkMode, matchesDarkMode } = store.getState().user
+ const isDarkMode = userDarkMode === null ? matchesDarkMode : userDarkMode
+
if (transaction.swapVCow || transaction.swapLockedGNOvCow) {
const status = transaction.receipt?.status
@@ -28,13 +31,13 @@ export const cowTokenMiddleware: Middleware, AppState> =
)
if (status === 1 && transaction.replacementType !== 'cancel') {
- cowSound = getCowSoundSuccess()
+ cowSound = getCowSoundSuccess(isDarkMode)
if (transaction.swapVCow) {
store.dispatch(setSwapVCowStatus(SwapVCowStatus.CONFIRMED))
}
} else {
- cowSound = getCowSoundError()
+ cowSound = getCowSoundError(isDarkMode)
if (transaction.swapVCow) {
store.dispatch(setSwapVCowStatus(SwapVCowStatus.INITIAL))
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts
index 76ba9c1439..f124150f29 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts
@@ -21,6 +21,7 @@ describe('soundMiddleware', () => {
orders: {
1: 'mock orders',
},
+ user: { userDarkMode: false },
} as any)
jest.clearAllMocks()
})
@@ -31,6 +32,7 @@ describe('soundMiddleware', () => {
when(actionMock.type).thenReturn('order/fullfillOrdersBatch')
when(mockStore.getState()).thenReturn({
orders: {},
+ user: { userDarkMode: false },
} as any)
soundMiddleware(instance(mockStore))(nextMock)(instance(actionMock))
@@ -114,6 +116,7 @@ describe('soundMiddleware', () => {
},
},
},
+ user: { userDarkMode: false },
} as any)
soundMiddleware(instance(mockStore))(nextMock)(instance(actionMock))
@@ -139,6 +142,7 @@ describe('soundMiddleware', () => {
},
},
},
+ user: { userDarkMode: false },
} as any)
soundMiddleware(instance(mockStore))(nextMock)(instance(actionMock))
diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts
index 23eb9683de..86c12e784c 100644
--- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts
+++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts
@@ -1,9 +1,11 @@
// On each Pending, Expired, Fulfilled order action a corresponding sound is dispatched
-import { getCowSoundError, getCowSoundSend, getCowSoundSuccess } from '@cowprotocol/common-utils'
+import { getCowSoundError, getCowSoundSend, getCowSoundSuccess, isMobile } from '@cowprotocol/common-utils'
import { isAnyOf } from '@reduxjs/toolkit'
import { AnyAction, Dispatch, Middleware, MiddlewareAPI } from 'redux'
+import { HALLOWEEN_MODE } from 'common/constants/theme'
+
import { addPopup } from '../../application/reducer'
import { AppState } from '../../index'
import { AddPendingOrderParams, BatchOrdersUpdateParams, UpdateOrderParams } from '../actions'
@@ -28,6 +30,16 @@ const isBatchCancelOrderAction = isAnyOf(OrderActions.cancelOrdersBatch)
const isFulfillOrderAction = isAnyOf(OrderActions.addPendingOrder, OrderActions.fulfillOrdersBatch)
const isAddPopup = isAnyOf(addPopup)
+function removeLightningEffect() {
+ document.body.classList.remove('lightning')
+}
+function addLightningEffect() {
+ document.body.classList.add('lightning')
+ setTimeout(() => {
+ removeLightningEffect()
+ }, 3000)
+}
+
export const soundMiddleware: Middleware, AppState> = (store) => (next) => (action) => {
const result = next(action)
@@ -47,27 +59,39 @@ export const soundMiddleware: Middleware, AppState> = (s
}
}
+ const { userDarkMode, matchesDarkMode } = store.getState().user
+ const isDarkMode = userDarkMode === null ? matchesDarkMode : userDarkMode
+
let cowSound
+ let showLighningEffect = false
+ const isHalloweenMode = HALLOWEEN_MODE && isDarkMode
+ const isHalloweenModeDesktop = HALLOWEEN_MODE && isDarkMode && !isMobile
if (isPendingOrderAction(action)) {
if (_shouldPlayPendingOrderSound(action.payload)) {
- cowSound = getCowSoundSend()
+ cowSound = getCowSoundSend(isHalloweenMode)
+ showLighningEffect = isHalloweenModeDesktop
}
} else if (isFulfillOrderAction(action)) {
- cowSound = getCowSoundSuccess()
+ cowSound = getCowSoundSuccess(isHalloweenMode)
+ showLighningEffect = isHalloweenModeDesktop
} else if (isBatchExpireOrderAction(action)) {
if (_shouldPlayExpiredOrderSound(action.payload, store)) {
- cowSound = getCowSoundError()
+ cowSound = getCowSoundError(isHalloweenMode)
}
} else if (isBatchCancelOrderAction(action)) {
- cowSound = getCowSoundError()
+ cowSound = getCowSoundError(isHalloweenMode)
} else if (isFailedTxAction(action)) {
- cowSound = getCowSoundError()
+ cowSound = getCowSoundError(isHalloweenMode)
} else if (isUpdateOrderAction(action)) {
- cowSound = _getUpdatedOrderSound(action.payload)
+ cowSound = _getUpdatedOrderSound(action.payload, isHalloweenMode)
}
if (cowSound) {
+ if (showLighningEffect) {
+ setTimeout(addLightningEffect, 300)
+ }
cowSound.play().catch((e) => {
+ removeLightningEffect()
console.error('🐮 Moooooo sound cannot be played', e)
})
}
@@ -94,10 +118,10 @@ function _shouldPlayExpiredOrderSound(
})
}
-function _getUpdatedOrderSound(payload: UpdateOrderParams) {
+function _getUpdatedOrderSound(payload: UpdateOrderParams, isHalloweenMode: boolean) {
if (!payload.order.isHidden) {
// Trigger COW sound when an order is being updated to a non-hidden state
- return getCowSoundSend()
+ return getCowSoundSend(isHalloweenMode)
}
return undefined
}
diff --git a/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx b/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx
index d4a328ff5a..89da465006 100644
--- a/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx
+++ b/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx
@@ -6,7 +6,6 @@ import { useWalletInfo } from '@cowprotocol/wallet'
import { Currency, Percent, Token } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
-import { shallowEqual } from 'react-redux'
import {
addSerializedToken,
@@ -38,15 +37,16 @@ export function deserializeToken(serializedToken: SerializedToken): Token {
}
export function useIsDarkMode(): boolean {
- const { userDarkMode, matchesDarkMode } = useAppSelector(
- ({ user: { matchesDarkMode, userDarkMode } }) => ({
- userDarkMode,
- matchesDarkMode,
- }),
- shallowEqual
- )
-
- return userDarkMode === null ? matchesDarkMode : userDarkMode
+ return true
+ // const { userDarkMode, matchesDarkMode } = useAppSelector(
+ // ({ user: { matchesDarkMode, userDarkMode } }) => ({
+ // userDarkMode,
+ // matchesDarkMode,
+ // }),
+ // shallowEqual
+ // )
+
+ // return userDarkMode === null ? matchesDarkMode : userDarkMode
}
export function useDarkModeManager(): [boolean, () => void] {
diff --git a/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx b/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx
index d65e3b7ea4..e7433313db 100644
--- a/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx
+++ b/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx
@@ -11,6 +11,7 @@ import { colorsUniswap } from 'legacy/theme/colorsUniswap'
import { Colors } from 'legacy/theme/styled'
import { UI } from 'common/constants/theme'
+import { HALLOWEEN_MODE } from 'common/constants/theme'
// TODO: This shouldn't be in the base theme
// Modal override items
@@ -544,4 +545,25 @@ export const ThemedGlobalStyle = createGlobalStyle`
}
}
+ // Halloween theme elements
+ ${
+ HALLOWEEN_MODE &&
+ css`
+ @keyframes blinker {
+ 50% {
+ background: black;
+ }
+
+ 100% {
+ background: white;
+ }
+ }
+
+ body.lightning {
+ filter: invert(1) grayscale(1);
+ animation: blinker 333ms linear infinite;
+ }
+ `
+ }
+ // ========================
`
diff --git a/apps/cowswap-frontend/src/legacy/theme/cowSwapAssets.ts b/apps/cowswap-frontend/src/legacy/theme/cowSwapAssets.ts
index 1997b9dce5..1d8946d201 100644
--- a/apps/cowswap-frontend/src/legacy/theme/cowSwapAssets.ts
+++ b/apps/cowswap-frontend/src/legacy/theme/cowSwapAssets.ts
@@ -1,7 +1,12 @@
+import FORTUNE_COOKIE_IMAGE_REGULAR from 'assets/images/fortune-cookie.png'
+import FORTUNE_COOKIE_IMAGE_HALLOWEEN from 'assets/images/fortuneCookieHalloween.svg'
+
+import { HALLOWEEN_MODE } from 'common/constants/theme'
+
export function cowSwapLogo(darkMode: boolean): string {
// Halloween version
- // const darkModeLogo = `
- // `
+ const halloweenModeLogo = `
+ `
// Regular Dark mode logo
const darkModeLogo = `
@@ -11,13 +16,12 @@ export function cowSwapLogo(darkMode: boolean): string {
// Regular Light mode logo
const lightModeLogo = ``
- return darkMode ? darkModeLogo : lightModeLogo
+ return darkMode && HALLOWEEN_MODE ? halloweenModeLogo : darkMode ? darkModeLogo : lightModeLogo
}
// Footer cows image
export function footerImage(darkMode: boolean): string {
const lightModeImage = ``
-
const darkModeImage = `
- `
+ `
+ const halloweenImage = ``
+
+ return darkMode && HALLOWEEN_MODE ? halloweenImage : darkMode ? darkModeImage : lightModeImage
+}
- return darkMode ? darkModeImage : lightModeImage
+// Fortune cookie image
+export function fortuneCookieImage(darkMode: boolean): string {
+ if (darkMode && HALLOWEEN_MODE) return FORTUNE_COOKIE_IMAGE_HALLOWEEN
+ return darkMode ? FORTUNE_COOKIE_IMAGE_REGULAR : FORTUNE_COOKIE_IMAGE_REGULAR
}
diff --git a/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx b/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx
index 0210d10a47..b87bcb7959 100644
--- a/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx
+++ b/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx
@@ -3,7 +3,6 @@ import { useSetAtom } from 'jotai'
import { useCallback, useMemo, useRef, useState } from 'react'
import { openFortuneCookieAnalytics, shareFortuneTwitterAnalytics } from '@cowprotocol/analytics'
-import fortuneCookieImage from '@cowprotocol/assets/cow-swap/fortune-cookie.png'
import twitterImage from '@cowprotocol/assets/cow-swap/twitter.svg'
import { useInterval } from '@cowprotocol/common-hooks'
import { addBodyClass, removeBodyClass } from '@cowprotocol/common-utils'
@@ -24,6 +23,7 @@ import {
updateOpenFortuneAtom,
} from 'modules/fortune/state/fortuneStateAtom'
+import { fortuneCookieImage } from 'common/constants/theme'
import { UI } from 'common/constants/theme'
import { SuccessBanner } from 'pages/Claim/styled'
@@ -77,7 +77,7 @@ const FortuneButton = styled.div<{ isDailyFortuneChecked: boolean }>`
--size: 90%;
content: '';
display: block;
- background: url(${fortuneCookieImage}) no-repeat center 100% / contain;
+ background: ${({ theme }) => `url(${fortuneCookieImage(theme.darkMode)}) no-repeat center 100% / contain`};
width: var(--size);
height: var(--size);
transition: transform 0.3s ease-in-out;
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx
index a416b9bbb4..1e76af9b36 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx
@@ -2,6 +2,7 @@ import { useAtom, useAtomValue, useSetAtom } from 'jotai'
import React, { useMemo } from 'react'
import { OrderKind } from '@cowprotocol/cow-sdk'
+import { Layer3Banner } from '@cowprotocol/ui'
import { Field } from 'legacy/state/types'
@@ -15,6 +16,7 @@ import { BulletListItem, UnlockWidgetScreen } from 'modules/trade/pure/UnlockWid
import { TradeFormValidation, useGetTradeFormValidation } from 'modules/tradeFormValidation'
import { useSetTradeQuoteParams, useTradeQuote } from 'modules/tradeQuote'
+import { FeatureGuard } from 'common/containers/FeatureGuard'
import { useRateInfoParams } from 'common/hooks/useRateInfoParams'
import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types'
@@ -256,6 +258,9 @@ const LimitOrders = React.memo((props: LimitOrdersProps) => {
inputCurrencyInfo={inputCurrencyInfo}
outputCurrencyInfo={outputCurrencyInfo}
/>
+
+
+
{tradeContext && (
+
+
+
+
>
diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts
index 72eb4716fb..a7f0e59583 100644
--- a/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts
+++ b/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts
@@ -12,6 +12,7 @@ import { Nullish } from 'types'
import { cowSwapStore } from 'legacy/state'
import { dispatchPresignedOrderPosted } from 'legacy/state/orders/middleware/updateOrderPopup'
+import { useIsDarkMode } from 'legacy/state/user/hooks'
import { getOrderSubmitSummary } from 'legacy/utils/trade'
import { updateAdvancedOrdersAtom, useAdvancedOrdersDerivedState } from 'modules/advancedOrders'
@@ -55,6 +56,8 @@ export function useCreateTwapOrder() {
const { priceImpact } = useTradePriceImpact()
const { confirmPriceImpactWithoutFee } = useConfirmPriceImpactWithoutFee()
+ const darkMode = useIsDarkMode()
+
return useCallback(
async (fallbackHandlerIsNotSet: boolean) => {
if (!chainId || !account) return
@@ -123,7 +126,7 @@ export function useCreateTwapOrder() {
outputAmount: twapOrder.buyAmount,
feeAmount: undefined,
})
- getCowSoundSend().play()
+ getCowSoundSend(darkMode).play()
dispatchPresignedOrderPosted(cowSwapStore, safeTxHash, summary, OrderClass.LIMIT, 'composable-order')
uploadAppData({ chainId, orderId, appData: appDataInfo })
@@ -156,6 +159,7 @@ export function useCreateTwapOrder() {
addTwapOrderToList,
recipient,
updateAdvancedOrdersState,
+ darkMode,
]
)
}
diff --git a/libs/assets/src/cow-swap/halloween-spider.svg b/libs/assets/src/cow-swap/halloween-spider.svg
index d4754a21a2..d84e2a0aab 100644
--- a/libs/assets/src/cow-swap/halloween-spider.svg
+++ b/libs/assets/src/cow-swap/halloween-spider.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/libs/common-utils/src/sound.ts b/libs/common-utils/src/sound.ts
index a73d2607b5..c527b14572 100644
--- a/libs/common-utils/src/sound.ts
+++ b/libs/common-utils/src/sound.ts
@@ -1,6 +1,13 @@
type SoundType = 'SEND' | 'SUCCESS' | 'SUCCESS_CLAIM' | 'ERROR'
type Sounds = Record
+const COW_SOUNDS_HALLOWEEN: Sounds = {
+ SEND: '/audio/halloween.mp3',
+ SUCCESS: '/audio/halloween.mp3',
+ SUCCESS_CLAIM: '/audio/success-claim.mp3',
+ ERROR: '/audio/error.mp3',
+}
+
const COW_SOUNDS: Sounds = {
SEND: '/audio/send.mp3',
SUCCESS: '/audio/success.mp3',
@@ -10,8 +17,8 @@ const COW_SOUNDS: Sounds = {
const SOUND_CACHE: Record = {}
-function getAudio(type: SoundType): HTMLAudioElement {
- const soundPath = COW_SOUNDS[type]
+function getAudio(useHalloween: boolean, type: SoundType): HTMLAudioElement {
+ const soundPath = useHalloween ? COW_SOUNDS_HALLOWEEN[type] : COW_SOUNDS[type]
let sound = SOUND_CACHE[soundPath]
if (!sound) {
@@ -22,18 +29,18 @@ function getAudio(type: SoundType): HTMLAudioElement {
return sound
}
-export function getCowSoundSend(): HTMLAudioElement {
- return getAudio('SEND')
+export function getCowSoundSend(useHalloween: boolean): HTMLAudioElement {
+ return getAudio(useHalloween, 'SEND')
}
-export function getCowSoundSuccess(): HTMLAudioElement {
- return getAudio('SUCCESS')
+export function getCowSoundSuccess(useHalloween: boolean): HTMLAudioElement {
+ return getAudio(useHalloween, 'SUCCESS')
}
-export function getCowSoundSuccessClaim(): HTMLAudioElement {
- return getAudio('SUCCESS_CLAIM')
+export function getCowSoundSuccessClaim(useHalloween: boolean): HTMLAudioElement {
+ return getAudio(useHalloween, 'SUCCESS_CLAIM')
}
-export function getCowSoundError(): HTMLAudioElement {
- return getAudio('ERROR')
+export function getCowSoundError(useHalloween: boolean): HTMLAudioElement {
+ return getAudio(useHalloween, 'ERROR')
}
diff --git a/libs/ui/src/index.ts b/libs/ui/src/index.ts
index f4df9da04b..b37656d5f5 100644
--- a/libs/ui/src/index.ts
+++ b/libs/ui/src/index.ts
@@ -9,4 +9,5 @@ export * from './pure/SelectDropdown'
export * from './pure/Tooltip'
export * from './pure/Popover'
export * from './pure/ExternalLink'
+export * from './pure/Layer3Banner'
export * from './enum'
diff --git a/libs/ui/src/pure/Layer3Banner/index.tsx b/libs/ui/src/pure/Layer3Banner/index.tsx
new file mode 100644
index 0000000000..a0ba00611a
--- /dev/null
+++ b/libs/ui/src/pure/Layer3Banner/index.tsx
@@ -0,0 +1,21 @@
+import { Helmet } from 'react-helmet'
+import styled from 'styled-components/macro'
+
+const Wrapper = styled.div`
+ ${({ addMargin = false }) => addMargin && 'margin: 15px 0;'}
+`
+
+export interface Layer3BannerProps {
+ addMargin?: boolean
+}
+
+export function Layer3Banner(props: Layer3BannerProps) {
+ return (
+
+
+
+
+
+
+ )
+}