Commit 1ea72460 authored by Jack Short's avatar Jack Short Committed by GitHub

feat: bottom sheet for mobile swap settings (#7072)

* feat: bottom sheet for settings dialogue

* renaming to settings

* renmaing

* cypress tests

* fixing the cypress tests

* chore: e2e insufficient liquidity test

* Revert "chore: e2e insufficient liquidity test"

This reverts commit 8250730f35182246ec908b5878b91b55a51cb941.
parent 2b6948db
...@@ -6,6 +6,7 @@ describe('Swap settings', () => { ...@@ -6,6 +6,7 @@ describe('Swap settings', () => {
cy.visit('/swap', { featureFlags: [FeatureFlag.uniswapXEnabled] }) cy.visit('/swap', { featureFlags: [FeatureFlag.uniswapXEnabled] })
cy.contains('Settings').should('not.exist') cy.contains('Settings').should('not.exist')
cy.get(getTestSelector('open-settings-dialog-button')).click() cy.get(getTestSelector('open-settings-dialog-button')).click()
cy.get(getTestSelector('mobile-settings-menu')).should('not.exist')
cy.contains('Max slippage').should('exist') cy.contains('Max slippage').should('exist')
cy.contains('Transaction deadline').should('exist') cy.contains('Transaction deadline').should('exist')
cy.contains('UniswapX').should('exist') cy.contains('UniswapX').should('exist')
...@@ -13,4 +14,16 @@ describe('Swap settings', () => { ...@@ -13,4 +14,16 @@ describe('Swap settings', () => {
cy.get(getTestSelector('open-settings-dialog-button')).click() cy.get(getTestSelector('open-settings-dialog-button')).click()
cy.contains('Settings').should('not.exist') cy.contains('Settings').should('not.exist')
}) })
it('should open the mobile settings menu', () => {
cy.viewport('iphone-6')
cy.visit('/swap', { featureFlags: [FeatureFlag.uniswapXEnabled] })
cy.get(getTestSelector('open-settings-dialog-button')).click()
cy.get(getTestSelector('mobile-settings-menu')).should('exist')
cy.contains('Max slippage').should('exist')
cy.contains('Transaction deadline').should('exist')
cy.contains('UniswapX').should('exist')
cy.contains('Local routing').should('exist')
cy.get(getTestSelector('mobile-settings-scrim')).click()
})
}) })
...@@ -58,7 +58,7 @@ const ScrimBackground = styled.div<{ open: boolean }>` ...@@ -58,7 +58,7 @@ const ScrimBackground = styled.div<{ open: boolean }>`
transition: opacity ${({ theme }) => theme.transition.duration.medium} ease-in-out; transition: opacity ${({ theme }) => theme.transition.duration.medium} ease-in-out;
} }
` `
const Scrim = ({ onClick, open }: { onClick: () => void; open: boolean }) => { export const Scrim = ({ onClick, open, testId }: { onClick: () => void; open: boolean; testId?: string }) => {
const { width } = useWindowSize() const { width } = useWindowSize()
useEffect(() => { useEffect(() => {
...@@ -68,7 +68,7 @@ const Scrim = ({ onClick, open }: { onClick: () => void; open: boolean }) => { ...@@ -68,7 +68,7 @@ const Scrim = ({ onClick, open }: { onClick: () => void; open: boolean }) => {
} }
}, [open, width]) }, [open, width])
return <ScrimBackground onClick={onClick} open={open} /> return <ScrimBackground data-testid={testId} onClick={onClick} open={open} />
} }
const AccountDrawerScrollWrapper = styled.div` const AccountDrawerScrollWrapper = styled.div`
......
import { Trans } from '@lingui/macro'
import { Percent } from '@uniswap/sdk-core' import { Percent } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { Scrim } from 'components/AccountDrawer'
import AnimatedDropdown from 'components/AnimatedDropdown' import AnimatedDropdown from 'components/AnimatedDropdown'
import { AutoColumn } from 'components/Column' import Column, { AutoColumn } from 'components/Column'
import Row from 'components/Row'
import { isSupportedChain, L2_CHAIN_IDS } from 'constants/chains' import { isSupportedChain, L2_CHAIN_IDS } from 'constants/chains'
import useDisableScrolling from 'hooks/useDisableScrolling' import useDisableScrolling from 'hooks/useDisableScrolling'
import { useOnClickOutside } from 'hooks/useOnClickOutside' import { useOnClickOutside } from 'hooks/useOnClickOutside'
import { useRef } from 'react' import { Portal } from 'nft/components/common/Portal'
import { useIsMobile } from 'nft/hooks'
import { useMemo, useRef } from 'react'
import { useModalIsOpen, useToggleSettingsMenu } from 'state/application/hooks' import { useModalIsOpen, useToggleSettingsMenu } from 'state/application/hooks'
import { ApplicationModal } from 'state/application/reducer' import { ApplicationModal } from 'state/application/reducer'
import { InterfaceTrade } from 'state/routing/types' import { InterfaceTrade } from 'state/routing/types'
import { isUniswapXTrade } from 'state/routing/utils' import { isUniswapXTrade } from 'state/routing/utils'
import styled from 'styled-components' import styled from 'styled-components'
import { Divider } from 'theme' import { CloseIcon, Divider, ThemedText } from 'theme'
import { Z_INDEX } from 'theme/zIndex'
import MaxSlippageSettings from './MaxSlippageSettings' import MaxSlippageSettings from './MaxSlippageSettings'
import MenuButton from './MenuButton' import MenuButton from './MenuButton'
...@@ -47,6 +53,39 @@ const ExpandColumn = styled(AutoColumn)` ...@@ -47,6 +53,39 @@ const ExpandColumn = styled(AutoColumn)`
padding-top: 16px; padding-top: 16px;
` `
const MobileMenuContainer = styled(Row)`
overflow: visible;
position: fixed;
height: 100%;
top: 100vh;
left: 0;
right: 0;
width: 100%;
z-index: ${Z_INDEX.fixed};
`
const MobileMenuWrapper = styled(Column)<{ open: boolean }>`
height: min-content;
width: 100%;
padding: 8px 16px 24px;
background-color: ${({ theme }) => theme.backgroundSurface};
overflow: hidden;
position: absolute;
bottom: ${({ open }) => (open ? `100vh` : 0)};
transition: bottom ${({ theme }) => theme.transition.duration.medium};
border: ${({ theme }) => `1px solid ${theme.backgroundOutline}`};
border-radius: 12px;
border-bottom-right-radius: 0px;
border-bottom-left-radius: 0px;
font-size: 16px;
box-shadow: unset;
z-index: ${Z_INDEX.modal};
`
const MobileMenuHeader = styled(Row)`
margin-bottom: 16px;
`
export default function SettingsTab({ export default function SettingsTab({
autoSlippage, autoSlippage,
chainId, chainId,
...@@ -63,34 +102,67 @@ export default function SettingsTab({ ...@@ -63,34 +102,67 @@ export default function SettingsTab({
const isOpen = useModalIsOpen(ApplicationModal.SETTINGS) const isOpen = useModalIsOpen(ApplicationModal.SETTINGS)
const toggleMenu = useToggleSettingsMenu() const toggleMenu = useToggleSettingsMenu()
useOnClickOutside(node, isOpen ? toggleMenu : undefined)
const isMobile = useIsMobile()
const isOpenMobile = isOpen && isMobile
const isOpenDesktop = isOpen && !isMobile
useOnClickOutside(node, isOpenDesktop ? toggleMenu : undefined)
useDisableScrolling(isOpen) useDisableScrolling(isOpen)
const isChainSupported = isSupportedChain(chainId) const isChainSupported = isSupportedChain(chainId)
const Settings = useMemo(
() => (
<>
<AutoColumn gap="16px">
<RouterPreferenceSettings />
</AutoColumn>
<AnimatedDropdown open={!isUniswapXTrade(trade)}>
<ExpandColumn>
<Divider />
<MaxSlippageSettings autoSlippage={autoSlippage} />
{showDeadlineSettings && (
<>
<Divider />
<TransactionDeadlineSettings />
</>
)}
</ExpandColumn>
</AnimatedDropdown>
</>
),
[autoSlippage, showDeadlineSettings, trade]
)
return ( return (
<Menu ref={node}> <>
<MenuButton disabled={!isChainSupported || chainId !== connectedChainId} isActive={isOpen} onClick={toggleMenu} /> <Menu ref={node}>
{isOpen && ( <MenuButton
<MenuFlyout> disabled={!isChainSupported || chainId !== connectedChainId}
<AutoColumn gap="16px"> isActive={isOpen}
<RouterPreferenceSettings /> onClick={toggleMenu}
</AutoColumn> />
<AnimatedDropdown open={!isUniswapXTrade(trade)}> {isOpenDesktop && !isMobile && <MenuFlyout>{Settings}</MenuFlyout>}
<ExpandColumn> </Menu>
<Divider /> {isMobile && (
<MaxSlippageSettings autoSlippage={autoSlippage} /> <Portal>
{showDeadlineSettings && ( <MobileMenuContainer data-testid="mobile-settings-menu">
<> <Scrim testId="mobile-settings-scrim" onClick={toggleMenu} open={isOpenMobile} />
<Divider /> <MobileMenuWrapper open={isOpenMobile}>
<TransactionDeadlineSettings /> <MobileMenuHeader padding="8px 0px 4px">
</> <CloseIcon size={24} onClick={toggleMenu} />
)} <Row padding="0px 24px 0px 0px" justify="center">
</ExpandColumn> <ThemedText.SubHeader>
</AnimatedDropdown> <Trans>Settings</Trans>
</MenuFlyout> </ThemedText.SubHeader>
</Row>
</MobileMenuHeader>
{Settings}
</MobileMenuWrapper>
</MobileMenuContainer>
</Portal>
)} )}
</Menu> </>
) )
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment