Skip to content

Commit

Permalink
Uniswap widget style (#922)
Browse files Browse the repository at this point in the history
* Organize css selectors.

* Update RouterContext import in Storybook.

* Separate export from declaration in all pages.

Workaround for fixing this Storybook issue: storybookjs/storybook#11419 (comment)

* Fix i18n in Storybook.

* Fix lint.

* Move getting the web3provider inside the widget.

* Upgrade uniswap widget package.

* Style token selection screen.

* Apply round borders to all blue buttons.

* Fix lint
  • Loading branch information
ferni authored Mar 30, 2022
1 parent ad3e9d6 commit 936e108
Show file tree
Hide file tree
Showing 27 changed files with 196 additions and 566 deletions.
2 changes: 1 addition & 1 deletion .storybook/i18n.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import i18n from 'i18next'
import { initReactI18next } from 'next-i18next'
import { initReactI18next } from 'react-i18next'

import enTranslation from '../public/locales/en/common.json'

Expand Down
1 change: 1 addition & 0 deletions .storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
'@storybook/addon-essentials',
'@storybook/addon-postcss',
'storybook-addon-next-router',
'storybook-i18next',
],
// typescript: {
// reactDocgen: 'react-docgen-typescript',
Expand Down
2 changes: 1 addition & 1 deletion .storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ThemeProvider } from 'theme-ui'
import { theme } from '../theme'
import { I18nextProvider } from 'next-i18next'
import i18n from './i18n'
import { RouterContext } from 'next/dist/next-server/lib/router-context'
import { RouterContext } from 'next/dist/shared/lib/router-context'

