feat: nft explore promo banner (#5369)
* init * it looks good and is working * don't change image on every render * un-move dark mode hook * oops * handle mobile screen smallest size * first round comment responses * second round comments * rest of comments * fix analytics changes * remove unnecesasry z index
This commit is contained in:
parent
ceed5e0b4c
commit
c1cb712087
@ -3,7 +3,9 @@ import AddressClaimModal from 'components/claim/AddressClaimModal'
|
||||
import ConnectedAccountBlocked from 'components/ConnectedAccountBlocked'
|
||||
import { NftVariant, useNftFlag } from 'featureFlags/flags/nft'
|
||||
import useAccountRiskCheck from 'hooks/useAccountRiskCheck'
|
||||
import NftExploreBanner from 'nft/components/nftExploreBanner/NftExploreBanner'
|
||||
import { lazy } from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { useModalIsOpen, useToggleModal } from 'state/application/hooks'
|
||||
import { ApplicationModal } from 'state/application/reducer'
|
||||
|
||||
@ -17,6 +19,12 @@ export default function TopLevelModals() {
|
||||
|
||||
const blockedAccountModalOpen = useModalIsOpen(ApplicationModal.BLOCKED_ACCOUNT)
|
||||
const { account } = useWeb3React()
|
||||
const location = useLocation()
|
||||
const isNftEnabled = useNftFlag() === NftVariant.Enabled
|
||||
const pageShowsNftPromoBanner =
|
||||
location.pathname.startsWith('/swap') ||
|
||||
location.pathname.startsWith('/tokens') ||
|
||||
location.pathname.startsWith('/pool')
|
||||
|
||||
useAccountRiskCheck(account)
|
||||
const open = Boolean(blockedAccountModalOpen && account)
|
||||
@ -25,8 +33,13 @@ export default function TopLevelModals() {
|
||||
<AddressClaimModal isOpen={addressClaimOpen} onDismiss={addressClaimToggle} />
|
||||
<ConnectedAccountBlocked account={account} isOpen={open} />
|
||||
<Bag />
|
||||
{useNftFlag() === NftVariant.Enabled && <TransactionCompleteModal />}
|
||||
{useNftFlag() === NftVariant.Enabled && <AirdropModal />}
|
||||
{isNftEnabled && (
|
||||
<>
|
||||
<TransactionCompleteModal />
|
||||
<AirdropModal />
|
||||
{pageShowsNftPromoBanner && <NftExploreBanner />}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
130
src/nft/components/nftExploreBanner/NftExploreBanner.tsx
Normal file
130
src/nft/components/nftExploreBanner/NftExploreBanner.tsx
Normal file
@ -0,0 +1,130 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { LARGE_MEDIA_BREAKPOINT, SMALL_MOBILE_MEDIA_BREAKPOINT } from 'components/Tokens/constants'
|
||||
import { Box } from 'nft/components/Box'
|
||||
import { bodySmall, subhead } from 'nft/css/common.css'
|
||||
import { X } from 'react-feather'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useShowNftPromoBanner } from 'state/user/hooks'
|
||||
import styled from 'styled-components/macro'
|
||||
import { StyledInternalLink } from 'theme'
|
||||
import { Z_INDEX } from 'theme/zIndex'
|
||||
|
||||
import nftPromoImage1 from '../nftExploreBanner/nftArt1.png'
|
||||
import nftPromoImage2 from '../nftExploreBanner/nftArt2.png'
|
||||
import nftPromoImage3 from '../nftExploreBanner/nftArt3.png'
|
||||
|
||||
function getRandom(list: any[]) {
|
||||
return list[Math.floor(Math.random() * list.length)]
|
||||
}
|
||||
const randomizedNftImage = getRandom([nftPromoImage1, nftPromoImage2, nftPromoImage3])
|
||||
|
||||
const PopupContainer = styled.div<{ show: boolean }>`
|
||||
background-color: ${({ theme }) => theme.backgroundSurface};
|
||||
box-shadow: ${({ theme }) => theme.deepShadow};
|
||||
border: 1px solid ${({ theme }) => theme.backgroundOutline};
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
color: ${({ theme }) => theme.textPrimary};
|
||||
display: ${({ show }) => (show ? 'flex' : 'none')};
|
||||
flex-direction: column;
|
||||
position: fixed;
|
||||
right: clamp(0px, 1vw, 16px);
|
||||
z-index: ${Z_INDEX.sticky};
|
||||
transition: ${({
|
||||
theme: {
|
||||
transition: { duration, timing },
|
||||
},
|
||||
}) => `${duration.slow} opacity ${timing.in}`};
|
||||
width: 98vw;
|
||||
bottom: 55px;
|
||||
@media screen and (min-width: ${LARGE_MEDIA_BREAKPOINT}) {
|
||||
bottom: 48px;
|
||||
}
|
||||
@media screen and (min-width: ${SMALL_MOBILE_MEDIA_BREAKPOINT}) {
|
||||
width: 391px;
|
||||
}
|
||||
:hover {
|
||||
border: double 1px transparent;
|
||||
border-radius: 12px;
|
||||
background-image: ${({ theme }) =>
|
||||
`linear-gradient(${theme.backgroundSurface}, ${theme.backgroundSurface}),
|
||||
radial-gradient(circle at top left, hsla(299, 100%, 87%, 1), hsla(299, 100%, 61%, 1))`};
|
||||
background-origin: border-box;
|
||||
background-clip: padding-box, border-box;
|
||||
}
|
||||
`
|
||||
|
||||
const InnerContainer = styled.div`
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
position: relative;
|
||||
gap: 8px;
|
||||
padding: 8px;
|
||||
`
|
||||
|
||||
const TextContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
`
|
||||
|
||||
const StyledXButton = styled(X)`
|
||||
color: ${({ theme }) => theme.textSecondary};
|
||||
&:hover {
|
||||
opacity: ${({ theme }) => theme.opacity.hover};
|
||||
}
|
||||
&:active {
|
||||
opacity: ${({ theme }) => theme.opacity.click};
|
||||
}
|
||||
`
|
||||
|
||||
const StyledImageContainer = styled(Box)`
|
||||
width: 23%;
|
||||
cursor: pointer;
|
||||
aspectratio: 1;
|
||||
transition: transform 0.25s ease 0s;
|
||||
object-fit: contain;
|
||||
`
|
||||
|
||||
export default function NftExploreBanner() {
|
||||
const [showNftPromoBanner, stopShowingNftPromoBanner] = useShowNftPromoBanner()
|
||||
const navigate = useNavigate()
|
||||
|
||||
const navigateToNfts = () => {
|
||||
navigate('/nfts')
|
||||
stopShowingNftPromoBanner()
|
||||
}
|
||||
|
||||
return (
|
||||
<PopupContainer show={showNftPromoBanner} onClick={navigateToNfts}>
|
||||
<InnerContainer>
|
||||
<StyledImageContainer as="img" src={randomizedNftImage} draggable={false} />
|
||||
<TextContainer>
|
||||
{/* <HeaderText> */}
|
||||
<div className={subhead}>
|
||||
<Trans>Introducing Uniswap NFT</Trans>
|
||||
</div>
|
||||
{/* </HeaderText> */}
|
||||
|
||||
{/* <Description> */}
|
||||
<div className={bodySmall}>
|
||||
<Trans>Buy and sell NFTs across more listings at better prices.</Trans>{' '}
|
||||
<StyledInternalLink to="/nfts">
|
||||
<Trans>Explore NFTs</Trans>
|
||||
</StyledInternalLink>{' '}
|
||||
</div>
|
||||
</TextContainer>
|
||||
{/* </Description> */}
|
||||
<StyledXButton
|
||||
size={20}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
stopShowingNftPromoBanner()
|
||||
}}
|
||||
/>
|
||||
</InnerContainer>
|
||||
</PopupContainer>
|
||||
)
|
||||
}
|
BIN
src/nft/components/nftExploreBanner/nftArt1.png
Normal file
BIN
src/nft/components/nftExploreBanner/nftArt1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
BIN
src/nft/components/nftExploreBanner/nftArt2.png
Normal file
BIN
src/nft/components/nftExploreBanner/nftArt2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
BIN
src/nft/components/nftExploreBanner/nftArt3.png
Normal file
BIN
src/nft/components/nftExploreBanner/nftArt3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
@ -97,15 +97,23 @@ const Marginer = styled.div`
|
||||
`
|
||||
|
||||
function getCurrentPageFromLocation(locationPathname: string): PageName | undefined {
|
||||
switch (locationPathname) {
|
||||
case '/swap':
|
||||
switch (true) {
|
||||
case locationPathname.startsWith('/swap'):
|
||||
return PageName.SWAP_PAGE
|
||||
case '/vote':
|
||||
case locationPathname.startsWith('/vote'):
|
||||
return PageName.VOTE_PAGE
|
||||
case '/pool':
|
||||
case locationPathname.startsWith('/pool'):
|
||||
return PageName.POOL_PAGE
|
||||
case '/tokens':
|
||||
case locationPathname.startsWith('/tokens'):
|
||||
return PageName.TOKENS_PAGE
|
||||
case locationPathname.startsWith('/nfts/profile'):
|
||||
return PageName.NFT_PROFILE_PAGE
|
||||
case locationPathname.startsWith('/nfts/asset'):
|
||||
return PageName.NFT_DETAILS_PAGE
|
||||
case locationPathname.startsWith('/nfts/collection'):
|
||||
return PageName.NFT_COLLECTION_PAGE
|
||||
case locationPathname.startsWith('/nfts'):
|
||||
return PageName.NFT_EXPLORE_PAGE
|
||||
default:
|
||||
return undefined
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
addSerializedToken,
|
||||
removeSerializedToken,
|
||||
updateHideClosedPositions,
|
||||
updateShowNftPromoBanner,
|
||||
updateShowSurveyPopup,
|
||||
updateUserClientSideRouter,
|
||||
updateUserDarkMode,
|
||||
@ -271,6 +272,17 @@ export function useURLWarningVisible(): boolean {
|
||||
return useAppSelector((state: AppState) => state.user.URLWarningVisible)
|
||||
}
|
||||
|
||||
export function useShowNftPromoBanner(): [boolean, () => void] {
|
||||
const dispatch = useAppDispatch()
|
||||
const showNftPromoBanner = useAppSelector((state) => state.user.NFTPromoBannerVisible)
|
||||
|
||||
const stopShowingNftPromoBanner = useCallback(() => {
|
||||
dispatch(updateShowNftPromoBanner({ showNftPromoBanner: false }))
|
||||
}, [dispatch])
|
||||
|
||||
return [showNftPromoBanner, stopShowingNftPromoBanner]
|
||||
}
|
||||
|
||||
/**
|
||||
* Given two tokens return the liquidity token that represents its liquidity shares
|
||||
* @param tokenA one of the two tokens
|
||||
|
@ -48,6 +48,7 @@ export interface UserState {
|
||||
|
||||
timestamp: number
|
||||
URLWarningVisible: boolean
|
||||
NFTPromoBannerVisible: boolean // whether or not we should show the nft explore promo banner
|
||||
|
||||
// undefined means has not gone through A/B split yet
|
||||
showSurveyPopup: boolean | undefined
|
||||
@ -74,6 +75,7 @@ export const initialState: UserState = {
|
||||
pairs: {},
|
||||
timestamp: currentTimestamp(),
|
||||
URLWarningVisible: true,
|
||||
NFTPromoBannerVisible: true,
|
||||
showSurveyPopup: undefined,
|
||||
showDonationLink: true,
|
||||
}
|
||||
@ -121,6 +123,9 @@ const userSlice = createSlice({
|
||||
updateShowDonationLink(state, action) {
|
||||
state.showDonationLink = action.payload.showDonationLink
|
||||
},
|
||||
updateShowNftPromoBanner(state, action) {
|
||||
state.NFTPromoBannerVisible = action.payload.NFTPromoBannerVisible
|
||||
},
|
||||
addSerializedToken(state, { payload: { serializedToken } }) {
|
||||
if (!state.tokens) {
|
||||
state.tokens = {}
|
||||
@ -210,5 +215,6 @@ export const {
|
||||
updateUserExpertMode,
|
||||
updateUserLocale,
|
||||
updateUserSlippageTolerance,
|
||||
updateShowNftPromoBanner,
|
||||
} = userSlice.actions
|
||||
export default userSlice.reducer
|
||||
|
Loading…
Reference in New Issue
Block a user