Feat/1147 input setter (#1148)

* feat(console-lite): stretch half page width for xl screens on connect wallet on portfolio page

* feat(console-lite): make InputSetter component reusable

* fix(console-lite): pr comments

* fix(console-lite): failing tests
This commit is contained in:
Elmar 2022-08-31 16:32:53 +01:00 committed by GitHub
parent 3519f1b814
commit 4407a778a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 145 additions and 50 deletions

View File

@ -7,13 +7,13 @@ import {
SliderThumb, SliderThumb,
SliderTrack, SliderTrack,
SliderRange, SliderRange,
Input,
FormGroup, FormGroup,
Icon, Icon,
Tooltip, Tooltip,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { BigNumber } from 'bignumber.js'; import { BigNumber } from 'bignumber.js';
import { DealTicketEstimates } from './deal-ticket-estimates'; import { DealTicketEstimates } from './deal-ticket-estimates';
import { InputSetter } from '../input-setter';
import * as constants from './constants'; import * as constants from './constants';
interface DealTicketSizeProps { interface DealTicketSizeProps {
@ -61,7 +61,6 @@ export const DealTicketSize = ({
}: DealTicketSizeProps) => { }: DealTicketSizeProps) => {
const sizeRatios = [0, 25, 50, 75, 100]; const sizeRatios = [0, 25, 50, 75, 100];
const [inputValue, setInputValue] = useState(value); const [inputValue, setInputValue] = useState(value);
const [isInputVisible, setIsInputVisible] = useState(false);
const onInputValueChange = useCallback( const onInputValueChange = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => { (event: React.ChangeEvent<HTMLInputElement>) => {
@ -84,30 +83,21 @@ export const DealTicketSize = ({
const onButtonValueChange = useCallback( const onButtonValueChange = useCallback(
(size: number) => { (size: number) => {
if (isInputVisible) {
setIsInputVisible(false);
}
const newVal = new BigNumber(size) const newVal = new BigNumber(size)
.decimalPlaces(positionDecimalPlaces) .decimalPlaces(positionDecimalPlaces)
.toNumber(); .toNumber();
onValueChange([newVal]); onValueChange([newVal]);
setInputValue(newVal); setInputValue(newVal);
}, },
[isInputVisible, onValueChange, positionDecimalPlaces] [onValueChange, positionDecimalPlaces]
); );
const toggleInput = useCallback(() => { const onSliderValueChange = useCallback(
setIsInputVisible(!isInputVisible); (value: number[]) => {
}, [isInputVisible]); setInputValue(value[0]);
onValueChange(value);
const onInputEnter = useCallback(
(event: React.KeyboardEvent) => {
if (event.key === 'Enter') {
event.stopPropagation();
toggleInput();
}
}, },
[toggleInput] [onValueChange]
); );
return max === 0 ? ( return max === 0 ? (
@ -121,7 +111,7 @@ export const DealTicketSize = ({
<SliderRoot <SliderRoot
className="mb-2" className="mb-2"
value={[value]} value={[value]}
onValueChange={onValueChange} onValueChange={onSliderValueChange}
step={step} step={step}
min={min} min={min}
max={max} max={max}
@ -160,36 +150,16 @@ export const DealTicketSize = ({
label="Enter Size" label="Enter Size"
labelFor="trade-size-input" labelFor="trade-size-input"
> >
{isInputVisible ? ( <InputSetter
<div className="flex items-center"> id="input-order-size-market"
<Input type="number"
id="input-order-size-market" step={step}
type="number" min={min}
step={step} max={max}
min={min} className="w-full"
max={max} value={inputValue}
className="w-full" onChange={onInputValueChange}
value={inputValue} />
onKeyDown={onInputEnter}
onChange={onInputValueChange}
/>
<button
className="no-underline hover:underline text-blue ml-2"
type="button"
onClick={toggleInput}
>
{t('set')}
</button>
</div>
) : (
<button
className="no-underline hover:underline text-blue"
onClick={toggleInput}
type="button"
>
{value}
</button>
)}
</FormGroup> </FormGroup>
</dd> </dd>
</div> </div>

View File

@ -0,0 +1 @@
export * from './input-setter';

View File

@ -0,0 +1,64 @@
import React from 'react';
import { render, waitFor, fireEvent } from '@testing-library/react';
import { InputSetter } from './index';
describe('InputSetter Component', () => {
it('should show the correct value and visibility based on props', async () => {
const value = 'Hello';
const isInputVisible = true;
const { getByRole } = await render(
<InputSetter
id="input-order-size-market"
type="number"
className="w-full"
value={value}
isInputVisible={isInputVisible}
onChange={() => false}
/>
);
const input = getByRole('spinbutton');
const btn = getByRole('button');
expect(input).toHaveAttribute('value', value);
expect(btn).toBeTruthy();
});
it('should toggle the visibility of the input when the button is clicked', async () => {
const value = 'Hello';
const isInputVisible = true;
const { getByRole } = await render(
<InputSetter
id="input-order-size-market"
type="number"
className="w-full"
value={value}
isInputVisible={isInputVisible}
onChange={() => false}
/>
);
const btn = getByRole('button');
fireEvent.click(btn);
await waitFor(() => getByRole('button'));
expect(getByRole('button')).toHaveTextContent(value);
});
it('should toggle the visibility of the input when the enter key is pressed', async () => {
const value = 'Hello';
const isInputVisible = true;
const { getByRole } = await render(
<InputSetter
id="input-order-size-market"
name="input-order-size-market"
type="number"
className="w-full"
value={value}
isInputVisible={isInputVisible}
onChange={() => false}
/>
);
fireEvent.keyDown(getByRole('spinbutton'), {
key: 'Enter',
});
await waitFor(() => getByRole('button'));
expect(getByRole('button')).toHaveTextContent(value);
});
});

View File

@ -0,0 +1,56 @@
import React, { useCallback, useState } from 'react';
import { t } from '@vegaprotocol/react-helpers';
import { Input } from '@vegaprotocol/ui-toolkit';
import type { InputProps } from '@vegaprotocol/ui-toolkit';
interface InputSetterProps {
buttonLabel?: string;
value: string | number;
isInputVisible?: boolean;
onValueChange?: () => string;
}
export const InputSetter = ({
buttonLabel = t('set'),
value = '',
isInputVisible = false,
onValueChange,
...props
}: InputSetterProps & InputProps) => {
const [isInputToggled, setIsInputToggled] = useState(isInputVisible);
const toggleInput = useCallback(() => {
setIsInputToggled(!isInputToggled);
}, [isInputToggled]);
const onInputEnter = useCallback(
(event: React.KeyboardEvent) => {
if (event.key === 'Enter') {
event.stopPropagation();
toggleInput();
}
},
[toggleInput]
);
return isInputToggled ? (
<div className="flex items-center">
<Input {...props} value={value} onKeyDown={onInputEnter} />
<button
type="button"
className="no-underline hover:underline text-blue ml-2"
onClick={toggleInput}
>
{buttonLabel}
</button>
</div>
) : (
<button
type="button"
className="no-underline hover:underline text-blue"
onClick={toggleInput}
>
{value}
</button>
);
};

View File

@ -11,7 +11,11 @@ import ConnectWallet from '../wallet-connector';
export const Portfolio = () => { export const Portfolio = () => {
const { keypair } = useVegaWallet(); const { keypair } = useVegaWallet();
if (!keypair) { if (!keypair) {
return <ConnectWallet />; return (
<section className="xl:w-1/2">
<ConnectWallet />
</section>
);
} }
return ( return (
<Tabs> <Tabs>

View File

@ -55,7 +55,7 @@ type InputAppend = NoPrepend &
type AffixProps = InputPrepend | InputAppend; type AffixProps = InputPrepend | InputAppend;
type InputProps = InputRootProps & AffixProps; export type InputProps = InputRootProps & AffixProps;
export const inputStyle = ({ export const inputStyle = ({
style, style,