addDecorator((storyFn) => <I18nextProvider i18n={i18n}>{storyFn()}</I18nextProvider>)
addDecorator((storyFn) => <ThemeProvider theme={theme}>{storyFn()}</ThemeProvider>)
Expand Down
25 changes: 7 additions & 18 deletions components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,7 @@ function ButtonDropdown({
function UserDesktopMenu() {
const exchangeEnabled = useFeatureToggle('Exchange')
const { t } = useTranslation()
const { web3ContextConnected$, accountData$, context$, web3Context$ } = useAppContext()
const [web3ContextConnected] = useObservable(web3ContextConnected$)
const web3Provider =
web3ContextConnected?.status !== 'connectedReadonly'
? web3ContextConnected?.web3.currentProvider
: null
const { accountData$, context$, web3Context$ } = useAppContext()
const [context] = useObservable(context$)
const [accountData] = useObservable(accountData$)
const [web3Context] = useObservable(web3Context$)
Expand Down Expand Up @@ -214,7 +209,7 @@ function UserDesktopMenu() {
<Box sx={{ display: ['inline', 'none', 'inline'] }}>{t('my-positions')}</Box>
<VaultCount />
</PositionsLink>
{exchangeEnabled && web3Provider ? (
{exchangeEnabled && (
<ButtonDropdown
ButtonContents={({ active }) => (
<Icon
Expand All @@ -226,9 +221,9 @@ function UserDesktopMenu() {
)}
round={true}
>
<UniswapWidget web3Provider={web3Provider} />
<UniswapWidget />
</ButtonDropdown>
) : null}
)}
{!shouldHideSettings && (
<ButtonDropdown
ButtonContents={({ active }) => (
Expand Down Expand Up @@ -348,12 +343,6 @@ function ConnectedHeader() {
const earnEnabled = useFeatureToggle('EarnProduct')
const exchangeEnabled = useFeatureToggle('Exchange')

const web3Provider = (() => {
const { web3ContextConnected$ } = useAppContext()
const [web3Context] = useObservable(web3ContextConnected$)
return web3Context?.status !== 'connectedReadonly' ? web3Context?.web3.currentProvider : null
})()

return (
<React.Fragment>
<Box sx={{ display: ['none', 'block'] }}>
Expand Down Expand Up @@ -413,7 +402,7 @@ function ConnectedHeader() {
<Flex sx={{ width: '100%', justifyContent: 'space-between', alignItems: 'center' }}>
<Logo />
</Flex>
{exchangeEnabled && web3Provider ? (
{exchangeEnabled && (
<Box sx={{ mr: 2 }}>
<ButtonDropdown
ButtonContents={({ active }) => (
Expand All @@ -434,10 +423,10 @@ function ConnectedHeader() {
transform: 'translateX(-50%) translateY(-50%)',
}}
>
<UniswapWidget web3Provider={web3Provider} />
<UniswapWidget />
</ButtonDropdown>
</Box>
) : null}
)}
<MobileMenu />
<MobileSettings />
</BasicHeader>
Expand Down
28 changes: 13 additions & 15 deletions components/uniswapWidget/UniswapWidget.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import detectEthereumProvider from '@metamask/detect-provider'
import { WithChildren } from 'helpers/types'
import React, { useEffect, useState } from 'react'
import React from 'react'
import { Box } from 'theme-ui'

import { UniswapWidget } from './UniswapWidget'
Expand All @@ -9,25 +8,24 @@ function StoryLayout({ children }: WithChildren) {
return <Box sx={{ p: 5, bg: 'pink' }}>{children}</Box>
}

function useWeb3Provider() {
const [provider, setProvider]: any = useState()
// function useWeb3Provider() {
// const [provider, setProvider]: any = useState()

useEffect(() => {
detectEthereumProvider()
.then(setProvider)
.catch(() => {
console.error('Error detecting provider')
})
}, [])
// useEffect(() => {
// detectEthereumProvider()
// .then(setProvider)
// .catch(() => {
// console.error('Error detecting provider')
// })
// }, [])

return provider
}
// return provider
// }

export const Widget = () => {
const provider = useWeb3Provider()
return (
<StoryLayout>
<UniswapWidget web3Provider={provider} />
<UniswapWidget />
</StoryLayout>
)
}
Expand Down
82 changes: 59 additions & 23 deletions components/uniswapWidget/UniswapWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useAppContext } from 'components/AppContextProvider'
import { AppSpinner } from 'helpers/AppSpinner'
import { useObservable } from 'helpers/observableHook'
import dynamic from 'next/dynamic'
import React, { useEffect, useState } from 'react'
import { theme } from 'theme'
import { Box, Flex } from 'theme-ui'
import { provider } from 'web3-core'

import tokenList from './tokenList.json'

Expand All @@ -23,26 +24,42 @@ const widgetTheme = {
borderRadius: radii.mediumLarge,
}

const wrapperPath = 'div > div:nth-of-type(2) > div:nth-of-type(2)'
function scrollbarBg(hexColor: string) {
return `radial-gradient( closest-corner at 0.25em 0.25em, ${hexColor} 0.25em, transparent 0.25em ), linear-gradient( to bottom, ${hexColor}00 0.25em, ${hexColor} 0.25em, ${hexColor} calc(100% - 0.25em), ${hexColor}00 calc(100% - 0.25em) ), radial-gradient( closest-corner at 0.25em calc(100% - 0.25em), ${hexColor} 0.25em, ${hexColor}00 0.25em )`
}

const cssPaths = {
// main screen
swapBtn: `${wrapperPath} > div:nth-of-type(2) > div > button`,
token1Btn: `${wrapperPath} > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > button`,
token2Btn: `${wrapperPath} > div:nth-of-type(3) > div > div:nth-of-type(2) > div:nth-of-type(1) > button`,
input1: `${wrapperPath} > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > div > input`,
input2: `${wrapperPath} > div:nth-of-type(3) > div > div:nth-of-type(2) > div:nth-of-type(1) > div > input`,
confirmBtn: `${wrapperPath} > div:nth-of-type(3) > div > div:nth-of-type(4) > button`,
const cssPaths = (() => {
const main = 'div > div:nth-of-type(2) > div:nth-of-type(2)'
const tokenSel = 'div > div:nth-of-type(1)'

// token selection
// this is used by the widget to expand the hover effect through the scrollbar
hoverAppended: `div > div:nth-of-type(1) > div > div:nth-of-type(3) > div:nth-of-type(1)`,
tokenOption: `div > div:nth-of-type(1) > div > div:nth-of-type(3) > div:nth-of-type(2) > div > div > button`,
}
return {
main: {
swapBtn: `${main} > div:nth-of-type(2) > div > button`,
token1Btn: `${main} > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > button`,
token2Btn: `${main} > div:nth-of-type(3) > div > div:nth-of-type(2) > div:nth-of-type(1) > button`,
input1: `${main} > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > div > input`,
input2: `${main} > div:nth-of-type(3) > div > div:nth-of-type(2) > div:nth-of-type(1) > div > input`,
},
// token select
tokenSel: {
// hoverAppended is for expanding the hover effect through the scrollbar (we'll hide it)
hoverAppended: `${tokenSel} > div > div:nth-of-type(3) > div:nth-of-type(1)`,
option: `${tokenSel} > div > div:nth-of-type(3) > div:nth-of-type(2) > div > div > button`,
search: `${tokenSel} input[inputmode=text]`,
scrollbar: `${tokenSel} .scrollbar`,
},
}
})()

export function UniswapWidget({ web3Provider }: { web3Provider?: provider }) {
export function UniswapWidget() {
const [SwapWidget, setSwapWidget] = useState()

const web3Provider = (() => {
const { web3ContextConnected$ } = useAppContext()
const [web3Context] = useObservable(web3ContextConnected$)
return web3Context?.status !== 'connectedReadonly' ? web3Context?.web3.currentProvider : null
})()

useEffect(() => {
setSwapWidget(
// @ts-ignore
Expand All @@ -52,30 +69,49 @@ export function UniswapWidget({ web3Provider }: { web3Provider?: provider }) {
)
}, [])

const { swapBtn, token1Btn, token2Btn, confirmBtn, hoverAppended, tokenOption } = cssPaths
const { main, tokenSel } = cssPaths

return web3Provider && SwapWidget ? (
<Box
sx={{
[swapBtn]: {
'.subhead': { fontWeight: 'medium' },
[main.swapBtn]: {
border: '3px solid',
borderColor: 'border',
':hover': { borderColor: 'primary', bg: 'surface' },
},
[token1Btn + '[color="interactive"], ' + token2Btn + '[color="interactive"]']: {
[main.token1Btn + '[color="interactive"], ' + main.token2Btn + '[color="interactive"]']: {
border: '1px solid',
borderColor: 'border',
':hover': { borderColor: 'primary', bg: 'surface' },
},
[hoverAppended]: { display: 'none' },
[tokenOption]: { bg: 'transparent', ':hover': { bg: 'border' }, borderRadius: '8px' },
[tokenSel.hoverAppended]: { display: 'none' },
[tokenSel.option]: {
bg: 'transparent',
':hover': { bg: 'border' },
borderRadius: '8px',
'.subhead': { fontWeight: 'semiBold' },
},
[tokenSel.search]: {
borderColor: 'border',
borderRadius: 'medium',
':hover': { bg: 'surface' },
':focus': { borderColor: 'primary' },
'::placeholder': { color: 'text.lavender' },
},
[tokenSel.scrollbar]: {
'::-webkit-scrollbar-thumb': {
background: scrollbarBg('#A8A9B1'),
backgroundClip: 'padding-box',
},
},
}}
css={`
${token1Btn} > div > div, ${token2Btn} > div > div {
${main.token1Btn} > div > div, ${main.token2Btn} > div > div {
font-size: 18px !important;
}
${confirmBtn} {
button[color=accent] {
border-radius: 32px !important;
}
`}
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"@types/ramda": "^0.27.34",
"@types/react-lottie": "^1.2.6",
"@types/theme-ui": "^0.3.1",
"@uniswap/widgets": "^0.0.25-beta",
"@uniswap/widgets": "^0.0.26-beta",
"@web3-react/abstract-connector": "^6.0.7",
"@web3-react/core": "^6.1.1",
"@web3-react/injected-connector": "npm:@oasisdex/injected-connector@^6.1.11",
Expand Down Expand Up @@ -213,9 +213,10 @@
"patch-package": "^6.2.2",
"prettier": "^2.0.1",
"prisma": "^3.9.1",
"react-i18next": "^11.16.2",
"sinon": "^9.0.2",
"sinon-chai": "^3.5.0",
"storybook-addon-i18next": "^1.3.0",
"storybook-i18next": "^1.0.3",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.4.3",
"webpack": "^4.42.1"
Expand Down
4 changes: 3 additions & 1 deletion pages/404.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const getStaticProps = async ({ locale }: { locale: string }) => ({
},
})

export default function NotFoundPage() {
function NotFoundPage() {
const { t } = useTranslation()

return (
Expand All @@ -27,3 +27,5 @@ export default function NotFoundPage() {
}

NotFoundPage.layout = MarketingLayout

export default NotFoundPage
4 changes: 3 additions & 1 deletion pages/[vault]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function getServerSideProps(ctx: GetServerSidePropsContext) {
}
}

export default function Vault({ id }: { id: string }) {
function Vault({ id }: { id: string }) {
const vaultId = new BigNumber(id)
const isValidVaultId = vaultId.isInteger() && vaultId.gt(0)
const automationEnabled = useFeatureToggle('Automation')
Expand Down Expand Up @@ -63,3 +63,5 @@ export default function Vault({ id }: { id: string }) {
}

Vault.layout = AppLayout

export default Vault
4 changes: 3 additions & 1 deletion pages/about.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import React from 'react'
import { Box, Grid, Heading, Image, Text } from 'theme-ui'

export default function AboutPage({ members }: { members: TeamMember[] }) {
function AboutPage({ members }: { members: TeamMember[] }) {
const { t } = useTranslation()

return (
Expand Down Expand Up @@ -53,6 +53,8 @@ AboutPage.layoutProps = {
variant: 'marketingSmallContainer',
}

export default AboutPage

function PortraitsGrid({ members }: { members: TeamMember[] }) {
const PORTRAIT_SIZE = '169px'

Expand Down
4 changes: 3 additions & 1 deletion pages/asset/[asset].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export async function getStaticProps(
}
}

export default function AssetPage({ content }: { content: AssetPageContent }) {
function AssetPage({ content }: { content: AssetPageContent }) {
const { replace } = useRouter()

if (!content) {
Expand All @@ -51,3 +51,5 @@ export default function AssetPage({ content }: { content: AssetPageContent }) {
}

AssetPage.layout = ProductPagesLayout

export default AssetPage
4 changes: 3 additions & 1 deletion pages/borrow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const getStaticProps = async ({ locale }: { locale: string }) => ({
},
})

export default function BorrowPage() {
function BorrowPage() {
return (
<WithConnection>
<BorrowView />
Expand All @@ -21,3 +21,5 @@ export default function BorrowPage() {

BorrowPage.layout = ProductPagesLayout
BorrowPage.theme = 'Landing'

export default BorrowPage
4 changes: 3 additions & 1 deletion pages/careers/[slug].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import dynamic from 'next/dynamic'
import React from 'react'
import { Box, Text } from 'theme-ui'

export default function CareerPage({ career }: { career: Career }) {
function CareerPage({ career }: { career: Career }) {
const { t } = useTranslation()
const Markdown = dynamic(() => import(`features/careers/listings/${career.slug}.mdx`))

Expand Down Expand Up @@ -73,6 +73,8 @@ CareerPage.layoutProps = {
variant: 'marketingSmallContainer',
}

export default CareerPage

export async function getStaticProps({ params, locale }: GetServerSidePropsContext) {
const career = await getCareerByFileName(`${params!.slug}.mdx`)

Expand Down
4 changes: 3 additions & 1 deletion pages/careers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const getStaticProps = async ({ locale }: { locale: string }) => {
},
}
}
export default function CareersPage({ careers }: { careers: Career[] }) {
function CareersPage({ careers }: { careers: Career[] }) {
const { t } = useTranslation()
const careersByArea = groupBy(careers, 'area')

Expand Down Expand Up @@ -136,3 +136,5 @@ CareersPage.layoutProps = {
topBackground: 'lighter',
variant: 'marketingSmallContainer',
}

export default CareersPage
Loading

0 comments on commit 936e108

Please sign in to comment.