Skip to content

Commit 8b52a92

Browse files
committed
% selector in asset input
1 parent 71e1637 commit 8b52a92

File tree

4 files changed

+135
-4
lines changed

4 files changed

+135
-4
lines changed

src/components/transactions/Swap/actions/ActionsSkeleton.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ const stateToLoadingType = (state: SwapState): LoadingType => {
1313

1414
export const ActionsLoading: React.FC<{ state: SwapState }> = ({ state }) => {
1515
const loadingType = stateToLoadingType(state);
16-
17-
// Timer logic for updating the loading text after 2 seconds when loadingType is 'quote'
1816
const [quoteTimeElapsed, setQuoteTimeElapsed] = useState(false);
1917
const timerRef = useRef<NodeJS.Timeout | null>(null);
2018

19+
// Timer logic for updating the loading text after 2 seconds when loadingType is 'quote'
20+
// Trick to change quote loading trick to make it feel more smooth
2121
useEffect(() => {
2222
if (loadingType === 'quote') {
2323
setQuoteTimeElapsed(false);

src/components/transactions/Swap/inputs/LimitOrderInputs.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ export const LimitOrderInputs = ({
6363
assets={swapState.inputAssets}
6464
value={state.inputAmount}
6565
onChange={swapState.handleInputChange}
66+
onClear={() =>
67+
setState({
68+
inputAmount: '',
69+
debouncedInputAmount: '',
70+
inputAmountUSD: '',
71+
})
72+
}
6673
usdValue={state.inputAmountUSD || '0'}
6774
onSelect={swapState.handleSelectedInputToken}
6875
selectedAsset={state.sourceToken}
@@ -163,6 +170,13 @@ export const LimitOrderInputs = ({
163170
onChange={(value) => {
164171
swapState.handleOutputChange(value);
165172
}}
173+
onClear={() =>
174+
setState({
175+
outputAmount: '',
176+
debouncedOutputAmount: '',
177+
outputAmountUSD: '',
178+
})
179+
}
166180
onSelect={swapState.handleSelectedOutputToken}
167181
disableInput={false}
168182
selectedAsset={state.destinationToken}

src/components/transactions/Swap/inputs/MarketOrderInputs.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const MarketOrderInputs = ({
1515
params,
1616
state,
1717
swapState,
18+
setState,
1819
}: {
1920
params: SwapParams;
2021
state: SwapState;
@@ -64,6 +65,20 @@ export const MarketOrderInputs = ({
6465
assets={swapState.inputAssets}
6566
value={state.inputAmount}
6667
onChange={swapState.handleInputChange}
68+
onClear={() =>
69+
setState({
70+
inputAmount: '',
71+
debouncedInputAmount: '',
72+
inputAmountUSD: '',
73+
outputAmount: '',
74+
debouncedOutputAmount: '',
75+
outputAmountUSD: '',
76+
swapRate: undefined,
77+
ratesLoading: false,
78+
error: undefined,
79+
warnings: [],
80+
})
81+
}
6782
usdValue={state.inputAmountUSD.toString() || '0'}
6883
onSelect={swapState.handleSelectedInputToken}
6984
selectedAsset={state.sourceToken}

src/components/transactions/Swap/inputs/primitives/SwapAssetInput.tsx

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { valueToBigNumber } from '@aave/math-utils';
12
import { isAddress } from '@ethersproject/address';
23
import { formatUnits } from '@ethersproject/units';
34
import { ExclamationIcon } from '@heroicons/react/outline';
@@ -12,7 +13,10 @@ import {
1213
InputBase,
1314
ListItemText,
1415
MenuItem,
16+
Popover,
1517
SvgIcon,
18+
ToggleButton,
19+
ToggleButtonGroup,
1620
Typography,
1721
useTheme,
1822
} from '@mui/material';
@@ -64,6 +68,7 @@ export interface AssetInputProps {
6468
usdValue: string;
6569
chainId: number;
6670
onChange?: (value: string) => void;
71+
onClear?: () => void;
6772
disabled?: boolean;
6873
disableInput?: boolean;
6974
onSelect?: (asset: SwappableToken) => void;
@@ -84,6 +89,7 @@ export const SwitchAssetInput = ({
8489
value,
8590
usdValue,
8691
onChange,
92+
onClear,
8793
disabled,
8894
disableInput,
8995
onSelect,
@@ -281,7 +287,11 @@ export const SwitchAssetInput = ({
281287
},
282288
}}
283289
onClick={() => {
284-
onChange && onChange('');
290+
if (onClear) {
291+
onClear();
292+
} else {
293+
onChange && onChange('');
294+
}
285295
}}
286296
disabled={disabled}
287297
>
@@ -530,10 +540,20 @@ export const SwitchAssetInput = ({
530540
sx={{ ml: 1 }}
531541
/>
532542
</Typography>
543+
{!disableInput && (
544+
<PercentSelector
545+
disabled={disabled || Number(selectedAsset.balance) === 0}
546+
onSelectPercent={(fraction) => {
547+
const maxBase = forcedMaxValue || selectedAsset.balance || '0';
548+
const next = valueToBigNumber(maxBase).multipliedBy(fraction).toString();
549+
onChange && onChange(next);
550+
}}
551+
/>
552+
)}
533553
{!disableInput && (
534554
<Button
535555
size="small"
536-
sx={{ minWidth: 0, ml: '7px', p: 0 }}
556+
sx={{ minWidth: 0, ml: '1px', pt: 0, pb: 0, mr: '-5px' }}
537557
onClick={() => {
538558
onChange && onChange(forcedMaxValue || '-1');
539559
}}
@@ -555,3 +575,85 @@ export const SwitchAssetInput = ({
555575
</Box>
556576
);
557577
};
578+
579+
const PercentSelector = ({
580+
disabled,
581+
onSelectPercent,
582+
}: {
583+
disabled?: boolean;
584+
onSelectPercent: (fraction: number) => void;
585+
}) => {
586+
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
587+
const open = Boolean(anchorEl);
588+
589+
const handleOpen = (event: React.MouseEvent<HTMLButtonElement>) => {
590+
if (disabled) return;
591+
setAnchorEl(event.currentTarget);
592+
};
593+
const handleClose = () => setAnchorEl(null);
594+
595+
const handlePick = (fraction: number) => {
596+
onSelectPercent(fraction);
597+
handleClose();
598+
};
599+
600+
return (
601+
<>
602+
<Button
603+
size="small"
604+
sx={{ minWidth: 0, ml: '6px', py: 0, fontSize: '12px' }}
605+
onClick={handleOpen}
606+
disabled={disabled}
607+
>
608+
<Trans>%</Trans>
609+
</Button>
610+
<Popover
611+
open={open}
612+
anchorEl={anchorEl}
613+
onClose={handleClose}
614+
anchorOrigin={{ vertical: 'top', horizontal: 'left' }}
615+
transformOrigin={{ vertical: 'bottom', horizontal: 'left' }}
616+
PaperProps={{
617+
sx: {
618+
p: 1,
619+
backgroundColor: 'background.surface',
620+
border: '1px solid',
621+
borderColor: 'divider',
622+
},
623+
}}
624+
>
625+
<Box sx={{ display: 'flex', alignItems: 'center', p: 0.5 }}>
626+
<ToggleButtonGroup
627+
exclusive
628+
sx={{
629+
backgroundColor: 'background.surface',
630+
borderRadius: '6px',
631+
borderColor: 'background.surface',
632+
}}
633+
onChange={(_, v) => v && handlePick(v)}
634+
>
635+
{[0.25, 0.5, 0.75].map((fraction) => (
636+
<ToggleButton
637+
key={fraction}
638+
value={fraction}
639+
sx={{
640+
borderRadius: 1,
641+
py: 0.5,
642+
px: 1,
643+
borderWidth: 2,
644+
'&.Mui-selected': {
645+
backgroundColor: 'background.paper',
646+
},
647+
}}
648+
>
649+
<Typography variant="subheader2" color="primary.main">
650+
{Math.round(fraction * 100)}%
651+
</Typography>
652+
</ToggleButton>
653+
))}
654+
</ToggleButtonGroup>
655+
</Box>
656+
</Popover>
657+
</>
658+
);
659+
};

0 commit comments

Comments
 (0)