Skip to content

Commit

Permalink
feat: iterate on configurator (#3364)
Browse files Browse the repository at this point in the history
* feat: iterate on configurator

* feat: move embed code button (#3365)

* feat: move embed code button

* feat: add snackbar click to copy (#3366)

* feat: add snackbar click to copy

* feat: snackbar set timeout to 3s

* feat: revert click away and font fix

* feat: embed code button styling

* feat: embed code button refactor

* feat: remove comments
  • Loading branch information
fairlighteth authored Nov 9, 2023
1 parent c36beb6 commit c4ba4bb
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 82 deletions.
6 changes: 3 additions & 3 deletions apps/widget-configurator/src/app/analytics.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { sendEvent, Category } from '@cowprotocol/analytics'

export function connectWalletToConfigurator() {
export function connectWalletToConfiguratorGA() {
sendEvent({
category: Category.WIDGET_CONFIGURATOR,
action: 'Connect wallet',
})
}

export function viewEmbedCode() {
export function viewEmbedCodeGA() {
sendEvent({
category: Category.WIDGET_CONFIGURATOR,
action: 'View code',
})
}

export function copyEmbedCode() {
export function copyEmbedCodeGA() {
sendEvent({
category: Category.WIDGET_CONFIGURATOR,
action: 'Copy code',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useState } from 'react'

export function useEmbedDialogState(initialOpen = false) {
const [open, setOpen] = useState(initialOpen)

const handleOpen = () => setOpen(true)
const handleClose = () => setOpen(false)

return {
dialogOpen: open,
handleDialogClose: handleClose,
handleDialogOpen: handleOpen,
}
}
112 changes: 78 additions & 34 deletions apps/widget-configurator/src/app/configurator/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@ import { useContext, useEffect, useState } from 'react'
import { TradeType } from '@cowprotocol/widget-lib'
import { CowSwapWidget } from '@cowprotocol/widget-react'

import ChromeReaderModeIcon from '@mui/icons-material/ChromeReaderMode'
import CodeIcon from '@mui/icons-material/Code'
import EditIcon from '@mui/icons-material/Edit'
import KeyboardDoubleArrowLeftIcon from '@mui/icons-material/KeyboardDoubleArrowLeft'
import LanguageIcon from '@mui/icons-material/Language'
import Box from '@mui/material/Box'
import Divider from '@mui/material/Divider'
import Drawer from '@mui/material/Drawer'
import Link from '@mui/material/Link'
import Fab from '@mui/material/Fab'
import List from '@mui/material/List'
import ListItemButton from '@mui/material/ListItemButton'
import ListItemIcon from '@mui/material/ListItemIcon'
import ListItemText from '@mui/material/ListItemText'
import Typography from '@mui/material/Typography'
import { useAccount, useNetwork } from 'wagmi'

Expand All @@ -16,22 +25,16 @@ import { CurrentTradeTypeControl } from './controls/CurrentTradeTypeControl'
import { NetworkControl, NetworkOption, NetworkOptions } from './controls/NetworkControl'
import { ThemeControl } from './controls/ThemeControl'
import { TradeModesControl } from './controls/TradeModesControl'
import { useEmbedDialogState } from './hooks/useEmbedDialogState'
import { useProvider } from './hooks/useProvider'
import { useSyncWidgetNetwork } from './hooks/useSyncWidgetNetwork'
import { useWidgetParamsAndSettings } from './hooks/useWidgetParamsAndSettings'
import {
ContentStyled,
DrawerStyled,
LinksWrapper,
ShowDrawerButton,
WalletConnectionWrapper,
WrapperStyled,
} from './styled'
import { ContentStyled, DrawerStyled, WalletConnectionWrapper, WrapperStyled } from './styled'
import { ConfiguratorState } from './types'

import { ColorModeContext } from '../../theme/ColorModeContext'
import { web3Modal } from '../../wagmiConfig'
import { connectWalletToConfigurator } from '../analytics'
import { connectWalletToConfiguratorGA } from '../analytics'
import { EmbedDialog } from '../embedDialog'

const DEFAULT_STATE = {
Expand Down Expand Up @@ -67,6 +70,14 @@ export function Configurator({ title }: { title: string }) {
const [buyToken] = buyTokenState
const [buyTokenAmount] = buyTokenAmountState

const { dialogOpen, handleDialogClose, handleDialogOpen } = useEmbedDialogState()

const LINKS = [
{ icon: <CodeIcon />, label: 'View embed code', onClick: () => handleDialogOpen() },
{ icon: <LanguageIcon />, label: 'Widget web', url: `https://cow.fi/widget/?${UTM_PARAMS}` },
{ icon: <ChromeReaderModeIcon />, label: 'Developer docs', url: `https://docs.cow.fi/?${UTM_PARAMS}` },
]

const { isDisconnected, isConnected } = useAccount()
const network = useNetwork()

Expand Down Expand Up @@ -98,40 +109,36 @@ export function Configurator({ title }: { title: string }) {
// Fire an event to GA when user connect a wallet
useEffect(() => {
if (isConnected) {
connectWalletToConfigurator()
connectWalletToConfiguratorGA()
}
}, [isConnected])

return (
<Box sx={WrapperStyled}>
{!isDrawerOpen && (
<button onClick={() => setIsDrawerOpen(true)} style={ShowDrawerButton(mode)}>
✏️
</button>
<Fab
size="medium"
color="secondary"
aria-label="edit"
onClick={(e) => {
e.stopPropagation()
setIsDrawerOpen(true)
}}
style={{ position: 'fixed', bottom: '1.6rem', left: '1.6rem' }}
>
<EditIcon />
</Fab>
)}

<Drawer sx={DrawerStyled} variant="persistent" anchor="left" open={isDrawerOpen}>
<Typography variant="h6" sx={{ width: '100%', textAlign: 'center', margin: '0 0 1.6rem', fontWeight: 'bold' }}>
<Typography variant="h6" sx={{ width: '100%', textAlign: 'center', margin: '0 auto 1rem', fontWeight: 'bold' }}>
{title}
</Typography>

<div style={LinksWrapper}>
<Link variant="body2" href={`https://cow.fi/widget/?${UTM_PARAMS}`}>
Website
</Link>
{/*TODO: add link to the widget page docs*/}
<Link variant="body2" href={`https://docs.cow.fi/?${UTM_PARAMS}`}>
Docs
</Link>
</div>

<Divider variant="middle">Wallet</Divider>

<div style={WalletConnectionWrapper}>
<w3m-button />
</div>

<Divider variant="middle">General</Divider>

<ThemeControl />

<TradeModesControl state={tradeModesState} />
Expand All @@ -150,22 +157,59 @@ export function Configurator({ title }: { title: string }) {

<CurrencyInputControl label="Buy token" tokenIdState={buyTokenState} tokenAmountState={buyTokenAmountState} />

<Divider variant="middle" />
{isDrawerOpen && (
<Fab
size="small"
color="primary"
aria-label="hide drawer"
onClick={() => setIsDrawerOpen(false)}
style={{ position: 'fixed', top: '1.3rem', left: '26.7rem' }}
>
<KeyboardDoubleArrowLeftIcon />
</Fab>
)}

<Link href="#hide" onClick={() => setIsDrawerOpen(false)}>
Hide drawer
</Link>
<List
sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}
component="nav"
aria-labelledby="nested-list-subheader"
>
{LINKS.map(({ label, icon, url, onClick }) => (
<ListItemButton
key={label}
component={onClick ? 'button' : 'a'}
href={onClick ? undefined : url}
target={onClick ? undefined : '_blank'}
rel={onClick ? undefined : 'noopener noreferrer'}
onClick={onClick}
>
<ListItemIcon>{icon}</ListItemIcon>
<ListItemText primary={label} />
</ListItemButton>
))}
</List>
</Drawer>

<Box sx={ContentStyled}>
{params && (
<>
<EmbedDialog params={params} />
<EmbedDialog params={params} open={dialogOpen} handleClose={handleDialogClose} />
<br />
<CowSwapWidget provider={provider} params={params} />
</>
)}
</Box>

<Fab
color="primary"
size="large"
variant="extended"
sx={{ position: 'fixed', bottom: '2rem', right: '1.6rem' }}
onClick={() => handleDialogOpen()}
>
<CodeIcon sx={{ mr: 1 }} />
View Embed Code
</Fab>
</Box>
)
}
25 changes: 2 additions & 23 deletions apps/widget-configurator/src/app/configurator/styled.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { CSSProperties } from 'react'

import { Theme } from '@mui/material/styles'

import type { PaletteMode } from '@mui/material'

export const WrapperStyled = { display: 'flex', flexFlow: 'column wrap', width: '100%' }

export const DrawerStyled = (theme: Theme) => ({
width: '29rem',
flexShrink: 0,

'& .MuiDrawer-paper': {
width: '29rem',
boxSizing: 'border-box',
Expand Down Expand Up @@ -42,23 +39,5 @@ export const ContentStyled = {
export const WalletConnectionWrapper = {
display: 'flex',
justifyContent: 'center',
}

export const ShowDrawerButton: (mode: PaletteMode) => CSSProperties = (mode: PaletteMode) => ({
borderRadius: '50%',
width: '60px',
height: '60px',
position: 'fixed',
left: '20px',
bottom: '20px',
background: mode === 'dark' ? 'rgb(63 162 255 / 71%)' : '#fff',
border: 0,
fontSize: '24px',
cursor: 'pointer',
})

export const LinksWrapper = {
display: 'flex',
justifyContent: 'center',
gap: '15px',
margin: '0 auto 1rem',
}
54 changes: 32 additions & 22 deletions apps/widget-configurator/src/app/embedDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { SyntheticEvent, useEffect, useMemo, useRef, useState } from 'react'
import React, { SyntheticEvent, useEffect, useMemo, useRef, useState } from 'react'

import { CowSwapWidgetProps } from '@cowprotocol/widget-react'

import MuiAlert, { AlertProps } from '@mui/material/Alert'
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import Dialog, { DialogProps } from '@mui/material/Dialog'
import DialogActions from '@mui/material/DialogActions'
import DialogContent from '@mui/material/DialogContent'
import DialogTitle from '@mui/material/DialogTitle'
import Snackbar from '@mui/material/Snackbar'
import Tab from '@mui/material/Tab'
import Tabs from '@mui/material/Tabs'
import SyntaxHighlighter from 'react-syntax-highlighter'
Expand All @@ -18,7 +20,11 @@ import { reactExample } from './utils/reactExample'
import { vanilaNpmExample } from './utils/vanilaNpmExample'
import { vanillaNoDepsExample } from './utils/vanillaNoDepsExample'

import { copyEmbedCode, viewEmbedCode } from '../analytics'
import { copyEmbedCodeGA, viewEmbedCodeGA } from '../analytics'

const Alert = React.forwardRef<HTMLDivElement, AlertProps>(function Alert(props, ref) {
return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />
})

function a11yProps(index: number) {
return {
Expand All @@ -29,28 +35,33 @@ function a11yProps(index: number) {

export interface EmbedDialogProps {
params: CowSwapWidgetProps['params']
open: boolean
handleClose: () => void
}

export function EmbedDialog({ params }: EmbedDialogProps) {
const [open, setOpen] = useState(false)
export function EmbedDialog({ params, open, handleClose }: EmbedDialogProps) {
const [scroll, setScroll] = useState<DialogProps['scroll']>('paper')

const [currentTab, setCurrentTab] = useState(0)
const descriptionElementRef = useRef<HTMLElement>(null)

const handleClickOpen = (scrollType: DialogProps['scroll']) => () => {
setOpen(true)
setScroll(scrollType)
viewEmbedCode()
const [snackbarOpen, setSnackbarOpen] = useState(false)
const handleCopy = () => {
navigator.clipboard.writeText(code)
copyEmbedCodeGA()
setSnackbarOpen(true)
}

const handleClose = () => {
setOpen(false)
const handleSnackbarClose = (event?: React.SyntheticEvent | Event, reason?: string) => {
if (reason === 'clickaway') {
return
}
setSnackbarOpen(false)
}

const descriptionElementRef = useRef<HTMLElement>(null)

useEffect(() => {
if (open) {
setScroll('paper')
viewEmbedCodeGA()
const { current: descriptionElement } = descriptionElementRef
if (descriptionElement !== null) {
descriptionElement.focus()
Expand All @@ -66,23 +77,16 @@ export function EmbedDialog({ params }: EmbedDialogProps) {
return ''
}, [currentTab, params])

const handleCopy = () => {
navigator.clipboard.writeText(code)
copyEmbedCode()
}

return (
<div>
<Button variant="outlined" onClick={handleClickOpen('paper')}>{`View Embed Code </>`}</Button>
{/* <Button onClick={handleClickOpen('body')}>scroll=body</Button> */}
<Dialog
fullWidth
maxWidth="lg"
open={open}
onClose={handleClose}
scroll={scroll}
aria-labelledby="scroll-dialog-title"
aria-describedby="scroll-dialog-description"
open={open}
onClose={handleClose}
>
<DialogTitle id="scroll-dialog-title">Snippet for CoW Widget</DialogTitle>

Expand Down Expand Up @@ -114,6 +118,12 @@ export function EmbedDialog({ params }: EmbedDialogProps) {
<Button onClick={handleCopy}>Copy</Button>
</DialogActions>
</Dialog>

<Snackbar open={snackbarOpen} autoHideDuration={3000} onClose={handleSnackbarClose}>
<Alert onClose={handleSnackbarClose} severity="success" sx={{ width: '100%' }}>
Successfully copied to clipboard!
</Alert>
</Snackbar>
</div>
)
}
Loading

0 comments on commit c4ba4bb

Please sign in to comment.