Skip to content

Commit

Permalink
fix: prevent scroll adjusting number inputs (#1280)
Browse files Browse the repository at this point in the history
* fix: blur number inputs `onWheel` events

* fix: remove duplicate attribute

* fix: use `inputMode` and `pattern`

* fix: use `type` attribute + replace more fields

* fix: missing field

* fix: remove attribute
  • Loading branch information
iamacook authored Dec 6, 2022
1 parent edce31f commit 637fd61
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 29 deletions.
31 changes: 31 additions & 0 deletions src/components/common/NumberField/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { TextField } from '@mui/material'
import { forwardRef, useRef } from 'react'
import type { TextFieldProps } from '@mui/material'
import type { ReactElement } from 'react'

const NumberField = forwardRef<HTMLInputElement, TextFieldProps>(({ inputProps, ...props }, ref): ReactElement => {
const inputRef = useRef<HTMLInputElement>()

const handleBlur = () => {
inputRef.current?.blur()
}

return (
<TextField
type="number"
autoComplete="off"
inputRef={inputRef}
onWheel={handleBlur}
ref={ref}
inputProps={{
step: 'any',
...inputProps,
}}
{...props}
/>
)
})

NumberField.displayName = 'NumberField'

export default NumberField
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
MenuItem,
Select,
Switch,
TextField,
Typography,
RadioGroup,
FormControlLabel,
Expand All @@ -23,6 +22,7 @@ import useChainId from '@/hooks/useChainId'
import { getResetTimeOptions } from '@/components/transactions/TxDetails/TxData/SpendingLimits'
import { defaultAbiCoder } from '@ethersproject/abi'
import { parseUnits } from 'ethers/lib/utils'
import NumberField from '@/components/common/NumberField'

export type NewSpendingLimitData = {
beneficiary: string
Expand Down Expand Up @@ -107,10 +107,9 @@ export const SpendingLimitForm = ({ data, onSubmit }: Props) => {
</FormControl>

<FormControl fullWidth>
<TextField
<NumberField
label={errors.amount?.message || 'Amount'}
error={!!errors.amount}
autoComplete="off"
required
{...register('amount', {
required: true,
Expand Down
6 changes: 3 additions & 3 deletions src/components/transactions/TxFilterForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import RadioGroup from '@mui/material/RadioGroup'
import FormLabel from '@mui/material/FormLabel'
import FormControlLabel from '@mui/material/FormControlLabel'
import Radio from '@mui/material/Radio'
import TextField from '@mui/material/TextField'
import Button from '@mui/material/Button'
import Divider from '@mui/material/Divider'
import { isBefore, isAfter, startOfDay } from 'date-fns'
Expand All @@ -19,6 +18,7 @@ import { trackEvent } from '@/services/analytics'
import { TX_LIST_EVENTS } from '@/services/analytics/events/txList'
import { txFilter, useTxFilter, TxFilterType, type TxFilter } from '@/utils/tx-history-filter'
import { useCurrentChain } from '@/hooks/useChains'
import NumberField from '@/components/common/NumberField'

enum TxFilterFormFieldNames {
FILTER_TYPE = 'type',
Expand Down Expand Up @@ -191,7 +191,7 @@ const TxFilterForm = ({ toggleFilter }: { toggleFilter: () => void }): ReactElem
},
}}
render={({ field, fieldState }) => (
<TextField
<NumberField
label={
fieldState.error?.message ||
`Amount${isMultisigFilter && chain ? ` (only ${chain.nativeCurrency.symbol})` : ''}`
Expand Down Expand Up @@ -239,7 +239,7 @@ const TxFilterForm = ({ toggleFilter }: { toggleFilter: () => void }): ReactElem
},
}}
render={({ field, fieldState }) => (
<TextField
<NumberField
label={fieldState.error?.message || 'Nonce'}
error={!!fieldState.error}
{...field}
Expand Down
17 changes: 6 additions & 11 deletions src/components/tx/AdvancedParams/AdvancedParamsForm.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type SyntheticEvent } from 'react'
import { Button, DialogActions, FormControl, Grid, TextField, Link, Typography, DialogContent } from '@mui/material'
import { Button, DialogActions, FormControl, Grid, Link, Typography, DialogContent } from '@mui/material'
import OpenInNewIcon from '@mui/icons-material/OpenInNew'
import { BigNumber } from 'ethers'
import { FormProvider, useForm } from 'react-hook-form'
Expand All @@ -9,6 +9,7 @@ import NonceForm from '../NonceForm'
import ModalDialog from '@/components/common/ModalDialog'
import { AdvancedField, type AdvancedParameters } from './types.d'
import GasLimitInput from './GasLimitInput'
import NumberField from '@/components/common/NumberField'

const HELP_LINK = 'https://help.gnosis-safe.io/en/articles/4738445-advanced-transaction-parameters'

Expand Down Expand Up @@ -107,11 +108,9 @@ const AdvancedParamsForm = ({ params, ...props }: AdvancedParamsFormProps) => {
{!!params.safeTxGas && (
<Grid item xs={6}>
<FormControl fullWidth>
<TextField
<NumberField
label={errors.safeTxGas?.message || 'safeTxGas'}
error={!!errors.safeTxGas}
autoComplete="off"
type="number"
disabled={props.nonceReadonly}
required
{...register(AdvancedField.safeTxGas, { required: true, min: 0 })}
Expand All @@ -131,11 +130,9 @@ const AdvancedParamsForm = ({ params, ...props }: AdvancedParamsFormProps) => {
{/* User nonce */}
<Grid item xs={6}>
<FormControl fullWidth>
<TextField
<NumberField
label={errors.userNonce?.message || 'Wallet nonce'}
error={!!errors.userNonce}
autoComplete="off"
type="number"
{...register(AdvancedField.userNonce)}
/>
</FormControl>
Expand All @@ -150,10 +147,9 @@ const AdvancedParamsForm = ({ params, ...props }: AdvancedParamsFormProps) => {
{props.isEIP1559 && (
<Grid item xs={6}>
<FormControl fullWidth>
<TextField
<NumberField
label={errors.maxPriorityFeePerGas?.message || 'Max priority fee (Gwei)'}
error={!!errors.maxPriorityFeePerGas}
autoComplete="off"
required
{...register(AdvancedField.maxPriorityFeePerGas, {
required: true,
Expand All @@ -167,10 +163,9 @@ const AdvancedParamsForm = ({ params, ...props }: AdvancedParamsFormProps) => {

<Grid item xs={6}>
<FormControl fullWidth>
<TextField
<NumberField
label={errors.maxFeePerGas?.message || props.isEIP1559 ? 'Max fee (Gwei)' : 'Gas price (Gwei)'}
error={!!errors.maxFeePerGas}
autoComplete="off"
required
{...register(AdvancedField.maxFeePerGas, { required: true, pattern: FLOAT_REGEX, min: 0 })}
/>
Expand Down
7 changes: 3 additions & 4 deletions src/components/tx/AdvancedParams/GasLimitInput.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { FormControl, IconButton, TextField, Tooltip } from '@mui/material'
import { FormControl, IconButton, Tooltip } from '@mui/material'
import RotateLeftIcon from '@mui/icons-material/RotateLeft'
import { useFormContext } from 'react-hook-form'
import { BASE_TX_GAS } from '@/config/constants'
import { AdvancedField } from './types.d'
import NumberField from '@/components/common/NumberField'

const GasLimitInput = ({ recommendedGasLimit }: { recommendedGasLimit?: string }) => {
const {
Expand Down Expand Up @@ -31,10 +32,9 @@ const GasLimitInput = ({ recommendedGasLimit }: { recommendedGasLimit?: string }

return (
<FormControl fullWidth>
<TextField
<NumberField
label={errorMessage || 'Gas limit'}
error={!!errorMessage}
autoComplete="off"
InputProps={{
endAdornment: recommendedGasLimit && recommendedGasLimit !== currentGasLimit.toString() && (
<Tooltip title="Reset to recommended gas limit">
Expand All @@ -48,7 +48,6 @@ const GasLimitInput = ({ recommendedGasLimit }: { recommendedGasLimit?: string }
InputLabelProps={{
shrink: currentGasLimit !== undefined,
}}
type="number"
required
{...register(AdvancedField.gasLimit, { required: true, min: BASE_TX_GAS })}
/>
Expand Down
9 changes: 4 additions & 5 deletions src/components/tx/NonceForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { memo, useMemo } from 'react'
import type { ReactElement } from 'react'
import { useController, useFormContext, useWatch } from 'react-hook-form'
import { Autocomplete, IconButton, InputAdornment, MenuItem, TextField, Tooltip } from '@mui/material'
import { Autocomplete, IconButton, InputAdornment, MenuItem, Tooltip } from '@mui/material'
import RotateLeftIcon from '@mui/icons-material/RotateLeft'
import useSafeInfo from '@/hooks/useSafeInfo'
import NumberField from '@/components/common/NumberField'
import useTxQueue, { useQueuedTxByNonce } from '@/hooks/useTxQueue'
import { isMultisigExecutionInfo, isTransactionListItem } from '@/utils/transaction-guards'
import { uniqBy } from 'lodash'
import { getTransactionType } from '@/hooks/useTransactionType'
import useAddressBook from '@/hooks/useAddressBook'
import type { MenuItemProps } from '@mui/material'
import { getLatestTransactions } from '@/utils/tx-list'
import type { MenuItemProps } from '@mui/material'

type NonceFormProps = {
name: string
Expand Down Expand Up @@ -112,13 +113,11 @@ const NonceForm = ({ name, nonce, recommendedNonce, readonly }: NonceFormProps):
},
}}
renderInput={(params) => (
<TextField
<NumberField
{...params}
name={name}
onBlur={onBlur}
inputRef={ref}
type="number"
autoComplete="off"
error={!!fieldState.error}
label={label}
InputProps={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
MenuItem,
Select,
Typography,
TextField,
DialogContent,
Box,
SvgIcon,
Expand All @@ -31,6 +30,7 @@ import useChainId from '@/hooks/useChainId'
import { sameAddress } from '@/utils/addresses'
import InfoIcon from '@/public/images/notifications/info.svg'
import useIsSafeTokenPaused from '@/components/tx/modals/TokenTransferModal/useIsSafeTokenPaused'
import NumberField from '@/components/common/NumberField'

export const AutocompleteItem = (item: { tokenInfo: TokenInfo; balance: string }): ReactElement => (
<Grid container alignItems="center" gap={1}>
Expand Down Expand Up @@ -179,10 +179,9 @@ const SendAssetsForm = ({ onSubmit, formData, disableSpendingLimit = false }: Se
)}

<FormControl fullWidth sx={{ mt: 2 }}>
<TextField
<NumberField
label={errors.amount?.message || 'Amount'}
error={!!errors.amount}
autoComplete="off"
InputProps={{
endAdornment: (
<InputValueHelper onClick={onMaxAmountClick} disabled={!selectedToken}>
Expand Down

0 comments on commit 637fd61

Please sign in to comment.