Skip to content

Commit

Permalink
feat: add winter theme 🎅 (#5213)
Browse files Browse the repository at this point in the history
* feat: add winter theme

* feat: restore inline comment

* feat: show improved christmas success sound

* chore: improve handling of feature flags

* chore: remove unnecessary casting

* chore: refactor detection of christmas theme

* fix: fix lint

---------

Co-authored-by: Anxo Rodriguez <[email protected]>
  • Loading branch information
fairlighteth and anxolin authored Dec 17, 2024
1 parent 8be3a45 commit 7db4b72
Show file tree
Hide file tree
Showing 17 changed files with 137 additions and 58 deletions.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { ACTIVE_CUSTOM_THEME, CustomTheme } from '@cowprotocol/common-const'
import { useMediaQuery } from '@cowprotocol/common-hooks'
import { useFeatureFlags } from '@cowprotocol/common-hooks'
import { isInjectedWidget } from '@cowprotocol/common-utils'
import { Color, Footer, GlobalCoWDAOStyles, Media, MenuBar, CowSwapTheme } from '@cowprotocol/ui'
import { Color, Footer, GlobalCoWDAOStyles, Media, MenuBar } from '@cowprotocol/ui'

import SVG from 'react-inlinesvg'
import { NavLink } from 'react-router-dom'
import Snowfall from 'react-snowfall'
import { ThemeProvider } from 'theme'

import ErrorBoundary from 'legacy/components/ErrorBoundary'
Expand Down Expand Up @@ -53,8 +54,7 @@ export function App() {
useAnalyticsReporterCowSwap()
useInitializeUtm()

const featureFlags = useFeatureFlags()
const { isYieldEnabled } = featureFlags
const { isYieldEnabled, isChristmasEnabled, isHalloweenEnabled } = useFeatureFlags()

const isInjectedWidgetMode = isInjectedWidget()
const menuItems = useMenuItems()
Expand Down Expand Up @@ -97,11 +97,14 @@ export function App() {
const { pendingActivity } = useCategorizeRecentActivity()
const isMobile = useMediaQuery(Media.upToMedium(false))
const customTheme = useMemo(() => {
if (ACTIVE_CUSTOM_THEME === CustomTheme.HALLOWEEN && darkMode && featureFlags.isHalloweenEnabled) {
return 'darkHalloween' as CowSwapTheme
if (ACTIVE_CUSTOM_THEME === CustomTheme.HALLOWEEN && darkMode && isHalloweenEnabled) {
return 'darkHalloween'
}
if (ACTIVE_CUSTOM_THEME === CustomTheme.CHRISTMAS && isChristmasEnabled) {
return darkMode ? 'darkChristmas' : 'lightChristmas'
}
return undefined
}, [darkMode, featureFlags.isHalloweenEnabled])
}, [darkMode, isHalloweenEnabled, isChristmasEnabled])

const persistentAdditionalContent = (
<HeaderControls>
Expand All @@ -112,6 +115,8 @@ export function App() {
</HeaderControls>
)

const isChristmasTheme = ACTIVE_CUSTOM_THEME === CustomTheme.CHRISTMAS && isChristmasEnabled

return (
<ErrorBoundary>
<Suspense fallback={<LoadingApp />}>
Expand Down Expand Up @@ -151,12 +156,28 @@ export function App() {

<styledEl.BodyWrapper customTheme={customTheme}>
<TopLevelModals />

<RoutesApp />

<styledEl.Marginer />
</styledEl.BodyWrapper>

{!isInjectedWidgetMode && isChristmasTheme && (
<Snowfall
style={{
position: 'fixed',
width: '100vw',
height: '100vh',
zIndex: 3,
pointerEvents: 'none',
top: 0,
left: 0,
}}
snowflakeCount={isMobile ? 25 : darkMode ? 75 : 200}
radius={[0.5, 2.0]}
speed={[0.5, 2.0]}
wind={[-0.5, 1.0]}
/>
)}

{!isInjectedWidgetMode && (
<Footer
productVariant={PRODUCT_VARIANT}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import IMAGE_BACKGROUND_DARK_CHRISTMAS_MEDIUM from '@cowprotocol/assets/images/background-cowswap-christmas-dark-medium.svg'
import IMAGE_BACKGROUND_DARK_CHRISTMAS_SMALL from '@cowprotocol/assets/images/background-cowswap-christmas-dark-small.svg'
import IMAGE_BACKGROUND_DARK_CHRISTMAS from '@cowprotocol/assets/images/background-cowswap-christmas-dark.svg'
import IMAGE_BACKGROUND_LIGHT_CHRISTMAS_MEDIUM from '@cowprotocol/assets/images/background-cowswap-christmas-light-medium.svg'
import IMAGE_BACKGROUND_LIGHT_CHRISTMAS_SMALL from '@cowprotocol/assets/images/background-cowswap-christmas-light-small.svg'
import IMAGE_BACKGROUND_LIGHT_CHRISTMAS from '@cowprotocol/assets/images/background-cowswap-christmas-light.svg'
import IMAGE_BACKGROUND_DARK from '@cowprotocol/assets/images/background-cowswap-darkmode.svg'
import IMAGE_BACKGROUND_DARK_HALLOWEEN_MEDIUM from '@cowprotocol/assets/images/background-cowswap-halloween-dark-medium.svg'
import IMAGE_BACKGROUND_DARK_HALLOWEEN_SMALL from '@cowprotocol/assets/images/background-cowswap-halloween-dark-small.svg'
Expand All @@ -8,6 +14,14 @@ import { CowSwapTheme, Media } from '@cowprotocol/ui'
import * as CSS from 'csstype'
import styled from 'styled-components/macro'

function isChristmasTheme(theme?: CowSwapTheme) {
if (!theme) {
return false
}

return ['darkChristmas', 'lightChristmas'].includes(theme)
}

export const AppWrapper = styled.div<Partial<CSS.Properties>>`
display: flex;
flex-flow: column;
Expand Down Expand Up @@ -42,8 +56,12 @@ export const BodyWrapper = styled.div<{ customTheme?: CowSwapTheme }>`
const backgroundColor = theme.darkMode ? '#0E0F2D' : '#65D9FF'
let backgroundImage
if (customTheme === ('darkHalloween' as CowSwapTheme)) {
if (customTheme === 'darkHalloween') {
backgroundImage = `url(${IMAGE_BACKGROUND_DARK_HALLOWEEN})`
} else if (isChristmasTheme(customTheme)) {
backgroundImage = theme.darkMode
? `url(${IMAGE_BACKGROUND_DARK_CHRISTMAS})`
: `url(${IMAGE_BACKGROUND_LIGHT_CHRISTMAS})`
} else {
backgroundImage = theme.darkMode ? `url(${IMAGE_BACKGROUND_DARK})` : `url(${IMAGE_BACKGROUND_LIGHT})`
}
Expand All @@ -59,20 +77,32 @@ export const BodyWrapper = styled.div<{ customTheme?: CowSwapTheme }>`
background-size: auto;
${({ customTheme }) =>
customTheme === ('darkHalloween' as CowSwapTheme) &&
customTheme === 'darkHalloween' &&
`
background-image: url(${IMAGE_BACKGROUND_DARK_HALLOWEEN_MEDIUM});
`}
${({ customTheme, theme }) =>
isChristmasTheme(customTheme) &&
`
background-image: url(${theme.darkMode ? IMAGE_BACKGROUND_DARK_CHRISTMAS_MEDIUM : IMAGE_BACKGROUND_LIGHT_CHRISTMAS_MEDIUM});
`}
}
${Media.upToSmall()} {
padding: ${({ theme }) => (theme.isInjectedWidgetMode ? '0 0 16px' : '90px 16px 76px')};
min-height: ${({ theme }) => (theme.isInjectedWidgetMode ? 'initial' : 'calc(100vh - 100px)')};
${({ customTheme }) =>
customTheme === ('darkHalloween' as CowSwapTheme) &&
customTheme === 'darkHalloween' &&
`
background-image: url(${IMAGE_BACKGROUND_DARK_HALLOWEEN_SMALL});
`}
${({ customTheme, theme }) =>
isChristmasTheme(customTheme) &&
`
background-image: url(${theme.darkMode ? IMAGE_BACKGROUND_DARK_CHRISTMAS_SMALL : IMAGE_BACKGROUND_LIGHT_CHRISTMAS_SMALL});
`}
}
`
2 changes: 2 additions & 0 deletions apps/cowswap-frontend/src/modules/sounds/utils/sound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const THEMED_SOUNDS: Partial<Record<SoundType, ThemedSoundOptions>> = {
halloweenSound: '/audio/halloween.mp3',
},
SUCCESS: {
winterSound: '/audio/success-winterTheme.mp3',
halloweenSound: '/audio/halloween.mp3',
},
}
Expand All @@ -49,6 +50,7 @@ function getThemeBasedSound(type: SoundType): string {
const featureFlags = jotaiStore.get(featureFlagsAtom) as Record<string, boolean>
const defaultSound = DEFAULT_COW_SOUNDS[type]
const themedOptions = THEMED_SOUNDS[type]

const isInjectedWidgetMode = isInjectedWidget()

// When in widget mode, always return default sounds
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 7db4b72

Please sign in to comment.