feat: add base promotional advert (#7124)
* feat: add base promotional advert add mobile layout tweak text container size only show new banner on Base fix import update to new state structure * Update src/components/Banner/BaseAnnouncementBanner/index.tsx Co-authored-by: Charles Bachmeier <charles@bachmeier.io> * pr feedback --------- Co-authored-by: Charles Bachmeier <charles@bachmeier.io>
This commit is contained in:
parent
b14831be12
commit
0b8026e6fe
3
src/assets/svg/base_background_icon.svg
Normal file
3
src/assets/svg/base_background_icon.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="119" height="99" viewBox="0 0 119 99" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M118.097 29.6061C117.891 67.6376 86.8404 98.3016 48.7425 98.0958C12.5975 97.9006 -16.9048 69.9894 -19.659 34.6507L71.5199 35.1431L71.5825 23.5662L-19.5965 23.0738C-16.4608 -12.2332 13.3412 -39.824 49.4863 -39.6288C87.5842 -39.423 118.302 -8.4256 118.097 29.6061Z" fill="white" fill-opacity="0.1"/>
|
||||
</svg>
|
After Width: | Height: | Size: 452 B |
92
src/components/Banner/BaseAnnouncementBanner/index.tsx
Normal file
92
src/components/Banner/BaseAnnouncementBanner/index.tsx
Normal file
@ -0,0 +1,92 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { InterfaceElementName } from '@uniswap/analytics-events'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { ReactComponent as AppleLogo } from 'assets/svg/apple_logo.svg'
|
||||
import baseLogoUrl from 'assets/svg/base_background_icon.svg'
|
||||
import { useScreenSize } from 'hooks/useScreenSize'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { useHideBaseWalletBanner } from 'state/user/hooks'
|
||||
import { ThemedText } from 'theme'
|
||||
import { openDownloadApp, openWalletMicrosite } from 'utils/openDownloadApp'
|
||||
import { isIOS, isMobileSafari } from 'utils/userAgent'
|
||||
|
||||
import { BannerButton, BaseBackgroundImage, ButtonRow, PopupContainer, StyledXButton } from './styled'
|
||||
|
||||
export default function BaseWalletBanner() {
|
||||
const { chainId } = useWeb3React()
|
||||
const [hideBaseWalletBanner, toggleHideBaseWalletBanner] = useHideBaseWalletBanner()
|
||||
const location = useLocation()
|
||||
const isLandingScreen = location.search === '?intro=true' || location.pathname === '/'
|
||||
|
||||
const shouldDisplay = Boolean(!hideBaseWalletBanner && !isLandingScreen && chainId === ChainId.BASE)
|
||||
|
||||
const screenSize = useScreenSize()
|
||||
|
||||
if (isMobileSafari) return null
|
||||
|
||||
return (
|
||||
<PopupContainer show={shouldDisplay}>
|
||||
<StyledXButton
|
||||
data-testid="uniswap-wallet-banner"
|
||||
size={20}
|
||||
onClick={(e) => {
|
||||
// prevent click from bubbling to UI on the page underneath, i.e. clicking a token row
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
toggleHideBaseWalletBanner()
|
||||
}}
|
||||
/>
|
||||
|
||||
<BaseBackgroundImage src={baseLogoUrl} alt="transparent base background logo" />
|
||||
|
||||
<ThemedText.HeadlineMedium fontSize="24px" lineHeight="28px" color="white" maxWidth="224px">
|
||||
<Trans>
|
||||
Swap on{' '}
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M19.5689 10C19.5689 15.4038 15.1806 19.7845 9.76737 19.7845C4.63163 19.7845 0.418433 15.8414 0 10.8225H12.9554V9.17755H0C0.418433 4.15863 4.63163 0.215576 9.76737 0.215576C15.1806 0.215576 19.5689 4.59621 19.5689 10Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>{' '}
|
||||
BASE in the Uniswap wallet
|
||||
</Trans>
|
||||
</ThemedText.HeadlineMedium>
|
||||
|
||||
<ButtonRow>
|
||||
{isIOS ? (
|
||||
<>
|
||||
<BannerButton
|
||||
backgroundColor="white"
|
||||
onClick={() =>
|
||||
openDownloadApp({
|
||||
element: InterfaceElementName.UNISWAP_WALLET_BANNER_DOWNLOAD_BUTTON,
|
||||
appStoreParams: 'pt=123625782&ct=base-app-banner&mt=8',
|
||||
})
|
||||
}
|
||||
>
|
||||
<AppleLogo width={14} height={14} />
|
||||
<ThemedText.LabelSmall color="black" marginLeft="5px">
|
||||
{!screenSize['xs'] ? <Trans>Download</Trans> : <Trans>Download app</Trans>}
|
||||
</ThemedText.LabelSmall>
|
||||
</BannerButton>
|
||||
|
||||
<BannerButton backgroundColor="black" onClick={() => openWalletMicrosite()}>
|
||||
<ThemedText.LabelSmall color="white">
|
||||
<Trans>Learn more</Trans>
|
||||
</ThemedText.LabelSmall>
|
||||
</BannerButton>
|
||||
</>
|
||||
) : (
|
||||
<BannerButton backgroundColor="white" width="125px" onClick={() => openWalletMicrosite()}>
|
||||
<ThemedText.LabelSmall color="black">
|
||||
<Trans>Learn more</Trans>
|
||||
</ThemedText.LabelSmall>
|
||||
</BannerButton>
|
||||
)}
|
||||
</ButtonRow>
|
||||
</PopupContainer>
|
||||
)
|
||||
}
|
84
src/components/Banner/BaseAnnouncementBanner/styled.tsx
Normal file
84
src/components/Banner/BaseAnnouncementBanner/styled.tsx
Normal file
@ -0,0 +1,84 @@
|
||||
import walletBannerPhoneImageSrc from 'assets/images/wallet_banner_phone_image.png'
|
||||
import { BaseButton } from 'components/Button'
|
||||
import { OpacityHoverState } from 'components/Common'
|
||||
import Row from 'components/Row'
|
||||
import { X } from 'react-feather'
|
||||
import styled from 'styled-components'
|
||||
import { Z_INDEX } from 'theme/zIndex'
|
||||
|
||||
export const PopupContainer = styled.div<{ show: boolean }>`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
${({ show }) => !show && 'display: none'};
|
||||
|
||||
background: url(${walletBannerPhoneImageSrc});
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 18px right 15px;
|
||||
background-size: 166px;
|
||||
|
||||
:hover {
|
||||
background-size: 170px;
|
||||
}
|
||||
transition: background-size ${({ theme }) => theme.transition.duration.medium}
|
||||
${({ theme }) => theme.transition.timing.inOut};
|
||||
|
||||
background-color: ${({ theme }) => theme.chain_84531};
|
||||
color: ${({ theme }) => theme.textPrimary};
|
||||
position: fixed;
|
||||
z-index: ${Z_INDEX.sticky};
|
||||
|
||||
padding: 24px 16px 16px;
|
||||
|
||||
border-radius: 20px;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
width: 390px;
|
||||
height: 164px;
|
||||
|
||||
border: 1px solid ${({ theme }) => theme.backgroundOutline};
|
||||
|
||||
box-shadow: ${({ theme }) => theme.deepShadow};
|
||||
|
||||
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.md}px`}) {
|
||||
bottom: 62px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.sm}px`}) {
|
||||
background-position: top 32px right -10px;
|
||||
width: unset;
|
||||
right: 10px;
|
||||
left: 10px;
|
||||
height: 144px;
|
||||
}
|
||||
|
||||
user-select: none;
|
||||
`
|
||||
|
||||
export const BaseBackgroundImage = styled.img`
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 138px;
|
||||
width: 138px;
|
||||
`
|
||||
export const ButtonRow = styled(Row)`
|
||||
gap: 16px;
|
||||
`
|
||||
export const StyledXButton = styled(X)`
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 21px;
|
||||
right: 17px;
|
||||
|
||||
color: ${({ theme }) => theme.white};
|
||||
${OpacityHoverState};
|
||||
`
|
||||
|
||||
export const BannerButton = styled(BaseButton)`
|
||||
height: 40px;
|
||||
border-radius: 16px;
|
||||
padding: 10px;
|
||||
${OpacityHoverState};
|
||||
`
|
@ -1,150 +0,0 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { InterfaceElementName } from '@uniswap/analytics-events'
|
||||
import walletBannerPhoneImageSrc from 'assets/images/wallet_banner_phone_image.png'
|
||||
import { ReactComponent as AppleLogo } from 'assets/svg/apple_logo.svg'
|
||||
import { BaseButton } from 'components/Button'
|
||||
import { AutoColumn } from 'components/Column'
|
||||
import { OpacityHoverState } from 'components/Common'
|
||||
import Row from 'components/Row'
|
||||
import { useScreenSize } from 'hooks/useScreenSize'
|
||||
import { X } from 'react-feather'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { useHideUniswapWalletBanner } from 'state/user/hooks'
|
||||
import styled from 'styled-components'
|
||||
import { ThemedText } from 'theme'
|
||||
import { Z_INDEX } from 'theme/zIndex'
|
||||
import { openDownloadApp, openWalletMicrosite } from 'utils/openDownloadApp'
|
||||
import { isIOS, isMobileSafari } from 'utils/userAgent'
|
||||
|
||||
const PopupContainer = styled.div<{ show: boolean }>`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
${({ show }) => !show && 'display: none'};
|
||||
|
||||
background: url(${walletBannerPhoneImageSrc});
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 18px right 15px;
|
||||
background-size: 166px;
|
||||
|
||||
:hover {
|
||||
background-size: 170px;
|
||||
}
|
||||
transition: background-size ${({ theme }) => theme.transition.duration.medium}
|
||||
${({ theme }) => theme.transition.timing.inOut};
|
||||
|
||||
background-color: ${({ theme }) => theme.promotional};
|
||||
color: ${({ theme }) => theme.textPrimary};
|
||||
position: fixed;
|
||||
z-index: ${Z_INDEX.sticky};
|
||||
|
||||
padding: 24px 16px 16px;
|
||||
|
||||
border-radius: 20px;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
width: 390px;
|
||||
height: 164px;
|
||||
|
||||
border: 1px solid ${({ theme }) => theme.backgroundOutline};
|
||||
|
||||
box-shadow: ${({ theme }) => theme.deepShadow};
|
||||
|
||||
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.md}px`}) {
|
||||
bottom: 62px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.sm}px`}) {
|
||||
width: unset;
|
||||
right: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
user-select: none;
|
||||
`
|
||||
|
||||
const ButtonRow = styled(Row)`
|
||||
gap: 16px;
|
||||
`
|
||||
const StyledXButton = styled(X)`
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 21px;
|
||||
right: 17px;
|
||||
|
||||
color: ${({ theme }) => theme.white};
|
||||
${OpacityHoverState};
|
||||
`
|
||||
|
||||
const BannerButton = styled(BaseButton)`
|
||||
height: 40px;
|
||||
border-radius: 16px;
|
||||
padding: 10px;
|
||||
${OpacityHoverState};
|
||||
`
|
||||
|
||||
export default function UniswapWalletBanner() {
|
||||
const [hideUniswapWalletBanner, toggleHideUniswapWalletBanner] = useHideUniswapWalletBanner()
|
||||
const location = useLocation()
|
||||
const isLandingScreen = location.search === '?intro=true' || location.pathname === '/'
|
||||
|
||||
const shouldDisplay = Boolean(!hideUniswapWalletBanner && !isLandingScreen)
|
||||
|
||||
const screenSize = useScreenSize()
|
||||
|
||||
if (isMobileSafari) return null
|
||||
|
||||
return (
|
||||
<PopupContainer show={shouldDisplay}>
|
||||
<StyledXButton
|
||||
data-testid="uniswap-wallet-banner"
|
||||
size={20}
|
||||
onClick={(e) => {
|
||||
// prevent click from bubbling to UI on the page underneath, i.e. clicking a token row
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
toggleHideUniswapWalletBanner()
|
||||
}}
|
||||
/>
|
||||
|
||||
<AutoColumn gap="8px">
|
||||
<ThemedText.HeadlineMedium fontSize="24px" lineHeight="28px" color="white" maxWidth="60%">
|
||||
<Trans>Uniswap in your pocket</Trans>
|
||||
</ThemedText.HeadlineMedium>
|
||||
</AutoColumn>
|
||||
|
||||
<ButtonRow>
|
||||
{isIOS ? (
|
||||
<>
|
||||
<BannerButton
|
||||
backgroundColor="white"
|
||||
onClick={() =>
|
||||
openDownloadApp({
|
||||
element: InterfaceElementName.UNISWAP_WALLET_BANNER_DOWNLOAD_BUTTON,
|
||||
})
|
||||
}
|
||||
>
|
||||
<AppleLogo width={14} height={14} />
|
||||
<ThemedText.LabelSmall color="black" marginLeft="5px">
|
||||
{!screenSize['xs'] ? <Trans>Download</Trans> : <Trans>Download app</Trans>}
|
||||
</ThemedText.LabelSmall>
|
||||
</BannerButton>
|
||||
|
||||
<BannerButton backgroundColor="black" onClick={() => openWalletMicrosite()}>
|
||||
<ThemedText.LabelSmall color="white">
|
||||
<Trans>Learn more</Trans>
|
||||
</ThemedText.LabelSmall>
|
||||
</BannerButton>
|
||||
</>
|
||||
) : (
|
||||
<BannerButton backgroundColor="white" width="125px" onClick={() => openWalletMicrosite()}>
|
||||
<ThemedText.LabelSmall color="black">
|
||||
<Trans>Learn more</Trans>
|
||||
</ThemedText.LabelSmall>
|
||||
</BannerButton>
|
||||
)}
|
||||
</ButtonRow>
|
||||
</PopupContainer>
|
||||
)
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { OffchainActivityModal } from 'components/AccountDrawer/MiniPortfolio/Activity/OffchainActivityModal'
|
||||
import UniwalletModal from 'components/AccountDrawer/UniwalletModal'
|
||||
import UniswapWalletBanner from 'components/Banner/UniswapWalletBanner'
|
||||
import BaseAnnouncementBanner from 'components/Banner/BaseAnnouncementBanner'
|
||||
import AddressClaimModal from 'components/claim/AddressClaimModal'
|
||||
import ConnectedAccountBlocked from 'components/ConnectedAccountBlocked'
|
||||
import FiatOnrampModal from 'components/FiatOnrampModal'
|
||||
@ -28,7 +28,7 @@ export default function TopLevelModals() {
|
||||
<ConnectedAccountBlocked account={account} isOpen={accountBlocked} />
|
||||
<Bag />
|
||||
<UniwalletModal />
|
||||
<UniswapWalletBanner />
|
||||
<BaseAnnouncementBanner />
|
||||
<OffchainActivityModal />
|
||||
<TransactionCompleteModal />
|
||||
<AirdropModal />
|
||||
|
@ -16,8 +16,8 @@ import { AppState } from '../types'
|
||||
import {
|
||||
addSerializedPair,
|
||||
addSerializedToken,
|
||||
updateHideBaseWalletBanner,
|
||||
updateHideClosedPositions,
|
||||
updateHideUniswapWalletBanner,
|
||||
updateUserDeadline,
|
||||
updateUserLocale,
|
||||
updateUserRouterPreference,
|
||||
@ -211,15 +211,15 @@ export function useURLWarningVisible(): boolean {
|
||||
return useAppSelector((state: AppState) => state.user.URLWarningVisible)
|
||||
}
|
||||
|
||||
export function useHideUniswapWalletBanner(): [boolean, () => void] {
|
||||
export function useHideBaseWalletBanner(): [boolean, () => void] {
|
||||
const dispatch = useAppDispatch()
|
||||
const hideUniswapWalletBanner = useAppSelector((state) => state.user.hideUniswapWalletBanner)
|
||||
const hideBaseWalletBanner = useAppSelector((state) => state.user.hideBaseWalletBanner)
|
||||
|
||||
const toggleHideUniswapWalletBanner = useCallback(() => {
|
||||
dispatch(updateHideUniswapWalletBanner({ hideUniswapWalletBanner: true }))
|
||||
const toggleHideBaseWalletBanner = useCallback(() => {
|
||||
dispatch(updateHideBaseWalletBanner({ hideBaseWalletBanner: true }))
|
||||
}, [dispatch])
|
||||
|
||||
return [hideUniswapWalletBanner, toggleHideUniswapWalletBanner]
|
||||
return [hideBaseWalletBanner, toggleHideBaseWalletBanner]
|
||||
}
|
||||
|
||||
export function useUserDisabledUniswapX(): boolean {
|
||||
|
@ -7,8 +7,8 @@ import reducer, {
|
||||
addSerializedPair,
|
||||
addSerializedToken,
|
||||
initialState,
|
||||
updateHideBaseWalletBanner,
|
||||
updateHideClosedPositions,
|
||||
updateHideUniswapWalletBanner,
|
||||
updateSelectedWallet,
|
||||
updateUserDeadline,
|
||||
updateUserLocale,
|
||||
@ -110,10 +110,10 @@ describe('swap reducer', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('updateHideUniswapWalletBanner', () => {
|
||||
it('updates the hideUniswapWalletBanner', () => {
|
||||
store.dispatch(updateHideUniswapWalletBanner({ hideUniswapWalletBanner: true }))
|
||||
expect(store.getState().hideUniswapWalletBanner).toEqual(true)
|
||||
describe('updateHideBaseWalletBanner', () => {
|
||||
it('updates the updateHideBaseWalletBanner', () => {
|
||||
store.dispatch(updateHideBaseWalletBanner({ hideBaseWalletBanner: true }))
|
||||
expect(store.getState().hideBaseWalletBanner).toEqual(true)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -47,7 +47,7 @@ export interface UserState {
|
||||
|
||||
timestamp: number
|
||||
URLWarningVisible: boolean
|
||||
hideUniswapWalletBanner: boolean
|
||||
hideBaseWalletBanner: boolean
|
||||
disabledUniswapX?: boolean
|
||||
// undefined means has not gone through A/B split yet
|
||||
showSurveyPopup?: boolean
|
||||
@ -69,7 +69,7 @@ export const initialState: UserState = {
|
||||
pairs: {},
|
||||
timestamp: currentTimestamp(),
|
||||
URLWarningVisible: true,
|
||||
hideUniswapWalletBanner: false,
|
||||
hideBaseWalletBanner: false,
|
||||
showSurveyPopup: undefined,
|
||||
}
|
||||
|
||||
@ -98,8 +98,8 @@ const userSlice = createSlice({
|
||||
updateHideClosedPositions(state, action) {
|
||||
state.userHideClosedPositions = action.payload.userHideClosedPositions
|
||||
},
|
||||
updateHideUniswapWalletBanner(state, action) {
|
||||
state.hideUniswapWalletBanner = action.payload.hideUniswapWalletBanner
|
||||
updateHideBaseWalletBanner(state, action) {
|
||||
state.hideBaseWalletBanner = action.payload.hideBaseWalletBanner
|
||||
},
|
||||
updateDisabledUniswapX(state, action) {
|
||||
state.disabledUniswapX = action.payload.disabledUniswapX
|
||||
@ -214,7 +214,7 @@ export const {
|
||||
updateUserDeadline,
|
||||
updateUserLocale,
|
||||
updateUserSlippageTolerance,
|
||||
updateHideUniswapWalletBanner,
|
||||
updateHideBaseWalletBanner,
|
||||
updateDisabledUniswapX,
|
||||
} = userSlice.actions
|
||||
export default userSlice.reducer
|
||||
|
Loading…
Reference in New Issue
Block a user