Skip to content

Commit

Permalink
feat(suite): display bottom text message
Browse files Browse the repository at this point in the history
  • Loading branch information
enjojoy committed Aug 13, 2024
1 parent dc6096e commit a095d24
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 20 deletions.
5 changes: 4 additions & 1 deletion packages/components/src/components/form/Input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { InputState, InputSize } from '../inputTypes';
import { TopAddons } from '../TopAddons';
import { useElevation } from '../../ElevationContext/ElevationContext';
import { UIHorizontalAlignment } from '../../../config/types';
import { IconName } from '@suite-common/icons';

const Wrapper = styled.div<{ $width?: number; $hasBottomPadding: boolean }>`
display: inline-flex;
Expand Down Expand Up @@ -90,6 +91,7 @@ export interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>,
* @description pass `null` if bottom text can be `undefined`
*/
bottomText?: ReactNode;
bottomTextIcon?: IconName;
isDisabled?: boolean;
size?: InputSize;
className?: string;
Expand All @@ -115,6 +117,7 @@ const Input = ({
innerAddon,
innerAddonAlign = 'right',
bottomText,
bottomTextIcon,
size = 'large',
isDisabled,
'data-testid': dataTest,
Expand Down Expand Up @@ -203,7 +206,7 @@ const Input = ({
</InputWrapper>

{bottomText && (
<BottomText inputState={inputState} isDisabled={isDisabled}>
<BottomText inputState={inputState} isDisabled={isDisabled} icon={bottomTextIcon}>
{bottomText}
</BottomText>
)}
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/components/form/inputTypes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { UISize } from '../../config/types';

export type InputState = 'warning' | 'error';
export type InputState = 'warning' | 'error' | 'primary';

export type InputSize = Extract<UISize, 'small' | 'large'>;
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ const Link = ({
e.stopPropagation();
onClick?.(e);
}}
$type={type}
$variant={variant}
className={className}
>
Expand Down
21 changes: 17 additions & 4 deletions packages/suite/src/components/wallet/InputError.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ const Wrapper = styled.div`
gap: ${spacingsPx.xs};
`;

const ButtonWrapper = styled.div`
position: absolute;
top: 4px;
right: 16px;
`;

const ContentWrapper = styled.div`
flex-grow: 1;
padding-right: 150px;
`;

type ButtonProps = { onClick: MouseEventHandler<HTMLButtonElement>; text: string };
type LinkProps = { url: Url };

Expand All @@ -22,14 +33,16 @@ export type InputErrorProps = {

export const InputError = ({ button, message }: InputErrorProps) => (
<Wrapper>
{message}
<ContentWrapper>{message}</ContentWrapper>
{button &&
('url' in button ? (
<LearnMoreButton url={button.url} />
) : (
<Button size="tiny" variant="tertiary" onClick={button.onClick}>
{button.text}
</Button>
<ButtonWrapper>
<Button size="tiny" variant="tertiary" onClick={button.onClick}>
{button.text}
</Button>
</ButtonWrapper>
))}
</Wrapper>
);
73 changes: 59 additions & 14 deletions packages/suite/src/views/wallet/send/Outputs/Address.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,21 @@ import {
getInputState,
} from '@suite-common/wallet-utils';

import { AddressLabeling, Translation, MetadataLabeling } from 'src/components/suite';
import { AddressLabeling, MetadataLabeling } from 'src/components/suite';
import { Link } from '@trezor/components';
import { Translation } from '../../../../components/suite/Translation';

import { scanOrRequestSendFormThunk } from 'src/actions/wallet/send/sendFormThunks';
import { useDevice, useDispatch, useTranslation } from 'src/hooks/suite';
import { useSendFormContext } from 'src/hooks/wallet';
import { getProtocolInfo } from 'src/utils/suite/protocol';
import { PROTOCOL_TO_NETWORK } from 'src/constants/suite/protocol';
import { InputError } from 'src/components/wallet';
import { InputErrorProps } from 'src/components/wallet/InputError';
import { Row } from '@trezor/components';

import { HELP_CENTER_EVM_ADDRESS_CHECKSUM } from '@trezor/urls';
import { spacings } from '@trezor/theme';
const Container = styled.div`
position: relative;
`;
Expand Down Expand Up @@ -68,7 +74,6 @@ export const Address = ({ output, outputId, outputsCount }: AddressProps) => {
setDraftSaveRequest,
} = useSendFormContext();
const { translationString } = useTranslation();

const { descriptor, networkType, symbol } = account;
const inputName = `outputs.${outputId}.address` as const;
// NOTE: compose errors are always associated with the amount.
Expand All @@ -84,7 +89,16 @@ export const Address = ({ output, outputId, outputsCount }: AddressProps) => {
const options = getDefaultValue('options', []);
const broadcastEnabled = options.includes('broadcast');
const isOnline = useSelector(state => state.suite.online);
const inputState = getInputState(addressError);
const getInputErrorState = () => {
if (hasAddressChecksummed) {
return 'primary';
}
if (addressError) {
return getInputState(addressError);
}

return undefined;
};

const handleQrClick = useCallback(async () => {
const uri = await dispatch(scanOrRequestSendFormThunk()).unwrap();
Expand Down Expand Up @@ -256,10 +270,49 @@ export const Address = ({ output, outputId, outputsCount }: AddressProps) => {
});
const addressBottomText = isAddressWithLabel ? addressLabelComponent : null;

const getBottomText = () => {
if (hasAddressChecksummed) {
return (
<Row width="100%" justifyContent="flex-start" gap={spacings.xs}>
<Translation
id="TR_CHECKSUM_CONVERSION_INFO"
values={{
a: chunks => (
<Link
href={HELP_CENTER_EVM_ADDRESS_CHECKSUM}
variant="nostyle"
icon="EXTERNAL_LINK"
type="label"
>
{chunks}
</Link>
),
}}
/>
</Row>
);
}
if (addressError) {
return (
<InputError message={addressError.message} button={getValidationButtonProps()} />
);
}

return addressBottomText;
};

const getBottomTextIcon = () => {
if (hasAddressChecksummed) {
return 'check';
}

return undefined;
};

return (
<Container>
<Input
inputState={inputState}
inputState={getInputErrorState()}
innerAddon={
metadataEnabled && broadcastEnabled ? (
<MetadataLabelingWrapper>
Expand Down Expand Up @@ -321,16 +374,8 @@ export const Address = ({ output, outputId, outputsCount }: AddressProps) => {
/>
) : undefined
}
bottomText={
addressError ? (
<InputError
message={addressError.message}
button={getValidationButtonProps()}
/>
) : (
addressBottomText
)
}
bottomText={getBottomText()}
bottomTextIcon={getBottomTextIcon()}
data-testid={inputName}
defaultValue={addressValue}
maxLength={formInputsMaxLength.address}
Expand Down

0 comments on commit a095d24

Please sign in to comment.