diff --git a/apps/widget-configurator/src/app/analytics.ts b/apps/widget-configurator/src/app/analytics.ts index 6504d10783..990d6393c1 100644 --- a/apps/widget-configurator/src/app/analytics.ts +++ b/apps/widget-configurator/src/app/analytics.ts @@ -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', diff --git a/apps/widget-configurator/src/app/configurator/hooks/useEmbedDialogState.ts b/apps/widget-configurator/src/app/configurator/hooks/useEmbedDialogState.ts new file mode 100644 index 0000000000..9c2b18c0af --- /dev/null +++ b/apps/widget-configurator/src/app/configurator/hooks/useEmbedDialogState.ts @@ -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, + } +} diff --git a/apps/widget-configurator/src/app/configurator/index.tsx b/apps/widget-configurator/src/app/configurator/index.tsx index 531d044451..476cbf28ad 100644 --- a/apps/widget-configurator/src/app/configurator/index.tsx +++ b/apps/widget-configurator/src/app/configurator/index.tsx @@ -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' @@ -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 = { @@ -67,6 +70,14 @@ export function Configurator({ title }: { title: string }) { const [buyToken] = buyTokenState const [buyTokenAmount] = buyTokenAmountState + const { dialogOpen, handleDialogClose, handleDialogOpen } = useEmbedDialogState() + + const LINKS = [ + { icon: , label: 'View embed code', onClick: () => handleDialogOpen() }, + { icon: , label: 'Widget web', url: `https://cow.fi/widget/?${UTM_PARAMS}` }, + { icon: , label: 'Developer docs', url: `https://docs.cow.fi/?${UTM_PARAMS}` }, + ] + const { isDisconnected, isConnected } = useAccount() const network = useNetwork() @@ -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 ( {!isDrawerOpen && ( - + { + e.stopPropagation() + setIsDrawerOpen(true) + }} + style={{ position: 'fixed', bottom: '1.6rem', left: '1.6rem' }} + > + + )} + - + {title} -
- - Website - - {/*TODO: add link to the widget page docs*/} - - Docs - -
- - Wallet -
- General - @@ -150,22 +157,59 @@ export function Configurator({ title }: { title: string }) { - + {isDrawerOpen && ( + setIsDrawerOpen(false)} + style={{ position: 'fixed', top: '1.3rem', left: '26.7rem' }} + > + + + )} - setIsDrawerOpen(false)}> - Hide drawer - + + {LINKS.map(({ label, icon, url, onClick }) => ( + + {icon} + + + ))} +
{params && ( <> - +
)}
+ + handleDialogOpen()} + > + + View Embed Code +
) } diff --git a/apps/widget-configurator/src/app/configurator/styled.ts b/apps/widget-configurator/src/app/configurator/styled.ts index b7a683c4b2..92321ff78a 100644 --- a/apps/widget-configurator/src/app/configurator/styled.ts +++ b/apps/widget-configurator/src/app/configurator/styled.ts @@ -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', @@ -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', } diff --git a/apps/widget-configurator/src/app/embedDialog/index.tsx b/apps/widget-configurator/src/app/embedDialog/index.tsx index af861a87bd..8d99ce1921 100644 --- a/apps/widget-configurator/src/app/embedDialog/index.tsx +++ b/apps/widget-configurator/src/app/embedDialog/index.tsx @@ -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' @@ -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(function Alert(props, ref) { + return +}) function a11yProps(index: number) { return { @@ -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('paper') - const [currentTab, setCurrentTab] = useState(0) + const descriptionElementRef = useRef(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(null) - useEffect(() => { if (open) { + setScroll('paper') + viewEmbedCodeGA() const { current: descriptionElement } = descriptionElementRef if (descriptionElement !== null) { descriptionElement.focus() @@ -66,23 +77,16 @@ export function EmbedDialog({ params }: EmbedDialogProps) { return '' }, [currentTab, params]) - const handleCopy = () => { - navigator.clipboard.writeText(code) - copyEmbedCode() - } - return (
- - {/* */} Snippet for CoW Widget @@ -114,6 +118,12 @@ export function EmbedDialog({ params }: EmbedDialogProps) { + + + + Successfully copied to clipboard! + +
) } diff --git a/apps/widget-configurator/src/main.tsx b/apps/widget-configurator/src/main.tsx index cba050ffbe..564fe8c4cf 100644 --- a/apps/widget-configurator/src/main.tsx +++ b/apps/widget-configurator/src/main.tsx @@ -1,6 +1,7 @@ import { StrictMode, useMemo } from 'react' import { CssBaseline, GlobalStyles } from '@mui/material' +import 'inter-ui' import Box from '@mui/material/Box' import { createTheme, PaletteOptions, ThemeProvider } from '@mui/material/styles' import { createRoot } from 'react-dom/client' @@ -30,6 +31,28 @@ function Root() { return createTheme({ palette, typography: commonTypography, + components: { + MuiCssBaseline: { + styleOverrides: { + '@global': { + html: { + fontFamily: '"Inter var", "Inter", sans-serif', + }, + body: { + fontFamily: '"Inter var", "Inter", sans-serif', + }, + '@supports (font-variation-settings: normal)': { + html: { + fontFamily: '"Inter var", "Inter", sans-serif', + }, + body: { + fontFamily: '"Inter var", "Inter", sans-serif', + }, + }, + }, + }, + }, + }, }) }, [mode]) diff --git a/apps/widget-configurator/src/theme/commonTypography.ts b/apps/widget-configurator/src/theme/commonTypography.ts index c513bc4796..7678625399 100644 --- a/apps/widget-configurator/src/theme/commonTypography.ts +++ b/apps/widget-configurator/src/theme/commonTypography.ts @@ -1,6 +1,7 @@ import { TypographyOptions } from '@mui/material/styles/createTypography' export const commonTypography: TypographyOptions = { + fontFamily: '"Inter var", "Inter", sans-serif', htmlFontSize: 10, button: { textTransform: 'none' as const,