feat: welcome nft banner (#5379)
* wip * finished modal, waiting for assets * feat: use srcset for better assets optimisation * feat: bg photo * various tweaks * feat: wrap up logic * chore: use proper link * chore: bring switch back
This commit is contained in:
parent
d528b28203
commit
1a31560374
BIN
src/assets/images/welcomeModal-dark.jpg
Normal file
BIN
src/assets/images/welcomeModal-dark.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 134 KiB |
BIN
src/assets/images/welcomeModal-dark@2x.jpg
Normal file
BIN
src/assets/images/welcomeModal-dark@2x.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 449 KiB |
BIN
src/assets/images/welcomeModal-dark@3x.jpg
Normal file
BIN
src/assets/images/welcomeModal-dark@3x.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 927 KiB |
BIN
src/assets/images/welcomeModal-light.jpg
Normal file
BIN
src/assets/images/welcomeModal-light.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 118 KiB |
BIN
src/assets/images/welcomeModal-light@2x.jpg
Normal file
BIN
src/assets/images/welcomeModal-light@2x.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 364 KiB |
BIN
src/assets/images/welcomeModal-light@3x.jpg
Normal file
BIN
src/assets/images/welcomeModal-light@3x.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 718 KiB |
@ -8,7 +8,7 @@ import { Z_INDEX } from 'theme/zIndex'
|
||||
import { isMobile } from '../../utils/userAgent'
|
||||
|
||||
const AnimatedDialogOverlay = animated(DialogOverlay)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
const StyledDialogOverlay = styled(AnimatedDialogOverlay)<{ scrollOverlay?: boolean }>`
|
||||
&[data-reach-dialog-overlay] {
|
||||
z-index: ${Z_INDEX.modalBackdrop};
|
||||
|
111
src/nft/components/explore/WelcomeModal.tsx
Normal file
111
src/nft/components/explore/WelcomeModal.tsx
Normal file
@ -0,0 +1,111 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
import Modal from 'components/Modal'
|
||||
import { useState } from 'react'
|
||||
import { X } from 'react-feather'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
import { ExternalLink } from 'theme/components'
|
||||
import { ThemedText } from 'theme/components/text'
|
||||
|
||||
const Container = styled.div`
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 30% 24px 24px;
|
||||
overflow: hidden;
|
||||
height: fit-content;
|
||||
user-select: none;
|
||||
`
|
||||
|
||||
const CloseButton = styled(X)`
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 24px;
|
||||
cursor: pointer;
|
||||
`
|
||||
|
||||
const Background = styled.img`
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
object-fit: contain;
|
||||
`
|
||||
|
||||
const Content = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 1;
|
||||
gap: 16px;
|
||||
`
|
||||
|
||||
const Title = styled(ThemedText.LargeHeader)`
|
||||
@media (max-width: ${({ theme }) => theme.breakpoint.xl}px) {
|
||||
font-size: 20px !important;
|
||||
}
|
||||
`
|
||||
|
||||
const Paragraph = styled(ThemedText.BodySecondary)`
|
||||
line-height: 24px;
|
||||
|
||||
@media (max-width: ${({ theme }) => theme.breakpoint.xl}px) {
|
||||
font-size: 14px !important;
|
||||
line-height: 20px;
|
||||
}
|
||||
`
|
||||
|
||||
const BACKGROUND_IMAGE = {
|
||||
dark: {
|
||||
src: require('../../../assets/images/welcomeModal-dark.jpg').default,
|
||||
srcSet: `
|
||||
${require('../../../assets/images/welcomeModal-dark@2x.jpg').default} 2x,
|
||||
${require('../../../assets/images/welcomeModal-dark@3x.jpg').default} 3x,
|
||||
`,
|
||||
},
|
||||
light: {
|
||||
src: require('../../../assets/images/welcomeModal-light.jpg').default,
|
||||
srcSet: `
|
||||
${require('../../../assets/images/welcomeModal-light@2x.jpg').default} 2x,
|
||||
${require('../../../assets/images/welcomeModal-light@3x.jpg').default} 3x,
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
export function WelcomeModal({ onDismissed }: { onDismissed: () => void }) {
|
||||
const [isOpen, setIsOpen] = useState(true)
|
||||
|
||||
const dismiss = () => {
|
||||
setIsOpen(false)
|
||||
setTimeout(() => onDismissed())
|
||||
}
|
||||
|
||||
const theme = useTheme()
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onDismiss={dismiss} maxWidth={720}>
|
||||
<Container>
|
||||
<Background
|
||||
{...(theme.darkMode ? BACKGROUND_IMAGE.dark : BACKGROUND_IMAGE.light)}
|
||||
alt="Welcome modal background"
|
||||
draggable={false}
|
||||
/>
|
||||
<Content>
|
||||
<Title>Introducing Uniswap NFT</Title>
|
||||
<Paragraph>
|
||||
We’re excited to announce that Uniswap Labs has acquired Genie to build the marketplace for all digital
|
||||
assets! With Uniswap NFT, you can buy and sell NFTs across all marketplaces with the full functionality of
|
||||
Genie. Additonally, if you’ve used Genie in the past, then you may be eligible for a USDC airdrop. You can
|
||||
connect your wallet to claim any rewards. For more details on the airdrop please read the official
|
||||
announcement on the Uniswap Labs blog.{' '}
|
||||
<ExternalLink
|
||||
href="https://uniswap.org/blog/uniswap-nft-aggregator-announcement"
|
||||
title="Uniswap NFT aggregator announcement"
|
||||
>
|
||||
Learn more.
|
||||
</ExternalLink>
|
||||
</Paragraph>
|
||||
<CloseButton size={24} onClick={dismiss} />
|
||||
</Content>
|
||||
</Container>
|
||||
</Modal>
|
||||
)
|
||||
}
|
@ -2,8 +2,10 @@ import { Trace } from '@uniswap/analytics'
|
||||
import { PageName } from '@uniswap/analytics-events'
|
||||
import Banner from 'nft/components/explore/Banner'
|
||||
import TrendingCollections from 'nft/components/explore/TrendingCollections'
|
||||
import { WelcomeModal } from 'nft/components/explore/WelcomeModal'
|
||||
import { useBag } from 'nft/hooks'
|
||||
import { useEffect } from 'react'
|
||||
import { useHideNFTWelcomeModal } from 'state/user/hooks'
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
const ExploreContainer = styled.div`
|
||||
@ -23,6 +25,7 @@ const ExploreContainer = styled.div`
|
||||
|
||||
const NftExplore = () => {
|
||||
const setBagExpanded = useBag((state) => state.setBagExpanded)
|
||||
const [isModalHidden, hideModal] = useHideNFTWelcomeModal()
|
||||
|
||||
useEffect(() => {
|
||||
setBagExpanded({ bagExpanded: false, manualClose: false })
|
||||
@ -35,6 +38,7 @@ const NftExplore = () => {
|
||||
<Banner />
|
||||
<TrendingCollections />
|
||||
</ExploreContainer>
|
||||
{!isModalHidden && <WelcomeModal onDismissed={hideModal} />}
|
||||
</Trace>
|
||||
</>
|
||||
)
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
addSerializedToken,
|
||||
removeSerializedToken,
|
||||
updateHideClosedPositions,
|
||||
updateHideNFTWelcomeModal,
|
||||
updateShowNftPromoBanner,
|
||||
updateShowSurveyPopup,
|
||||
updateUserClientSideRouter,
|
||||
@ -118,6 +119,15 @@ export function useShowSurveyPopup(): [boolean | undefined, (showPopup: boolean)
|
||||
return [showSurveyPopup, toggleShowSurveyPopup]
|
||||
}
|
||||
|
||||
export function useHideNFTWelcomeModal(): [boolean | undefined, () => void] {
|
||||
const dispatch = useAppDispatch()
|
||||
const hideNFTWelcomeModal = useAppSelector((state) => state.user.hideNFTWelcomeModal)
|
||||
const hideModal = useCallback(() => {
|
||||
dispatch(updateHideNFTWelcomeModal({ hideNFTWelcomeModal: true }))
|
||||
}, [dispatch])
|
||||
return [hideNFTWelcomeModal, hideModal]
|
||||
}
|
||||
|
||||
export function useClientSideRouter(): [boolean, (userClientSideRouter: boolean) => void] {
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
|
@ -54,6 +54,8 @@ export interface UserState {
|
||||
showSurveyPopup: boolean | undefined
|
||||
|
||||
showDonationLink: boolean
|
||||
|
||||
hideNFTWelcomeModal: boolean
|
||||
}
|
||||
|
||||
function pairKey(token0Address: string, token1Address: string) {
|
||||
@ -78,6 +80,7 @@ export const initialState: UserState = {
|
||||
hideNFTPromoBanner: false,
|
||||
showSurveyPopup: undefined,
|
||||
showDonationLink: true,
|
||||
hideNFTWelcomeModal: true,
|
||||
}
|
||||
|
||||
const userSlice = createSlice({
|
||||
@ -123,6 +126,9 @@ const userSlice = createSlice({
|
||||
updateShowDonationLink(state, action) {
|
||||
state.showDonationLink = action.payload.showDonationLink
|
||||
},
|
||||
updateHideNFTWelcomeModal(state, action) {
|
||||
state.hideNFTWelcomeModal = action.payload.hideNFTWelcomeModal
|
||||
},
|
||||
updateShowNftPromoBanner(state, action) {
|
||||
state.hideNFTPromoBanner = action.payload.hideNFTPromoBanner
|
||||
},
|
||||
@ -210,6 +216,7 @@ export const {
|
||||
updateShowDonationLink,
|
||||
updateShowSurveyPopup,
|
||||
updateUserClientSideRouter,
|
||||
updateHideNFTWelcomeModal,
|
||||
updateUserDarkMode,
|
||||
updateUserDeadline,
|
||||
updateUserExpertMode,
|
||||
|
Loading…
Reference in New Issue
Block a user