Skip to content

Commit

Permalink
Widget UI + configurator (#3227)
Browse files Browse the repository at this point in the history
* feat: widget init mods

* feat: widget menu links

* feat: select menu

* feat: select menu

* feat: select menu

* Update apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx

Co-authored-by: Alexandr Kazachenko <[email protected]>

* feat: fix semicolons

* feat: menu styling

* feat: general styling

* feat: connect wallet internal

* feat: connect wallet internal

* feat: connect wallet internal

* feat: widget configurator app

* feat: widget configurator app

* feat: widget configurator app

* feat: widget configurator app

* feat: widget configurator app

* feat: widget configurator app

* feat: widget configurator app

* feat: widget configurator app

* feat: widget configurator app

* feat: widget configurator app

* feat: widget configurator app

* refactor: extract AccountElement and AccountModalState

* chore: update yarn.lock

* chore: fix code style

---------

Co-authored-by: Michel <[email protected]>
Co-authored-by: Alexandr Kazachenko <[email protected]>
  • Loading branch information
3 people authored Oct 20, 2023
1 parent ea85d84 commit 1a2c1de
Show file tree
Hide file tree
Showing 68 changed files with 1,720 additions and 286 deletions.
1 change: 1 addition & 0 deletions apps/cowswap-frontend/src/assets/icon/carret.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion apps/cowswap-frontend/src/assets/icon/gas-free.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions apps/cowswap-frontend/src/assets/icon/wallet.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions apps/cowswap-frontend/src/common/constants/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export enum UI {

// Icons
ICON_SIZE_NORMAL = '--cow-icon-size-normal',
ICON_SIZE_SMALL = '--cow-icon-size-small',
ICON_SIZE_XSMALL = '--cow-icon-size-xsmall',
ICON_SIZE_LARGE = '--cow-icon-size-large',
ICON_COLOR_NORMAL = '--cow-icon-color-normal',

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,19 @@ export const StepsWrapper = styled.div`
margin: auto;
position: absolute;
width: 100%;
max-width: 162px;
max-width: 35%;
left: 0;
right: 0;
top: 32px;
z-index: 1;
${({ theme }) => theme.mediaWidth.upToSmall`
max-width: 25%;
`}
${({ theme }) => theme.mediaWidth.upToVerySmall`
max-width: 20%;
`}
}
> hr::before {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ReactComponent as DropDown } from '@cowprotocol/assets/images/dropdown.
import { lighten, transparentize } from 'polished'
import styled from 'styled-components/macro'

import { UI } from 'common/constants/theme'

export const CurrencySelectWrapper = styled.button<{ isLoading: boolean; $stubbed: boolean; readonlyMode: boolean }>`
display: flex;
justify-content: space-between;
Expand All @@ -19,7 +21,7 @@ export const CurrencySelectWrapper = styled.button<{ isLoading: boolean; $stubbe
: `0px 4px 8px ${transparentize(0.96, theme.text1)}`};
opacity: ${({ isLoading }) => (isLoading ? 0.6 : 1)};
pointer-events: ${({ readonlyMode }) => (readonlyMode ? 'none' : '')};
border-radius: 16px;
border-radius: var(${UI.BORDER_RADIUS_NORMAL});
padding: 6px;
transition: background-color 0.15s ease-in-out;
max-width: 190px;
Expand Down
16 changes: 12 additions & 4 deletions apps/cowswap-frontend/src/cow-react/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Provider as AtomProvider } from 'jotai'
import { StrictMode } from 'react'

import { BlockNumberProvider } from '@cowprotocol/common-hooks'
import { isInjectedWidget } from '@cowprotocol/common-utils'
import { nodeRemoveChildFix } from '@cowprotocol/common-utils'
import { jotaiStore } from '@cowprotocol/core'
import { SnackbarsWidget } from '@cowprotocol/snackbars'
Expand Down Expand Up @@ -41,6 +42,7 @@ if (window.ethereum) {
}

const root = createRoot(document.getElementById('root')!)
const isInjectedWidgetMode = isInjectedWidget()

root.render(
<StrictMode>
Expand All @@ -56,12 +58,18 @@ root.render(
<BlockNumberProvider>
<WithLDProvider>
<Updaters />
<FeatureGuard featureFlag="cowFortuneEnabled">
<FortuneWidget />
</FeatureGuard>

{!isInjectedWidgetMode && (
<>
<FeatureGuard featureFlag="cowFortuneEnabled">
<FortuneWidget />
</FeatureGuard>
<AppziButton />
</>
)}

<Popups />
<SnackbarsWidget />
<AppziButton />
<App />
</WithLDProvider>
</BlockNumberProvider>
Expand Down
5 changes: 3 additions & 2 deletions apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { UI } from 'common/constants/theme'

// MOD imports
export const CopyIcon = styled(LinkStyledButton)`
--iconSize: var(${UI.ICON_SIZE_NORMAL});
color: ${({ theme }) => theme.text3};
flex-shrink: 0;
display: flex;
Expand All @@ -22,8 +23,8 @@ export const CopyIcon = styled(LinkStyledButton)`
font-size: 0.825rem;
border-radius: 50%;
background-color: transparent;
min-width: 20px;
min-height: 20px;
min-width: var(--iconSize);
min-height: var(--iconSize);
align-self: flex-end;
:hover,
:active,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React, { ErrorInfo, PropsWithChildren } from 'react'

import { sendError } from '@cowprotocol/analytics'
import { isInjectedWidget } from '@cowprotocol/common-utils'

import * as Sentry from '@sentry/react'
import styled from 'styled-components/macro'


import { ChunkLoadError } from 'legacy/components/ErrorBoundary/ChunkLoadError'
import { ErrorWithStackTrace } from 'legacy/components/ErrorBoundary/ErrorWithStackTrace'
import Footer from 'legacy/components/Footer'
Expand Down Expand Up @@ -128,6 +130,8 @@ export default class ErrorBoundary extends React.Component<PropsWithChildren, Er

return (
<AppWrapper>

{!isInjectedWidget() &&
<HeaderWrapper>
<HeaderRow marginRight="0">
<a href={Routes.HOME}>
Expand All @@ -137,6 +141,8 @@ export default class ErrorBoundary extends React.Component<PropsWithChildren, Er
</a>
</HeaderRow>
</HeaderWrapper>
}

<Wrapper>{isChunkLoadError ? <ChunkLoadError /> : <ErrorWithStackTrace error={error} />}</Wrapper>
<FooterWrapper>
<Footer />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react'

import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const'
import { TokenAmount } from '@cowprotocol/ui'
import { useWalletInfo } from '@cowprotocol/wallet'

import { useToggleAccountModal } from 'modules/account'
import { useNativeCurrencyBalances } from 'modules/tokens/hooks/useCurrencyBalance'
import { Web3Status } from 'modules/wallet/containers/Web3Status'

import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported'

import { Wrapper, BalanceText } from './styled'

interface AccountElementProps {
pendingActivities: string[]
isWidgetMode?: boolean
className?: string
}

export function AccountElement({ className, isWidgetMode, pendingActivities }: AccountElementProps) {
const { account, chainId } = useWalletInfo()
const isChainIdUnsupported = useIsProviderNetworkUnsupported()
const userEthBalance = useNativeCurrencyBalances(account ? [account] : [])?.[account ?? '']
const toggleAccountModal = useToggleAccountModal()
const nativeToken = NATIVE_CURRENCY_BUY_TOKEN[chainId].symbol

return (
<Wrapper className={className} active={!!account} onClick={() => account && toggleAccountModal()}>
{!isWidgetMode && account && !isChainIdUnsupported && userEthBalance && chainId && (
<BalanceText>
<TokenAmount amount={userEthBalance} tokenSymbol={{ symbol: nativeToken }} />
</BalanceText>
)}
<Web3Status pendingActivities={pendingActivities} />
</Wrapper>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { transparentize } from 'polished'
import { Text } from 'rebass'
import styled from 'styled-components/macro'

export const BalanceText = styled(Text)`
font-weight: 500;
font-size: 13px;
padding: 0 6px 0 12px;
min-width: initial;
${({ theme }) => theme.mediaWidth.upToExtraSmall`
display: none;
`};
${({ theme }) => theme.mediaWidth.upToMedium`
overflow: hidden;
max-width: 100px;
text-overflow: ellipsis;
`};
${({ theme }) => theme.mediaWidth.upToSmall`
display: none;
`};
`

export const Wrapper = styled.div<{ active: boolean }>`
display: flex;
flex-direction: row;
align-items: center;
background-color: ${({ theme, active }) => (!active ? theme.bg1 : theme.bg3)};
white-space: nowrap;
cursor: pointer;
background-color: ${({ theme, active }) => (!active ? theme.bg1 : theme.bg1)};
border-radius: 21px;
border: 2px solid transparent;
transition: border 0.2s ease-in-out;
pointer-events: auto;
width: auto;
:focus {
border: 1px solid blue;
}
&:hover {
border: 2px solid ${({ theme }) => transparentize(0.7, theme.text1)};
}
${({ theme }) => theme.mediaWidth.upToMedium`
height: 100%;
`}
${({ theme }) =>
theme.isInjectedWidgetMode &&
`
margin: 0 20px 0 auto!important;
border: 0!important;
`}
`
54 changes: 11 additions & 43 deletions apps/cowswap-frontend/src/legacy/components/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react'

import { toggleDarkModeAnalytics } from '@cowprotocol/analytics'
import { isInjectedWidget } from '@cowprotocol/common-utils'
import { addBodyClass, removeBodyClass } from '@cowprotocol/common-utils'
import { SupportedChainId as ChainId, SupportedChainId } from '@cowprotocol/cow-sdk'
import { TokenAmount } from '@cowprotocol/ui'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { useWalletInfo } from '@cowprotocol/wallet'

import SVG from 'react-inlinesvg'
Expand All @@ -16,24 +14,21 @@ import { LargeAndUp, upToLarge, upToMedium, upToSmall, useMediaQuery } from 'leg
import { useDarkModeManager } from 'legacy/state/user/hooks'
import { cowSwapLogo } from 'legacy/theme/cowSwapAssets'

import { OrdersPanel } from 'modules/account/containers/OrdersPanel'
import { useAccountModalState } from 'modules/account'
import { useInjectedWidgetParams } from 'modules/injectedWidget'
import { MainMenuContext } from 'modules/mainMenu'
import { MenuTree } from 'modules/mainMenu/pure/MenuTree'
import { useSwapRawState } from 'modules/swap/hooks/useSwapRawState'
import { useNativeCurrencyBalances } from 'modules/tokens/hooks/useCurrencyBalance'
import { useTradeState } from 'modules/trade/hooks/useTradeState'
import { getDefaultTradeRawState } from 'modules/trade/types/TradeRawState'
import { Web3Status } from 'modules/wallet/containers/Web3Status'

import { Routes } from 'common/constants/routes'
import { useCategorizeRecentActivity } from 'common/hooks/useCategorizeRecentActivity'
import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported'

import { AccountElement } from './AccountElement'
import MobileMenuIcon from './MobileMenuIcon'
import {
AccountElement,
BalanceText,
CustomLogoImg,
HeaderControls,
HeaderElement,
Expand All @@ -45,36 +40,19 @@ import {
Wrapper,
} from './styled'

const CHAIN_CURRENCY_LABELS: { [chainId in ChainId]?: string } = {
[ChainId.GNOSIS_CHAIN]: 'xDAI',
}

export default function Header() {
const { account, chainId } = useWalletInfo()
const isInjectedWidgetMode = isInjectedWidget()
const injectedWidgetParams = useInjectedWidgetParams()

const isChainIdUnsupported = useIsProviderNetworkUnsupported()

const { pendingActivity } = useCategorizeRecentActivity()
const userEthBalance = useNativeCurrencyBalances(account ? [account] : [])?.[account ?? '']
const nativeToken = CHAIN_CURRENCY_LABELS[chainId] || 'ETH'
const [darkMode, toggleDarkModeAux] = useDarkModeManager()
const toggleDarkMode = useCallback(() => {
toggleDarkModeAnalytics(!darkMode)
toggleDarkModeAux()
}, [toggleDarkModeAux, darkMode])
const swapRawState = useSwapRawState()
const { state: tradeState } = useTradeState()

const [isOrdersPanelOpen, setIsOrdersPanelOpen] = useState<boolean>(false)
const handleOpenOrdersPanel = () => {
account && setIsOrdersPanelOpen(true)
}
const handleCloseOrdersPanel = () => {
setIsOrdersPanelOpen(false)
!isOrdersPanelOpen && removeBodyClass('noScroll')
}
const { isOpen: isAccountModalOpen } = useAccountModalState()

const navigate = useNavigate()

Expand Down Expand Up @@ -120,15 +98,15 @@ export default function Header() {
// Toggle the 'noScroll' class on body, whenever the mobile menu or orders panel is open.
// This removes the inner scrollbar on the page body, to prevent showing double scrollbars.
useEffect(() => {
isMobileMenuOpen || isOrdersPanelOpen ? addBodyClass('noScroll') : removeBodyClass('noScroll')
}, [isOrdersPanelOpen, isMobileMenuOpen, isUpToLarge, isUpToMedium, isUpToSmall, isLargeAndUp])
isMobileMenuOpen || isAccountModalOpen ? addBodyClass('noScroll') : removeBodyClass('noScroll')
}, [isAccountModalOpen, isMobileMenuOpen, isUpToLarge, isUpToMedium, isUpToSmall, isLargeAndUp])

return (
<Wrapper isMobileMenuOpen={isMobileMenuOpen}>
<HeaderModWrapper>
<HeaderRow>
{!injectedWidgetParams.hideLogo && (
<Title href={isInjectedWidgetMode ? undefined : Routes.HOME} isMobileMenuOpen={isMobileMenuOpen}>
<Title href={Routes.HOME} isMobileMenuOpen={isMobileMenuOpen}>
<UniIcon>
<LogoImage isMobileMenuOpen={isMobileMenuOpen}>
{injectedWidgetParams.logoUrl ? (
Expand All @@ -140,14 +118,14 @@ export default function Header() {
</UniIcon>
</Title>
)}
{!isInjectedWidgetMode && <MenuTree isMobileMenuOpen={isMobileMenuOpen} context={menuContext} />}
{<MenuTree isMobileMenuOpen={isMobileMenuOpen} context={menuContext} />}
</HeaderRow>

<HeaderControls>
{!injectedWidgetParams.hideNetworkSelector && <NetworkSelector />}

<HeaderElement>
{!isInjectedWidgetMode && !isChainIdUnsupported && (
{!isChainIdUnsupported && (
<CowBalanceButton
onClick={() => navigate('/account')}
account={account}
Expand All @@ -156,21 +134,11 @@ export default function Header() {
/>
)}

<AccountElement active={!!account} onClick={handleOpenOrdersPanel}>
{account && !isChainIdUnsupported && userEthBalance && chainId && (
<BalanceText>
<TokenAmount amount={userEthBalance} tokenSymbol={{ symbol: nativeToken }} />
</BalanceText>
)}
<Web3Status pendingActivities={pendingActivity} />
</AccountElement>
<AccountElement pendingActivities={pendingActivity} />
</HeaderElement>
</HeaderControls>

{isUpToLarge && !isInjectedWidgetMode && (
<MobileMenuIcon isMobileMenuOpen={isMobileMenuOpen} onClick={handleMobileMenuOnClick} />
)}
{isOrdersPanelOpen && <OrdersPanel handleCloseOrdersPanel={handleCloseOrdersPanel} />}
{isUpToLarge && <MobileMenuIcon isMobileMenuOpen={isMobileMenuOpen} onClick={handleMobileMenuOnClick} />}
</HeaderModWrapper>
</Wrapper>
)
Expand Down
Loading

0 comments on commit 1a2c1de

Please sign in to comment.