feat: Initial landing page redesign updates (#5456)

* Initial landing page redesign updates

* export

* unnecessary brackets

* unused component

* remove state for the overlay

* remove more show landing logic

* only show when on /

* gated

* pointer events fix

* import z-index

* get started -> continue

* rm text-fill-color

* no fill color

* unused icon

* dont add route

* css fixes
This commit is contained in:
Vignesh Mohankumar 2022-12-06 22:06:21 -05:00 committed by GitHub
parent 6480b947ef
commit 50f6401a8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 412 additions and 7 deletions

@ -211,6 +211,19 @@ export const ButtonEmpty = styled(BaseButton)`
} }
` `
export const ButtonCTA = styled(BaseButton)<{ redesignFlag?: boolean }>`
background: linear-gradient(10deg, rgba(255, 0, 199, 1) 0%, rgba(255, 159, 251, 1) 100%);
width: fit-content;
border-radius: 24px;
border: none;
padding: 16px 77.5px;
margin-left: 12px;
margin-bottom: 12px;
color: ${({ theme }) => theme.white};
&:hover {
opacity: 75%;
}
`
export const ButtonText = styled(BaseButton)` export const ButtonText = styled(BaseButton)`
padding: 0; padding: 0;
width: fit-content; width: fit-content;

@ -7,7 +7,7 @@ import { Box } from 'nft/components/Box'
import { Row } from 'nft/components/Flex' import { Row } from 'nft/components/Flex'
import { UniIcon } from 'nft/components/icons' import { UniIcon } from 'nft/components/icons'
import { ReactNode } from 'react' import { ReactNode } from 'react'
import { NavLink, NavLinkProps, useLocation } from 'react-router-dom' import { NavLink, NavLinkProps, useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { Bag } from './Bag' import { Bag } from './Bag'
@ -87,14 +87,22 @@ const PageTabs = () => {
const Navbar = () => { const Navbar = () => {
const isNftPage = useIsNftPage() const isNftPage = useIsNftPage()
const navigate = useNavigate()
return ( return (
<> <>
<nav className={styles.nav}> <nav className={styles.nav}>
<Box display="flex" height="full" flexWrap="nowrap" alignItems="stretch"> <Box display="flex" height="full" flexWrap="nowrap" alignItems="stretch">
<Box className={styles.leftSideContainer}> <Box className={styles.leftSideContainer}>
<Box as="a" href="#/swap" className={styles.logoContainer}> <Box className={styles.logoContainer}>
<UniIcon width="48" height="48" className={styles.logo} /> <UniIcon
width="48"
height="48"
className={styles.logo}
onClick={() => {
navigate('/')
}}
/>
</Box> </Box>
{!isNftPage && ( {!isNftPage && (
<Box display={{ sm: 'flex', lg: 'none' }}> <Box display={{ sm: 'flex', lg: 'none' }}>

@ -12,6 +12,9 @@ export const nav = style([
zIndex: '2', zIndex: '2',
background: 'backgroundFloating', background: 'backgroundFloating',
}), }),
{
backdropFilter: 'blur(24px)',
},
]) ])
export const logoContainer = style([ export const logoContainer = style([
@ -19,6 +22,7 @@ export const logoContainer = style([
display: 'flex', display: 'flex',
marginRight: { sm: '12', xxl: '20' }, marginRight: { sm: '12', xxl: '20' },
alignItems: 'center', alignItems: 'center',
cursor: 'pointer',
}), }),
]) ])

@ -23,13 +23,19 @@ export const PageWrapper = styled.div`
` `
// Mostly copied from `AppBody` but it was getting too hard to maintain backwards compatibility. // Mostly copied from `AppBody` but it was getting too hard to maintain backwards compatibility.
export const SwapWrapper = styled.main<{ margin?: string; maxWidth?: string }>` export const SwapWrapper = styled.main<{ margin?: string; maxWidth?: string; open: boolean }>`
position: relative; position: relative;
background: ${({ theme }) => theme.backgroundSurface}; background: ${({ theme }) => theme.backgroundSurface};
border-radius: 16px; border-radius: 16px;
border: 1px solid ${({ theme }) => theme.backgroundOutline}; border: 1px solid ${({ theme }) => theme.backgroundOutline};
padding: 8px; padding: 8px;
z-index: ${Z_INDEX.deprecated_content}; z-index: ${Z_INDEX.deprecated_content};
cursor: ${({ open }) => (open ? 'pointer' : 'suto')};
transition: transform 250ms ease;
&:hover {
border: 1px solid ${({ theme, open }) => (open ? theme.accentAction : theme.backgroundOutline)};
transform: ${({ open }) => (open ? `translateY(-4px)` : `none`)};
}
` `
export const ArrowWrapper = styled.div<{ clickable: boolean }>` export const ArrowWrapper = styled.div<{ clickable: boolean }>`

185
src/pages/About.tsx Normal file

@ -0,0 +1,185 @@
import { Box } from 'nft/components/Box'
import { DiscordIconMenu, GithubIconMenu, TwitterIconMenu } from 'nft/components/icons'
import { ReactNode } from 'react'
import { BookOpen, Globe, Heart, HelpCircle, Terminal, Twitter } from 'react-feather'
import { useIsDarkMode } from 'state/user/hooks'
import styled, { useTheme } from 'styled-components/macro'
import { BREAKPOINTS } from 'theme'
const MOBILE_BREAKPOINT = BREAKPOINTS.md
const IconRow = styled.span`
display: flex;
flex-direction: row;
`
const SMALL_CARD_ICON_SIZE = 32
const Icon = ({ href, children }: { href?: string; children: ReactNode }) => {
return (
<Box
as={href ? 'a' : 'div'}
href={href ?? undefined}
target={href ? '_blank' : undefined}
rel={href ? 'noopener noreferrer' : undefined}
display="flex"
flexDirection="column"
color="textPrimary"
background="none"
border="none"
justifyContent="center"
textAlign="center"
marginRight="12"
>
{children}
</Box>
)
}
const PageWrapper = styled.span<{ isDarkMode: boolean }>`
width: 100%;
align-self: center;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
`
const TitleText = styled.h1<{ isDarkMode: boolean }>`
color: transparent;
font-size: 48px;
font-weight: 600;
margin-bottom: 0px;
background: ${({ isDarkMode }) =>
isDarkMode
? 'linear-gradient(20deg, rgba(255, 244, 207, 1) 10%, rgba(255, 87, 218, 1) 100%)'
: 'linear-gradient(10deg, rgba(255,79,184,1) 0%, rgba(255,159,251,1) 100%)'};
background-clip: text;
-webkit-background-clip: text;
@media screen and (min-width: ${MOBILE_BREAKPOINT}px) {
font-size: 72px;
}
`
const Body = styled.p`
color: ${({ theme }) => theme.textPrimary};
font-size: 18px;
padding: 0;
margin: 0;
`
const ContentWrapper = styled.span`
max-width: 960px;
pointer-events: all;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
padding: 8rem 1rem 1rem 1rem;
gap: 24px;
@media screen and (min-width: ${MOBILE_BREAKPOINT}px) {
padding: 8rem 5rem 5rem 5rem;
gap: 56px;
}
`
const SmallCardContainer = styled.div`
display: grid;
gap: 12px;
width: 100%;
grid-template-columns: 1fr;
@media screen and (min-width: ${BREAKPOINTS.sm}px) {
grid-template-columns: 1fr 1fr;
}
@media screen and (min-width: ${BREAKPOINTS.lg}px) {
grid-template-columns: 1fr 1fr 1fr;
}
`
const SmallCard = styled.a`
background-color: #0e111a;
display: flex;
flex-direction: column;
justify-content: space-between;
text-decoration: none;
color: white;
padding: 32px;
min-height: 220px;
font-weight: light;
border-radius: 12px;
border: 1px solid ${({ theme }) => theme.backgroundOutline};
font-size: 32px;
transition: 200ms ease all;
&:hover {
transition: 200ms ease background-color;
background-color: ${({ theme }) => theme.backgroundModule};
}
`
export default function About() {
const isDarkMode = useIsDarkMode()
const theme = useTheme()
return (
<PageWrapper isDarkMode={isDarkMode}>
<ContentWrapper>
<TitleText isDarkMode={isDarkMode}>
Our mission: <br />
Unlock universal ownership & exchange
</TitleText>
<Body>
Uniswap Labs is building the future of decentralized finance by harnessing the power of the Uniswap Protocol.
</Body>
<SmallCardContainer>
<SmallCard href="https://uniswap.org" target="_blank" rel="noopener noreferrer">
<Globe size={SMALL_CARD_ICON_SIZE} strokeWidth={1} color={theme.textSecondary} />
Uniswap Protocol
</SmallCard>
<SmallCard href="https://uniswap.org/blog" target="_blank" rel="noopener noreferrer">
<BookOpen size={SMALL_CARD_ICON_SIZE} strokeWidth={1} color={theme.textSecondary} />
Blog
</SmallCard>
<SmallCard href="https://boards.greenhouse.io/uniswaplabs" target="_blank" rel="noopener noreferrer">
<Heart size={SMALL_CARD_ICON_SIZE} strokeWidth={1} color={theme.textSecondary} />
Careers
</SmallCard>
<SmallCard href="https://support.uniswap.org/" target="_blank" rel="noopener noreferrer">
<HelpCircle size={SMALL_CARD_ICON_SIZE} strokeWidth={1} color={theme.textSecondary} />
Support
</SmallCard>
<SmallCard href="https://twitter.com/Uniswap" target="_blank" rel="noopener noreferrer">
<Twitter size={SMALL_CARD_ICON_SIZE} strokeWidth={1} color={theme.textSecondary} />
Twitter
</SmallCard>
<SmallCard href="https://uniswap.org/developers" target="_blank" rel="noopener noreferrer">
<Terminal size={SMALL_CARD_ICON_SIZE} strokeWidth={1} color={theme.textSecondary} />
Developers
</SmallCard>
</SmallCardContainer>
<span>
<small>
Media inquires for Uniswap Labs - Contact <a href="mailto:media@uniswap.org">media@uniswap.org</a>
</small>
</span>
<IconRow>
<Icon href="https://discord.com/invite/FCfyBSbCU5">
<DiscordIconMenu width={24} height={24} color={theme.textSecondary} />
</Icon>
<Icon href="https://twitter.com/Uniswap">
<TwitterIconMenu width={24} height={24} color={theme.textSecondary} />
</Icon>
<Icon href="https://github.com/Uniswap">
<GithubIconMenu width={24} height={24} color={theme.textSecondary} />
</Icon>
</IconRow>
</ContentWrapper>
</PageWrapper>
)
}

@ -3,6 +3,7 @@ import { CustomUserProperties, EventName, getBrowser, PageName } from '@uniswap/
import Loader from 'components/Loader' import Loader from 'components/Loader'
import TopLevelModals from 'components/TopLevelModals' import TopLevelModals from 'components/TopLevelModals'
import { useFeatureFlagsIsLoaded } from 'featureFlags' import { useFeatureFlagsIsLoaded } from 'featureFlags'
import { LandingPageVariant, useLandingPageFlag } from 'featureFlags/flags/landingPage'
import ApeModeQueryParamReader from 'hooks/useApeModeQueryParamReader' import ApeModeQueryParamReader from 'hooks/useApeModeQueryParamReader'
import { CollectionPageSkeleton } from 'nft/components/collection/CollectionPageSkeleton' import { CollectionPageSkeleton } from 'nft/components/collection/CollectionPageSkeleton'
import { AssetDetailsLoading } from 'nft/components/details/AssetDetailsLoading' import { AssetDetailsLoading } from 'nft/components/details/AssetDetailsLoading'
@ -25,11 +26,13 @@ import Polling from '../components/Polling'
import Popups from '../components/Popups' import Popups from '../components/Popups'
import { useIsExpertMode } from '../state/user/hooks' import { useIsExpertMode } from '../state/user/hooks'
import DarkModeQueryParamReader from '../theme/components/DarkModeQueryParamReader' import DarkModeQueryParamReader from '../theme/components/DarkModeQueryParamReader'
import About from './About'
import AddLiquidity from './AddLiquidity' import AddLiquidity from './AddLiquidity'
import { RedirectDuplicateTokenIds } from './AddLiquidity/redirects' import { RedirectDuplicateTokenIds } from './AddLiquidity/redirects'
import { RedirectDuplicateTokenIdsV2 } from './AddLiquidityV2/redirects' import { RedirectDuplicateTokenIdsV2 } from './AddLiquidityV2/redirects'
import Earn from './Earn' import Earn from './Earn'
import Manage from './Earn/Manage' import Manage from './Earn/Manage'
import Landing from './Landing'
import MigrateV2 from './MigrateV2' import MigrateV2 from './MigrateV2'
import MigrateV2Pair from './MigrateV2/MigrateV2Pair' import MigrateV2Pair from './MigrateV2/MigrateV2Pair'
import Pool from './Pool' import Pool from './Pool'
@ -178,6 +181,8 @@ export default function App() {
const isHeaderTransparent = !scrolledState && !isBagExpanded const isHeaderTransparent = !scrolledState && !isBagExpanded
const landingPageFlag = useLandingPageFlag()
return ( return (
<ErrorBoundary> <ErrorBoundary>
<DarkModeQueryParamReader /> <DarkModeQueryParamReader />
@ -191,9 +196,11 @@ export default function App() {
<Popups /> <Popups />
<Polling /> <Polling />
<TopLevelModals /> <TopLevelModals />
<Landing />
<Suspense fallback={<Loader />}> <Suspense fallback={<Loader />}>
{isLoaded ? ( {isLoaded ? (
<Routes> <Routes>
{landingPageFlag === LandingPageVariant.Enabled && <Route path="/" element={<Swap />} />}
<Route path="tokens" element={<Tokens />}> <Route path="tokens" element={<Tokens />}>
<Route path=":chainName" /> <Route path=":chainName" />
</Route> </Route>
@ -243,6 +250,8 @@ export default function App() {
<Route path="migrate/v2" element={<MigrateV2 />} /> <Route path="migrate/v2" element={<MigrateV2 />} />
<Route path="migrate/v2/:address" element={<MigrateV2Pair />} /> <Route path="migrate/v2/:address" element={<MigrateV2Pair />} />
<Route path="about" element={<About />} />
<Route path="*" element={<RedirectPathToSwapOnly />} /> <Route path="*" element={<RedirectPathToSwapOnly />} />
<Route <Route

170
src/pages/Landing.tsx Normal file

File diff suppressed because one or more lines are too long

@ -12,6 +12,7 @@ import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter
import TokenSafetyModal from 'components/TokenSafety/TokenSafetyModal' import TokenSafetyModal from 'components/TokenSafety/TokenSafetyModal'
import { MouseoverTooltip } from 'components/Tooltip' import { MouseoverTooltip } from 'components/Tooltip'
import { isSupportedChain } from 'constants/chains' import { isSupportedChain } from 'constants/chains'
import { LandingPageVariant, useLandingPageFlag } from 'featureFlags/flags/landingPage'
import { useSwapCallback } from 'hooks/useSwapCallback' import { useSwapCallback } from 'hooks/useSwapCallback'
import useTransactionDeadline from 'hooks/useTransactionDeadline' import useTransactionDeadline from 'hooks/useTransactionDeadline'
import JSBI from 'jsbi' import JSBI from 'jsbi'
@ -19,7 +20,7 @@ import { formatSwapQuoteReceivedEventProperties } from 'lib/utils/analytics'
import { useCallback, useEffect, useMemo, useState } from 'react' import { useCallback, useEffect, useMemo, useState } from 'react'
import { ReactNode } from 'react' import { ReactNode } from 'react'
import { ArrowDown, CheckCircle, HelpCircle } from 'react-feather' import { ArrowDown, CheckCircle, HelpCircle } from 'react-feather'
import { useNavigate } from 'react-router-dom' import { useLocation, useNavigate } from 'react-router-dom'
import { Text } from 'rebass' import { Text } from 'rebass'
import { useToggleWalletModal } from 'state/application/hooks' import { useToggleWalletModal } from 'state/application/hooks'
import { InterfaceTrade } from 'state/routing/types' import { InterfaceTrade } from 'state/routing/types'
@ -495,6 +496,11 @@ export default function Swap() {
const showDetailsDropdown = Boolean( const showDetailsDropdown = Boolean(
!showWrap && userHasSpecifiedInputOutput && (trade || routeIsLoading || routeIsSyncing) !showWrap && userHasSpecifiedInputOutput && (trade || routeIsLoading || routeIsSyncing)
) )
const location = useLocation()
const landingPageFlag = useLandingPageFlag()
return ( return (
<Trace page={PageName.SWAP_PAGE} shouldLogImpression> <Trace page={PageName.SWAP_PAGE} shouldLogImpression>
<> <>
@ -507,7 +513,11 @@ export default function Swap() {
showCancel={true} showCancel={true}
/> />
<PageWrapper> <PageWrapper>
<SwapWrapper id="swap-page"> <SwapWrapper
onClick={() => landingPageFlag === LandingPageVariant.Enabled && navigate('/swap')}
open={landingPageFlag === LandingPageVariant.Enabled && location.pathname === '/'}
id="swap-page"
>
<SwapHeader allowedSlippage={allowedSlippage} /> <SwapHeader allowedSlippage={allowedSlippage} />
<ConfirmSwapModal <ConfirmSwapModal
isOpen={showConfirm} isOpen={showConfirm}

@ -17,7 +17,7 @@ export const MEDIA_WIDTHS = {
deprecated_upToLarge: 1280, deprecated_upToLarge: 1280,
} }
const BREAKPOINTS = { export const BREAKPOINTS = {
xs: 396, xs: 396,
sm: 640, sm: 640,
md: 768, md: 768,