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 = ` @@ -108,8 +112,14 @@ export function footerImage(darkMode: boolean): string { - - ` + ` + 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 ( + + + + +
+
+ ) +}