Skip to content

Commit

Permalink
Merge pull request #1956 from oasisprotocol/ml/prevent-scroll-input-n…
Browse files Browse the repository at this point in the history
…umber

Prevent value change on number input wheel scroll
  • Loading branch information
lubej authored Jun 4, 2024
2 parents 06b9849 + 9ba0d60 commit 382fd40
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 2 deletions.
1 change: 1 addition & 0 deletions .changelog/1956.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prevent value change on number input wheel scroll
35 changes: 35 additions & 0 deletions playwright/tests/transfer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { test, expect } from '@playwright/test'
import { privateKey, privateKeyAddress } from '../../src/utils/__fixtures__/test-inputs'
import { fillPrivateKeyWithoutPassword } from '../utils/fillPrivateKey'
import { warnSlowApi } from '../utils/warnSlowApi'
import { mockApi } from '../utils/mockApi'

test.beforeEach(async ({ page }) => {
await warnSlowApi(page)
await mockApi(page, 123)

await page.goto('/open-wallet/private-key')
await fillPrivateKeyWithoutPassword(page, {
privateKey: privateKey,
privateKeyAddress: privateKeyAddress,
persistenceCheckboxDisabled: false,
})
await expect(page.getByTestId('account-selector')).toBeVisible()
})

test('Scrolling on amount input field should preserve value', async ({ page }) => {
await page.getByTestId('nav-myaccount').click()

const input = page.getByPlaceholder('Enter an amount')
await input.click()
await input.fill('1111')
const inputPosition = await input.boundingBox()
await page.mouse.move(
inputPosition!.x + inputPosition!.width / 2,
inputPosition!.y + inputPosition!.height / 2,
)
await page.mouse.wheel(0, 10)
await page.mouse.wheel(0, 10)
await page.mouse.wheel(0, 10)
await expect(input).toHaveValue('1111')
})
4 changes: 3 additions & 1 deletion src/app/components/AddEscrowForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import { ResponsiveContext } from 'grommet/es6/contexts/ResponsiveContext'
import React, { memo, useContext, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'

import { TransactionStatus } from '../TransactionStatus'
import { usePreventChangeOnNumberInputScroll } from '../../lib/usePreventChangeOnNumberInputScroll'

interface Props {
validatorAddress: string
Expand All @@ -39,6 +39,7 @@ export const AddEscrowForm = memo((props: Props) => {
const minStaking = useSelector(selectMinStaking)
const ticker = useSelector(selectTicker)
const isMobile = useContext(ResponsiveContext) === 'small'
const { onWheel } = usePreventChangeOnNumberInputScroll()
const delegate = () => {
dispatch(
transactionActions.addEscrow({
Expand Down Expand Up @@ -111,6 +112,7 @@ export const AddEscrowForm = memo((props: Props) => {
</Text>
}
reverse
onWheel={onWheel}
/>
</Box>
<Button label={t('account.addEscrow.delegate', 'Delegate')} type="submit" primary />
Expand Down
2 changes: 2 additions & 0 deletions src/app/components/ReclaimEscrowForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { StringifiedBigInt } from 'types/StringifiedBigInt'
import { TransactionStatus } from '../TransactionStatus'
import { selectTicker } from '../../state/network/selectors'
import { AmountFormatter } from '../AmountFormatter'
import { usePreventChangeOnNumberInputScroll } from '../../lib/usePreventChangeOnNumberInputScroll'

interface Props {
/** Currently delegated amount */
Expand Down Expand Up @@ -109,6 +110,7 @@ export const ReclaimEscrowForm = memo((props: Props) => {
</Text>
}
reverse
{...usePreventChangeOnNumberInputScroll()}
/>
<Box align="end" margin={{ top: 'xsmall' }}>
<Text weight="bolder" size="small">
Expand Down
36 changes: 36 additions & 0 deletions src/app/lib/__tests__/usePreventChangeOnNumberInputScroll.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { render, fireEvent, act, waitFor } from '@testing-library/react'
import { TextInput } from 'grommet/es6/components/TextInput'
import { usePreventChangeOnNumberInputScroll } from '../usePreventChangeOnNumberInputScroll'

const TextInputFormItem = () => (
<TextInput role="input" type="number" {...usePreventChangeOnNumberInputScroll()} />
)

describe('usePreventChangeOnNumberInputScroll', () => {
it('Should focus on input that is already in focus', async () => {
const { getByRole } = render(<TextInputFormItem />)

const numberInput = getByRole('input')
fireEvent.change(numberInput, { target: { value: '123' } })

act(() => {
fireEvent.focus(numberInput)
fireEvent.wheel(numberInput)
})

waitFor(() => expect(numberInput).toHaveFocus())
expect(numberInput).toHaveValue(123)
})

it('Should not focus on input that is not focused', async () => {
const { getByRole } = render(<TextInputFormItem />)

const numberInput = getByRole('input')

act(() => {
fireEvent.wheel(numberInput)
})

expect(numberInput).not.toHaveFocus()
})
})
23 changes: 23 additions & 0 deletions src/app/lib/usePreventChangeOnNumberInputScroll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { TextInputProps } from 'grommet/es6/components/TextInput'

export const usePreventChangeOnNumberInputScroll = ({ onWheel }: Pick<TextInputProps, 'onWheel'> = {}): Pick<
TextInputProps,
'onWheel'
> => {
return {
onWheel: e => {
onWheel?.(e)

const target = e.target as HTMLElement
if (target !== document.activeElement) return

// Prevents input value change
target.blur()

// Focus after blur
setTimeout(() => {
target.focus()
}, 0)
},
}
}
4 changes: 3 additions & 1 deletion src/app/pages/AccountPage/Features/SendTransaction/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
import { parseRoseStringToBaseUnitString } from 'app/lib/helpers'
import { selectTicker } from '../../../../state/network/selectors'
import { selectTicker } from 'app/state/network/selectors'
import { usePreventChangeOnNumberInputScroll } from 'app/lib/usePreventChangeOnNumberInputScroll'

export interface SendTransactionProps {
isAddressInWallet: boolean
Expand Down Expand Up @@ -118,6 +119,7 @@ export function SendTransaction(props: SendTransactionProps) {
</Text>
}
reverse
{...usePreventChangeOnNumberInputScroll()}
/>
</FormField>
<Box direction="row" justify="between" margin={{ top: 'medium' }}>
Expand Down
3 changes: 3 additions & 0 deletions src/app/pages/ParaTimesPage/TransactionAmount/FeesSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Collapsible } from 'grommet/es6/components/Collapsible'
import { FormField } from 'grommet/es6/components/FormField'
import { TextInput } from 'grommet/es6/components/TextInput'
import { useTranslation } from 'react-i18next'
import { usePreventChangeOnNumberInputScroll } from 'app/lib/usePreventChangeOnNumberInputScroll'

type FeesSectionProps = {
feeAmount: string
Expand Down Expand Up @@ -46,6 +47,7 @@ export const FeesSection = ({ feeAmount, feeGas, ticker }: FeesSectionProps) =>
step="1"
type="number"
value={feeAmount}
{...usePreventChangeOnNumberInputScroll()}
/>
</FormField>
<FormField
Expand All @@ -62,6 +64,7 @@ export const FeesSection = ({ feeAmount, feeGas, ticker }: FeesSectionProps) =>
step="1"
type="number"
value={feeGas}
{...usePreventChangeOnNumberInputScroll()}
/>
</FormField>
</Collapsible>
Expand Down

0 comments on commit 382fd40

Please sign in to comment.