SlippageList.tsx
1 import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/outline'; 2 import { Trans } from '@lingui/macro'; 3 import { 4 Box, 5 Button, 6 Divider, 7 ListItemIcon, 8 ListItemText, 9 Menu, 10 MenuItem, 11 SvgIcon, 12 Typography, 13 } from '@mui/material'; 14 import * as React from 'react'; 15 import { SlippageTooltip } from 'src/components/infoTooltips/SlippageTooltip'; 16 import { useRootStore } from 'src/store/root'; 17 import { GENERAL } from 'src/utils/mixPanelEvents'; 18 19 import Paraswap from '/public/icons/other/paraswap.svg'; 20 21 interface ListSlippageButtonProps { 22 setSlippage: (value: string) => void; 23 selectedSlippage: string; 24 slippageTooltipHeader?: React.ReactNode; 25 } 26 27 export const ListSlippageButton = ({ 28 setSlippage, 29 selectedSlippage, 30 slippageTooltipHeader, 31 }: ListSlippageButtonProps) => { 32 const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); 33 const open = Boolean(anchorEl); 34 const trackEvent = useRootStore((store) => store.trackEvent); 35 36 const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => { 37 setAnchorEl(event.currentTarget); 38 }; 39 const handleClose = () => { 40 setAnchorEl(null); 41 }; 42 43 const values: string[] = ['0.1', '0.5', '1']; 44 45 return ( 46 <> 47 <Button 48 variant="text" 49 onClick={handleClick} 50 size="medium" 51 endIcon={ 52 <SlippageTooltip 53 headerContent={slippageTooltipHeader} 54 text={ 55 <Box sx={{ display: 'flex', alignItems: 'center' }}> 56 <Trans> 57 <Typography color="text.secondary" variant="description"> 58 Slippage tolerance{' '} 59 </Typography> 60 <Typography color="text.main" variant="secondary14" sx={{ px: '4px' }}> 61 {selectedSlippage}%{' '} 62 </Typography> 63 <SvgIcon sx={{ fontSize: '14px !important', mr: '4px' }}> 64 {open ? <ChevronUpIcon /> : <ChevronDownIcon />} 65 </SvgIcon> 66 </Trans> 67 </Box> 68 } 69 variant="secondary14" 70 /> 71 } 72 disabled={false} 73 data-cy={`slippageButton_${selectedSlippage}`} 74 /> 75 76 <Menu 77 anchorEl={anchorEl} 78 open={open} 79 onClose={handleClose} 80 MenuListProps={{ 81 'aria-labelledby': 'basic-button', 82 }} 83 keepMounted={true} 84 data-cy={`slippageMenu_${selectedSlippage}`} 85 > 86 <Box sx={{ px: '16px', py: '12px' }}> 87 <Typography variant="secondary12" color="text.secondary"> 88 <Trans>Select slippage tolerance</Trans> 89 </Typography> 90 </Box> 91 92 {values.map((slippageValue) => { 93 const selected = slippageValue === selectedSlippage; 94 95 return ( 96 <MenuItem 97 key={slippageValue} 98 selected={selected} 99 value={slippageValue} 100 onClick={() => { 101 setSlippage(slippageValue); 102 trackEvent(GENERAL.SET_SLIPPAGE, { amount: slippageValue }); 103 handleClose(); 104 }} 105 > 106 <ListItemText primaryTypographyProps={{ variant: 'subheader1' }}> 107 {slippageValue}% 108 </ListItemText> 109 <ListItemIcon> 110 <SvgIcon>{selected && <CheckIcon />}</SvgIcon> 111 </ListItemIcon> 112 </MenuItem> 113 ); 114 })} 115 116 <Divider /> 117 <Box sx={{ px: '16px', py: '12px', display: 'inline-flex', alignItems: 'center' }}> 118 <Typography 119 variant="secondary12" 120 color="text.secondary" 121 sx={{ display: 'flex', alignItems: 'center' }} 122 > 123 <Trans>Powered by</Trans> 124 <SvgIcon 125 sx={{ 126 fontSize: '20px', 127 width: '20px', 128 color: '#2669F5', 129 position: 'relative', 130 top: '5px', 131 left: '5px', 132 }} 133 > 134 <Paraswap /> 135 </SvgIcon> 136 </Typography> 137 <Typography variant="main12" color="text.secondary"> 138 Paraswap 139 </Typography> 140 </Box> 141 </Menu> 142 </> 143 ); 144 };