diff --git a/src/assets/images/welcomeModal-dark.jpg b/src/assets/images/welcomeModal-dark.jpg
new file mode 100644
index 0000000000..d7b8075713
Binary files /dev/null and b/src/assets/images/welcomeModal-dark.jpg differ
diff --git a/src/assets/images/welcomeModal-dark@2x.jpg b/src/assets/images/welcomeModal-dark@2x.jpg
new file mode 100644
index 0000000000..5043bb6712
Binary files /dev/null and b/src/assets/images/welcomeModal-dark@2x.jpg differ
diff --git a/src/assets/images/welcomeModal-dark@3x.jpg b/src/assets/images/welcomeModal-dark@3x.jpg
new file mode 100644
index 0000000000..1ce51e7849
Binary files /dev/null and b/src/assets/images/welcomeModal-dark@3x.jpg differ
diff --git a/src/assets/images/welcomeModal-light.jpg b/src/assets/images/welcomeModal-light.jpg
new file mode 100644
index 0000000000..849db5b349
Binary files /dev/null and b/src/assets/images/welcomeModal-light.jpg differ
diff --git a/src/assets/images/welcomeModal-light@2x.jpg b/src/assets/images/welcomeModal-light@2x.jpg
new file mode 100644
index 0000000000..b8ae653a1e
Binary files /dev/null and b/src/assets/images/welcomeModal-light@2x.jpg differ
diff --git a/src/assets/images/welcomeModal-light@3x.jpg b/src/assets/images/welcomeModal-light@3x.jpg
new file mode 100644
index 0000000000..ea606182c5
Binary files /dev/null and b/src/assets/images/welcomeModal-light@3x.jpg differ
diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx
index 90e7246806..22dd984710 100644
--- a/src/components/Modal/index.tsx
+++ b/src/components/Modal/index.tsx
@@ -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};
diff --git a/src/nft/components/explore/WelcomeModal.tsx b/src/nft/components/explore/WelcomeModal.tsx
new file mode 100644
index 0000000000..abefeb7e55
--- /dev/null
+++ b/src/nft/components/explore/WelcomeModal.tsx
@@ -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 (
+
+
+
+
+ Introducing Uniswap NFT
+
+ 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.{' '}
+
+ Learn more.
+
+
+
+
+
+
+ )
+}
diff --git a/src/nft/pages/explore/index.tsx b/src/nft/pages/explore/index.tsx
index cc5206fa06..254a91e7fa 100644
--- a/src/nft/pages/explore/index.tsx
+++ b/src/nft/pages/explore/index.tsx
@@ -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 = () => {
+ {!isModalHidden && }
>
)
diff --git a/src/state/user/hooks.tsx b/src/state/user/hooks.tsx
index 6eb5e2a011..caf9d50bc1 100644
--- a/src/state/user/hooks.tsx
+++ b/src/state/user/hooks.tsx
@@ -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()
diff --git a/src/state/user/reducer.ts b/src/state/user/reducer.ts
index 986eb0b9cf..d464acf2ec 100644
--- a/src/state/user/reducer.ts
+++ b/src/state/user/reducer.ts
@@ -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,