diff --git a/packages/components/src/components/Card/Card.tsx b/packages/components/src/components/Card/Card.tsx index aa25ce8c267..3b03710fd71 100644 --- a/packages/components/src/components/Card/Card.tsx +++ b/packages/components/src/components/Card/Card.tsx @@ -25,6 +25,7 @@ export const allowedCardFrameProps = [ 'minHeight', 'maxHeight', 'overflow', + 'flex', ] as const satisfies FramePropsKeys[]; type AllowedFrameProps = Pick; diff --git a/packages/components/src/components/IconCircle/IconCircle.stories.tsx b/packages/components/src/components/IconCircle/IconCircle.stories.tsx index d20b670aa83..cf5cf89abc4 100644 --- a/packages/components/src/components/IconCircle/IconCircle.stories.tsx +++ b/packages/components/src/components/IconCircle/IconCircle.stories.tsx @@ -9,7 +9,7 @@ import { IconCircleProps, allowedIconCircleFrameProps, } from './IconCircle'; -import { iconCircleVariants } from './types'; +import { iconCircleVariants, iconCirclePaddingTypes } from './types'; import { getFramePropsStory } from '../../utils/frameProps'; const meta: Meta = { @@ -22,6 +22,7 @@ export const IconCircle: StoryObj = { args: { variant: 'primary', name: 'butterfly', + paddingType: 'large', size: 40, hasBorder: true, ...getFramePropsStory(allowedIconCircleFrameProps).args, @@ -38,6 +39,12 @@ export const IconCircle: StoryObj = { type: 'number', }, }, + paddingType: { + control: { + type: 'select', + }, + options: iconCirclePaddingTypes, + }, hasBorder: { control: { type: 'boolean', diff --git a/packages/components/src/components/IconCircle/IconCircle.tsx b/packages/components/src/components/IconCircle/IconCircle.tsx index 5fe6b78708d..e605b462a5b 100644 --- a/packages/components/src/components/IconCircle/IconCircle.tsx +++ b/packages/components/src/components/IconCircle/IconCircle.tsx @@ -2,8 +2,18 @@ import styled from 'styled-components'; import { ExclusiveColorOrVariant, Icon, IconName, IconSize, getIconSize } from '../Icon/Icon'; import { TransientProps } from '../../utils/transientProps'; -import { IconCircleExclusiveColorOrVariant, IconCircleVariant, IconCircleColors } from './types'; -import { mapVariantToIconBackground, mapVariantToIconBorderColor } from './utils'; +import { + IconCircleExclusiveColorOrVariant, + IconCircleVariant, + IconCircleColors, + IconCirclePaddingType, +} from './types'; +import { + mapVariantToIconBackground, + mapVariantToIconBorderColor, + mapPaddingTypeToPadding, + mapPaddingTypeToBorderWidth, +} from './utils'; import { FrameProps, FramePropsKeys, @@ -19,23 +29,26 @@ type IconCircleWrapperProps = TransientProps< > & { $size: number; $hasBorder: boolean; + $paddingType: IconCirclePaddingType; }; const IconCircleWrapper = styled.div` width: ${({ $size }) => $size}px; background: ${mapVariantToIconBackground}; - padding: ${({ $size }) => $size * 0.75}px; + padding: ${mapPaddingTypeToPadding}; border-radius: 50%; - box-shadow: inset 0 0 0 ${({ $hasBorder, $size }) => ($hasBorder ? $size / 4 : 0)}px - ${mapVariantToIconBorderColor}; + box-shadow: inset 0 0 0 ${mapPaddingTypeToBorderWidth} ${mapVariantToIconBorderColor}; box-sizing: content-box; + ${({ $hasBorder }) => !$hasBorder && 'box-shadow: none;'} + ${withFrameProps} `; export type IconCircleProps = { name: IconName; size: IconSize | number; + paddingType?: IconCirclePaddingType; hasBorder?: boolean; } & IconCircleExclusiveColorOrVariant & AllowedFrameProps; @@ -44,6 +57,7 @@ export const IconCircle = ({ name, size, hasBorder = true, + paddingType = 'large', iconColor, variant, ...rest @@ -62,6 +76,7 @@ export const IconCircle = ({ return ( ; diff --git a/packages/components/src/components/IconCircle/utils.tsx b/packages/components/src/components/IconCircle/utils.tsx index 2e2358bc032..9b942c1d9f3 100644 --- a/packages/components/src/components/IconCircle/utils.tsx +++ b/packages/components/src/components/IconCircle/utils.tsx @@ -2,15 +2,28 @@ import { DefaultTheme } from 'styled-components'; import { Color, CSSColor } from '@trezor/theme'; -import { IconCircleVariant, IconCircleExclusiveColorOrVariant } from './types'; +import { + IconCircleVariant, + IconCircleExclusiveColorOrVariant, + IconCirclePaddingType, +} from './types'; import { TransientProps } from '../../utils/transientProps'; -type MapArgs = { +type VariantMapArgs = { theme: DefaultTheme; $hasBorder: boolean; } & TransientProps; -export const mapVariantToIconBorderColor = ({ $variant, theme, $iconColor }: MapArgs): CSSColor => { +type PaddingTypeMap = { + $paddingType: IconCirclePaddingType; + $size: number; +}; + +export const mapVariantToIconBorderColor = ({ + $variant, + theme, + $iconColor, +}: VariantMapArgs): CSSColor => { if ($variant === undefined) { return $iconColor?.foreground ?? 'transparent'; } @@ -31,17 +44,17 @@ export const mapVariantToIconBackground = ({ $hasBorder, $iconColor, $variant, -}: MapArgs): CSSColor => { +}: VariantMapArgs): CSSColor => { if ($variant === undefined) { return $iconColor?.background ?? 'transparent'; } const noBorderColorMap: Record = { - primary: 'backgroundPrimarySubtleOnElevation1', - warning: 'backgroundAlertYellowSubtleOnElevation1', - destructive: 'backgroundAlertRedSubtleOnElevation1', - info: 'backgroundAlertBlueSubtleOnElevation1', - tertiary: 'backgroundTertiaryDefaultOnElevation1', + primary: 'backgroundPrimarySubtleOnElevation0', + warning: 'backgroundAlertYellowSubtleOnElevation0', + destructive: 'backgroundAlertRedSubtleOnElevation0', + info: 'backgroundAlertBlueSubtleOnElevation0', + tertiary: 'backgroundTertiaryDefaultOnElevation0', }; const borderColorMap: Record = { @@ -54,3 +67,23 @@ export const mapVariantToIconBackground = ({ return theme[($hasBorder ? borderColorMap : noBorderColorMap)[$variant]]; }; + +export const mapPaddingTypeToPadding = ({ $paddingType, $size }: PaddingTypeMap): string => { + const paddingCoefficientMap: Record = { + small: 0.25, + medium: 0.5, + large: 0.75, + }; + + return $size * paddingCoefficientMap[$paddingType] + 'px'; +}; + +export const mapPaddingTypeToBorderWidth = ({ $paddingType, $size }: PaddingTypeMap): string => { + const borderCoefficientMap: Record = { + small: 0.1, + medium: 0.175, + large: 0.25, + }; + + return $size * borderCoefficientMap[$paddingType] + 'px'; +}; diff --git a/packages/components/src/components/InfoRow/InfoRow.stories.tsx b/packages/components/src/components/InfoRow/InfoRow.stories.tsx index ec339c91557..5e1354acf10 100644 --- a/packages/components/src/components/InfoRow/InfoRow.stories.tsx +++ b/packages/components/src/components/InfoRow/InfoRow.stories.tsx @@ -10,6 +10,7 @@ import { import { flexDirection } from '../Flex/Flex'; import { getFramePropsStory } from '../../utils/frameProps'; import { getTextPropsStory } from '../typography/utils'; +import { variables } from '../../config'; const meta: Meta = { title: 'InfoRow', @@ -40,6 +41,16 @@ export const InfoRow: StoryObj = { type: 'text', }, }, + iconName: { + options: ['none', ...variables.ICONS], + mapping: { + ...variables.ICONS, + none: undefined, + }, + control: { + type: 'select', + }, + }, ...getFramePropsStory(allowedInfoRowFrameProps).argTypes, ...getTextPropsStory(allowedInfoRowTextProps).argTypes, }, diff --git a/packages/components/src/components/InfoRow/InfoRow.tsx b/packages/components/src/components/InfoRow/InfoRow.tsx index ae361bb8aea..137c2ada207 100644 --- a/packages/components/src/components/InfoRow/InfoRow.tsx +++ b/packages/components/src/components/InfoRow/InfoRow.tsx @@ -12,16 +12,17 @@ import { } from '../../utils/frameProps'; import { TextPropsKeys, TextProps } from '../typography/utils'; import { TransientProps } from '../../utils/transientProps'; -import { FlexDirection, Flex } from '../Flex/Flex'; +import { FlexDirection, Flex, Row } from '../Flex/Flex'; +import { IconName, Icon } from '../Icon/Icon'; import { Text } from '../typography/Text/Text'; export const allowedInfoRowTextProps = ['typographyStyle'] as const satisfies TextPropsKeys[]; -type AllowedInfoRowTextProps = Pick; +type AllowedTextProps = Pick; export const allowedInfoRowFrameProps = ['margin'] as const satisfies FramePropsKeys[]; type AllowedFrameProps = Pick; -type ContainerProps = TransientProps; +type ContainerProps = TransientProps; const Container = styled.div` width: 100%; @@ -30,9 +31,10 @@ const Container = styled.div` `; export type InfoRowProps = AllowedFrameProps & - AllowedInfoRowTextProps & { + AllowedTextProps & { children?: ReactNode; direction?: FlexDirection; + iconName?: IconName; label: ReactNode; labelTypographyStyle?: TypographyStyle; }; @@ -41,6 +43,7 @@ export const InfoRow = ({ children, label, direction = 'column', + iconName, typographyStyle = 'body', labelTypographyStyle = 'hint', ...rest @@ -54,11 +57,14 @@ export const InfoRow = ({ direction={direction} alignItems={isRow ? 'center' : 'stretch'} justifyContent={isRow ? 'space-between' : undefined} - gap={isRow ? spacings.md : spacings.xxs} + gap={isRow ? spacings.md : spacings.xxxs} > - - {label} - + + {iconName && } + + {label} + + {children} diff --git a/packages/components/src/components/form/BottomText.tsx b/packages/components/src/components/form/BottomText.tsx index 63de78a3517..63be3fe3e4a 100644 --- a/packages/components/src/components/form/BottomText.tsx +++ b/packages/components/src/components/form/BottomText.tsx @@ -5,7 +5,7 @@ import styled, { keyframes } from 'styled-components'; import { spacings } from '@trezor/theme'; import { IconName, Icon, IconVariant } from '../Icon/Icon'; -import { InputState } from './inputTypes'; +import { InputState } from './types'; import { Row } from '../Flex/Flex'; import { Text, TextVariant } from '../typography/Text/Text'; import { UIVariant } from '../../config/types'; diff --git a/packages/components/src/components/form/FormCell/FormCell.tsx b/packages/components/src/components/form/FormCell/FormCell.tsx index ab788ca8377..09cae3415cd 100644 --- a/packages/components/src/components/form/FormCell/FormCell.tsx +++ b/packages/components/src/components/form/FormCell/FormCell.tsx @@ -11,7 +11,7 @@ import { withFrameProps, } from '../../../utils/frameProps'; import { Column } from '../../Flex/Flex'; -import { InputState } from '../inputTypes'; +import { InputState } from '../types'; import { TopAddons } from '../TopAddons'; import { BottomText } from '../BottomText'; import { IconName } from '../../Icon/Icon'; diff --git a/packages/components/src/components/form/Input/Input.tsx b/packages/components/src/components/form/Input/Input.tsx index c46db9c9b12..8a026454b31 100644 --- a/packages/components/src/components/form/Input/Input.tsx +++ b/packages/components/src/components/form/Input/Input.tsx @@ -6,14 +6,8 @@ import styled from 'styled-components'; import { spacingsPx, spacings, typography } from '@trezor/theme'; import { Icon } from '../../Icon/Icon'; -import { - baseInputStyle, - INPUT_HEIGHTS, - BaseInputProps, - Label, - LABEL_TRANSFORM, -} from '../InputStyles'; -import { InputSize } from '../inputTypes'; +import { baseInputStyle, INPUT_HEIGHTS, BaseInputProps, Label, LABEL_TRANSFORM } from '../styles'; +import { InputSize } from '../types'; import { FormCell, FormCellProps, @@ -77,7 +71,7 @@ const InputWrapper = styled.div` const getInputAddonPadding = (size: InputSize) => size === 'small' ? spacingsPx.sm : spacingsPx.md; -const InputAddon = styled.div<{ $align: innerAddonAlignment; $size: InputSize }>` +const InputAddon = styled.div<{ $align: InnerAddonAlignment; $size: InputSize }>` position: absolute; inset: 0 ${({ $align, $size }) => ($align === 'right' ? getInputAddonPadding($size) : 'auto')} 0 ${({ $align, $size }) => ($align === 'left' ? getInputAddonPadding($size) : 'auto')}; @@ -94,9 +88,11 @@ const InputLabel = styled(Label)` } `; -type innerAddonAlignment = Extract; +type InnerAddonAlignment = Extract; + +type InputHTMLProps = Omit, 'size'>; -export type InputProps = Omit, 'size'> & +export type InputProps = InputHTMLProps & AllowedFrameProps & AllowedTextProps & Omit & { @@ -106,8 +102,7 @@ export type InputProps = Omit, 'size'> & innerAddon?: ReactElement; size?: InputSize; 'data-testid'?: string; - innerAddonAlign?: innerAddonAlignment; - hasBottomPadding?: boolean; + innerAddonAlign?: InnerAddonAlignment; /** * @description the clear button replaces the addon on the right side */ @@ -118,7 +113,6 @@ export type InputProps = Omit, 'size'> & const Input = ({ value, innerRef, - inputState, label, innerAddon, innerAddonAlign = 'right', @@ -126,15 +120,21 @@ const Input = ({ 'data-testid': dataTest, showClearButton, placeholder, - isDisabled, onClear, - hasBottomPadding = true, ...rest }: InputProps) => { const [isHovered, setIsHovered] = useState(false); const { elevation } = useElevation(); const textProps = pickAndPrepareTextProps(rest, allowedInputTextProps); const formCellProps = pickFormCellProps(rest); + const { isDisabled, inputState } = formCellProps; + const inputProps = Object.entries(rest).reduce((props, [propKey, propValue]) => { + if (!(propKey in formCellProps) && !(propKey in textProps)) { + props[propKey as keyof InputHTMLProps] = propValue; + } + + return props; + }, {} as InputHTMLProps); const hasShowClearButton = (showClearButton === 'always' || (showClearButton === 'hover' && isHovered)) && @@ -145,7 +145,7 @@ const Input = ({ const [measureRightAddon, { width: rightAddonWidth }] = useMeasure(); return ( - + setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} @@ -174,7 +174,7 @@ const Input = ({ autoCapitalize="off" spellCheck={false} $inputState={inputState} - disabled={isDisabled} + disabled={isDisabled ?? false} $size={size} ref={innerRef} data-lpignore="true" @@ -184,7 +184,7 @@ const Input = ({ placeholder={placeholder || ''} // needed for uncontrolled inputs data-testid={dataTest} {...textProps} - {...rest} + {...inputProps} /> {label && ( diff --git a/packages/components/src/components/form/Select/Select.tsx b/packages/components/src/components/form/Select/Select.tsx index 473c7fc819d..c285c373019 100644 --- a/packages/components/src/components/form/Select/Select.tsx +++ b/packages/components/src/components/form/Select/Select.tsx @@ -15,8 +15,8 @@ import { nextElevation, } from '@trezor/theme'; -import { INPUT_HEIGHTS, LABEL_TRANSFORM, Label, baseInputStyle } from '../InputStyles'; -import { InputSize } from '../inputTypes'; +import { INPUT_HEIGHTS, LABEL_TRANSFORM, Label, baseInputStyle } from '../styles'; +import { InputSize } from '../types'; import { FormCell, FormCellProps, @@ -280,7 +280,6 @@ export type SelectProps = KeyPressScrollProps & isClean?: boolean; label?: ReactNode; size?: InputSize; - hasBottomPadding?: boolean; minValueWidth?: string; isMenuOpen?: boolean; isLoading?: boolean; @@ -292,7 +291,6 @@ export const Select = ({ isClean = false, label, size = 'large', - hasBottomPadding = true, useKeyPressScroll, isSearchable = false, minValueWidth = 'initial', @@ -300,18 +298,17 @@ export const Select = ({ components, onChange, placeholder, - isDisabled = false, isLoading = false, 'data-testid': dataTest, - ...props + ...rest }: SelectProps) => { const selectRef = useRef>(null); const { elevation } = useElevation(); const theme = useTheme(); const onKeyDown = useOnKeyDown(selectRef, useKeyPressScroll); const menuPortalTarget = useDetectPortalTarget(selectRef); - const formCellProps = pickFormCellProps(props); - + const formCellProps = pickFormCellProps(rest); + const { isDisabled } = formCellProps; const isRenderedInModal = menuPortalTarget !== null; const handleOnChange = useCallback['onChange']>( @@ -349,7 +346,7 @@ export const Select = ({ ); return ( - + diff --git a/packages/components/src/components/form/Textarea/Textarea.stories.tsx b/packages/components/src/components/form/Textarea/Textarea.stories.tsx index 30b4d06e14f..25d448cdd1c 100644 --- a/packages/components/src/components/form/Textarea/Textarea.stories.tsx +++ b/packages/components/src/components/form/Textarea/Textarea.stories.tsx @@ -85,10 +85,5 @@ export const Textarea: StoryObj = { }, }, inputState: { control: 'select', options: ['error', 'warning', 'primary'] }, - hasBottomPadding: { - control: { - type: 'boolean', - }, - }, }, }; diff --git a/packages/components/src/components/form/Textarea/Textarea.tsx b/packages/components/src/components/form/Textarea/Textarea.tsx index bd909c9628e..495fa4893be 100644 --- a/packages/components/src/components/form/Textarea/Textarea.tsx +++ b/packages/components/src/components/form/Textarea/Textarea.tsx @@ -4,7 +4,7 @@ import styled from 'styled-components'; import { spacingsPx, Elevation } from '@trezor/theme'; -import { InputState } from '../inputTypes'; +import { InputState } from '../types'; import { baseInputStyle, InputWrapper, @@ -12,7 +12,7 @@ import { getInputStateBgColor, INPUT_PADDING_TOP, LABEL_TRANSFORM, -} from '../InputStyles'; +} from '../styles'; import { FormCell, FormCellProps, pickFormCellProps } from '../FormCell/FormCell'; import { CharacterCount, CharacterCountProps } from './CharacterCount'; import { useElevation } from '../../ElevationContext/ElevationContext'; @@ -65,12 +65,13 @@ const TextareaLabel = styled(Label)` } `; -export type TextareaProps = TextareaHTMLAttributes & +type TextareaHTMLProps = TextareaHTMLAttributes; + +export type TextareaProps = TextareaHTMLProps & Omit & { isDisabled?: boolean; label?: ReactNode; innerRef?: Ref; - hasBottomPadding?: boolean; value?: string; characterCount?: CharacterCountProps['characterCount']; 'data-testid'?: string; @@ -79,21 +80,27 @@ export type TextareaProps = TextareaHTMLAttributes & export const Textarea = ({ value, maxLength, - isDisabled = false, innerRef, label, placeholder, rows = 5, - inputState, characterCount, 'data-testid': dataTest, ...rest }: TextareaProps) => { const { elevation } = useElevation(); const formCellProps = pickFormCellProps(rest); + const { isDisabled, inputState } = formCellProps; + const textareaProps = Object.entries(rest).reduce((props, [propKey, propValue]) => { + if (!(propKey in formCellProps)) { + props[propKey as keyof TextareaHTMLProps] = propValue; + } + + return props; + }, {} as TextareaHTMLProps); return ( - + = { @@ -19,17 +19,6 @@ export const INPUT_HEIGHTS: Record = { export const INPUT_BORDER_WIDTH = Number.parseFloat(borders.widths.large); -export const getInputStateTextColor = (state: InputState | undefined, theme: DefaultTheme) => { - switch (state) { - case 'warning': - return theme.textAlertYellow; - case 'error': - return theme.textAlertRed; - default: - return theme.textSubdued; - } -}; - export const getInputStateBorderColor = (state: InputState | undefined, theme: DefaultTheme) => { switch (state) { case 'warning': diff --git a/packages/components/src/components/form/inputTypes.ts b/packages/components/src/components/form/types.ts similarity index 100% rename from packages/components/src/components/form/inputTypes.ts rename to packages/components/src/components/form/types.ts diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index ea3db70e489..bbc0f1caa3a 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -29,7 +29,7 @@ export * from './components/ElevationContext/ElevationContext'; export * from './components/Flex/Flex'; export { FormCell, type FormCellProps } from './components/form/FormCell/FormCell'; export * from './components/form/Input/Input'; -export * from './components/form/InputStyles'; +export * from './components/form/styles'; export * from './components/form/Radio/Radio'; export * from './components/form/Range/Range'; export * from './components/form/Select/Select'; diff --git a/packages/components/src/utils/frameProps.tsx b/packages/components/src/utils/frameProps.tsx index 54ffaa1b85a..934108289d7 100644 --- a/packages/components/src/utils/frameProps.tsx +++ b/packages/components/src/utils/frameProps.tsx @@ -3,6 +3,7 @@ import { css } from 'styled-components'; import { SpacingValues } from '@trezor/theme'; import { makePropsTransient, TransientProps } from './transientProps'; +import type { Flex } from '../components/Flex/Flex'; type Margin = { top?: SpacingValues | 'auto'; @@ -41,6 +42,7 @@ export type FrameProps = { maxHeight?: string | number; overflow?: Overflow; pointerEvents?: PointerEvent; + flex?: Flex; }; export type FramePropsKeys = keyof FrameProps; @@ -67,6 +69,7 @@ export const withFrameProps = ({ $maxHeight, $overflow, $pointerEvents, + $flex, }: TransientFrameProps) => { return css` ${$margin && @@ -109,6 +112,10 @@ export const withFrameProps = ({ css` pointer-events: ${$pointerEvents}; `}; + ${$flex && + css` + flex: ${$flex}; + `}; `; }; @@ -124,6 +131,7 @@ const getStorybookType = (key: FramePropsKeys) => { case 'height': case 'maxWidth': case 'maxHeight': + case 'flex': return { control: { type: 'text', @@ -185,6 +193,7 @@ export const getFramePropsStory = (allowedFrameProps: Array) => ...(allowedFrameProps.includes('maxWidth') ? { maxWidth: undefined } : {}), ...(allowedFrameProps.includes('maxHeight') ? { maxHeight: undefined } : {}), ...(allowedFrameProps.includes('overflow') ? { overflow: undefined } : {}), + ...(allowedFrameProps.includes('overflow') ? { flex: undefined } : {}), ...(allowedFrameProps.includes('pointerEvents') ? { pointerEvents: undefined } : {}), }, argTypes, diff --git a/packages/connect-ui/src/components/Passphrase/PassphraseTypeCard.tsx b/packages/connect-ui/src/components/Passphrase/PassphraseTypeCard.tsx index 3136dbb7f01..93e8611192e 100644 --- a/packages/connect-ui/src/components/Passphrase/PassphraseTypeCard.tsx +++ b/packages/connect-ui/src/components/Passphrase/PassphraseTypeCard.tsx @@ -351,7 +351,6 @@ export const PassphraseTypeCard = (props: PassphraseTypeCardLegacyProps) => { })} onChange={onPassphraseChange} value={displayValue} - hasBottomPadding={false} innerRef={ref} bottomText={ isTooLong ? ( diff --git a/packages/connect-ui/src/components/Passphrase/PassphraseTypeCardContent.tsx b/packages/connect-ui/src/components/Passphrase/PassphraseTypeCardContent.tsx index 05adb990144..f7402bf914e 100644 --- a/packages/connect-ui/src/components/Passphrase/PassphraseTypeCardContent.tsx +++ b/packages/connect-ui/src/components/Passphrase/PassphraseTypeCardContent.tsx @@ -141,7 +141,6 @@ export const PassphraseTypeCardContent = ({ })} onChange={onPassphraseChange} value={displayValue} - hasBottomPadding={false} innerRef={innerRef} bottomText={ isPassphraseTooLong ? ( diff --git a/packages/product-components/src/components/PassphraseTypeCard/PassphraseTypeCardContent.tsx b/packages/product-components/src/components/PassphraseTypeCard/PassphraseTypeCardContent.tsx index 8e4fb932b2f..de26963b575 100644 --- a/packages/product-components/src/components/PassphraseTypeCard/PassphraseTypeCardContent.tsx +++ b/packages/product-components/src/components/PassphraseTypeCard/PassphraseTypeCardContent.tsx @@ -150,7 +150,6 @@ export const PassphraseTypeCardContent = ({ })} onChange={onPassphraseChange} value={displayValue} - hasBottomPadding={false} innerRef={innerRef} bottomText={ isPassphraseTooLong ? ( diff --git a/packages/suite-data/files/translations/cs.json b/packages/suite-data/files/translations/cs.json index f0804f7b413..b00c26459ec 100644 --- a/packages/suite-data/files/translations/cs.json +++ b/packages/suite-data/files/translations/cs.json @@ -1773,7 +1773,7 @@ "TR_STAKE_STAKING_PROCESS": "Proces stakingu", "TR_STAKE_START_STAKING": "Začněte stakovat", "TR_STAKE_TIME_TO_CLAIM": "Čas na výběr", - "TR_STAKE_TOTAL_PENDING": "Celková výše staku čekající na vyřízení:", + "TR_STAKE_TOTAL_PENDING": "Celková výše staku čekající na vyřízení", "TR_STAKE_TREZOR_NO_LIABILITY": "Při stakingu přechází odpovědnost za zabezpečení vašich prostředků z Trezoru na Everstake.", "TR_STAKE_UNSTAKE": "Zrušit staking", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "Staking zrušen a připraveno na výběr", diff --git a/packages/suite-data/files/translations/de.json b/packages/suite-data/files/translations/de.json index 1799c0204cd..16c6dd82e58 100644 --- a/packages/suite-data/files/translations/de.json +++ b/packages/suite-data/files/translations/de.json @@ -1773,7 +1773,7 @@ "TR_STAKE_STAKING_PROCESS": "Staking-Prozess", "TR_STAKE_START_STAKING": "Staking beginnen", "TR_STAKE_TIME_TO_CLAIM": "Zeit für einen Anspruch", - "TR_STAKE_TOTAL_PENDING": "Ausstehendes Staking insgesamt:", + "TR_STAKE_TOTAL_PENDING": "Ausstehendes Staking insgesamt", "TR_STAKE_TREZOR_NO_LIABILITY": "Beim Staking wird die Verantwortung für die Sicherheit deiner Assets von Trezor auf Everstake übertragen.", "TR_STAKE_UNSTAKE": "Unstaking", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "Anspruchsberechtigung bei Unstaking", diff --git a/packages/suite-data/files/translations/en.json b/packages/suite-data/files/translations/en.json index 3f4d0afcac2..9413aea11eb 100644 --- a/packages/suite-data/files/translations/en.json +++ b/packages/suite-data/files/translations/en.json @@ -1773,7 +1773,7 @@ "TR_STAKE_STAKING_PROCESS": "Staking process", "TR_STAKE_START_STAKING": "Start staking", "TR_STAKE_TIME_TO_CLAIM": "Time to claim", - "TR_STAKE_TOTAL_PENDING": "Total stake pending:", + "TR_STAKE_TOTAL_PENDING": "Total stake pending", "TR_STAKE_TREZOR_NO_LIABILITY": "When staking, the responsibility for your funds' security transitions from your Trezor to Everstake.", "TR_STAKE_UNSTAKE": "Unstake", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "Unstaked and ready to claim", diff --git a/packages/suite-data/files/translations/es.json b/packages/suite-data/files/translations/es.json index 9059706acff..df5234b3ec3 100644 --- a/packages/suite-data/files/translations/es.json +++ b/packages/suite-data/files/translations/es.json @@ -1773,7 +1773,7 @@ "TR_STAKE_STAKING_PROCESS": "Proceso de staking", "TR_STAKE_START_STAKING": "Empieza a hacer staking", "TR_STAKE_TIME_TO_CLAIM": "Es el momento de reclamar", - "TR_STAKE_TOTAL_PENDING": "Cantidad de stake pendiente:", + "TR_STAKE_TOTAL_PENDING": "Cantidad de stake pendiente", "TR_STAKE_TREZOR_NO_LIABILITY": "Al hacer staking, la responsabilidad de la seguridad de tus fondos pasa de tu Trezor a Everstake.", "TR_STAKE_UNSTAKE": "Quitar el stake", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "Sin stake y listo para reclamar", diff --git a/packages/suite-data/files/translations/fr.json b/packages/suite-data/files/translations/fr.json index c386b5ae3e9..0aadcdd56e0 100644 --- a/packages/suite-data/files/translations/fr.json +++ b/packages/suite-data/files/translations/fr.json @@ -1773,7 +1773,7 @@ "TR_STAKE_STAKING_PROCESS": "Processus de staking", "TR_STAKE_START_STAKING": "Commencer à staker", "TR_STAKE_TIME_TO_CLAIM": "Délai de demande", - "TR_STAKE_TOTAL_PENDING": "Total du staking en cours :", + "TR_STAKE_TOTAL_PENDING": "Total du staking en cours", "TR_STAKE_TREZOR_NO_LIABILITY": "Lors du staking, la responsabilité de la sécurité de vos fonds passe de votre Trezor à Everstake.", "TR_STAKE_UNSTAKE": "Unstaker", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "Unstaké et prêt à être demandé", diff --git a/packages/suite-data/files/translations/hu.json b/packages/suite-data/files/translations/hu.json index e52fdd09966..88a8f23bfc4 100644 --- a/packages/suite-data/files/translations/hu.json +++ b/packages/suite-data/files/translations/hu.json @@ -1747,7 +1747,7 @@ "TR_STAKE_STAKING_PROCESS": "Stake-elési folyamat", "TR_STAKE_START_STAKING": "Stake-elés megkezdése", "TR_STAKE_TIME_TO_CLAIM": "Idő az igénylésre", - "TR_STAKE_TOTAL_PENDING": "Teljes stake függőben:", + "TR_STAKE_TOTAL_PENDING": "Teljes stake függőben", "TR_STAKE_TREZOR_NO_LIABILITY": "A Trezor nem vállal felelősséget az Everstake biztonsági garanciáiért. A Trezor nem kezeli a stake-elt pénzed biztonságát.", "TR_STAKE_UNSTAKE": "Stake feloldása", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "Stake feloldva és készen áll az igénylésre", diff --git a/packages/suite-data/files/translations/it.json b/packages/suite-data/files/translations/it.json index ddbedb69a5f..989e2d6e93c 100644 --- a/packages/suite-data/files/translations/it.json +++ b/packages/suite-data/files/translations/it.json @@ -1773,7 +1773,7 @@ "TR_STAKE_STAKING_PROCESS": "Processo di staking", "TR_STAKE_START_STAKING": "Inizia a fare staking", "TR_STAKE_TIME_TO_CLAIM": "Tempo per la richiesta", - "TR_STAKE_TOTAL_PENDING": "Totale staking in sospeso:", + "TR_STAKE_TOTAL_PENDING": "Totale staking in sospeso", "TR_STAKE_TREZOR_NO_LIABILITY": "Quando si effettua lo staking, la responsabilità della sicurezza delle transazioni relative ai fondi passa da Trezor a Everstake.", "TR_STAKE_UNSTAKE": "Esegui unstaking", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "Non più in staking e richiedibili", diff --git a/packages/suite-data/files/translations/ja.json b/packages/suite-data/files/translations/ja.json index 1e2af30b021..3bae1b9685a 100644 --- a/packages/suite-data/files/translations/ja.json +++ b/packages/suite-data/files/translations/ja.json @@ -1773,7 +1773,7 @@ "TR_STAKE_STAKING_PROCESS": "ステークの手順", "TR_STAKE_START_STAKING": "ステーキングを開始", "TR_STAKE_TIME_TO_CLAIM": "請求の時期", - "TR_STAKE_TOTAL_PENDING": "保留中のステーク合計:", + "TR_STAKE_TOTAL_PENDING": "保留中のステーク合計", "TR_STAKE_TREZOR_NO_LIABILITY": "ステーキングの際、お客様の資金の安全に対する責任は、お客様のTrezorからEverstakeに移行します。", "TR_STAKE_UNSTAKE": "ステーク解除", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "ステークが解除され、請求の準備ができています", diff --git a/packages/suite-data/files/translations/pt.json b/packages/suite-data/files/translations/pt.json index 49d61ee82ad..bcf3d59eac0 100644 --- a/packages/suite-data/files/translations/pt.json +++ b/packages/suite-data/files/translations/pt.json @@ -1773,7 +1773,7 @@ "TR_STAKE_STAKING_PROCESS": "Processo para inclusão no stake", "TR_STAKE_START_STAKING": "Comece a fazer stake", "TR_STAKE_TIME_TO_CLAIM": "É hora de resgatar", - "TR_STAKE_TOTAL_PENDING": "Total em stake pendente:", + "TR_STAKE_TOTAL_PENDING": "Total em stake pendente", "TR_STAKE_TREZOR_NO_LIABILITY": "Ao apostar, a responsabilidade pela segurança de seus fundos passa da sua Trezor para a Everstake.", "TR_STAKE_UNSTAKE": "Remover do stake", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "Removido do stake e pronto para resgate", diff --git a/packages/suite-data/files/translations/sk.json b/packages/suite-data/files/translations/sk.json index 36c83cfcf21..610a9ba60ca 100644 --- a/packages/suite-data/files/translations/sk.json +++ b/packages/suite-data/files/translations/sk.json @@ -1554,7 +1554,7 @@ "TR_STAKE_STAKING_IS": "Staking involves temporarily locking your Ethereum assets to support the blockchain's operation. In return, you'll earn additional Ethereum as a reward.", "TR_STAKE_START_STAKING": "Start staking", "TR_STAKE_TIME_TO_CLAIM": "Time to claim", - "TR_STAKE_TOTAL_PENDING": "Total stake pending:", + "TR_STAKE_TOTAL_PENDING": "Total stake pending", "TR_STAKE_TREZOR_NO_LIABILITY": "When staking, the responsibility for your funds' security transitions from your Trezor to Everstake.", "TR_STAKE_UNSTAKE": "Unstake", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "Unstaked and ready to claim", diff --git a/packages/suite-data/files/translations/tr.json b/packages/suite-data/files/translations/tr.json index 8bb0683c922..1e1445808ac 100644 --- a/packages/suite-data/files/translations/tr.json +++ b/packages/suite-data/files/translations/tr.json @@ -1773,7 +1773,7 @@ "TR_STAKE_STAKING_PROCESS": "Stake etme süreci", "TR_STAKE_START_STAKING": "Stake etmeye başla", "TR_STAKE_TIME_TO_CLAIM": "Talep etme zamanı", - "TR_STAKE_TOTAL_PENDING": "Toplam stake beklemede:", + "TR_STAKE_TOTAL_PENDING": "Toplam stake beklemede", "TR_STAKE_TREZOR_NO_LIABILITY": "Stake işlemi sırasında, fonlarınızın güvenliğine ilişkin sorumluluk Trezor'unuzdan Everstake'e geçer.", "TR_STAKE_UNSTAKE": "Unstake et", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "Unstake edildi ve talep etmeye hazır", diff --git a/packages/suite-data/files/translations/uk.json b/packages/suite-data/files/translations/uk.json index 16f2649709b..0750e29fda3 100644 --- a/packages/suite-data/files/translations/uk.json +++ b/packages/suite-data/files/translations/uk.json @@ -1554,7 +1554,7 @@ "TR_STAKE_STAKING_IS": "Стейкінг передбачає тимчасове блокування ваших активів Ethereum для підтримки роботи блокчейну. В обмін на це ви отримаєте додаткову кількість Ethereum в якості винагороди.", "TR_STAKE_START_STAKING": "Розпочати Стейкінг", "TR_STAKE_TIME_TO_CLAIM": "Час ", - "TR_STAKE_TOTAL_PENDING": "Загальний поточний стейкінг :", + "TR_STAKE_TOTAL_PENDING": "Загальний поточний стейкінг", "TR_STAKE_TREZOR_NO_LIABILITY": "Під час стейкінгу відповідальність за безпеку ваших коштів переходить від вашого Trezor до Everstake.", "TR_STAKE_UNSTAKE": "Зняти зі стейкінгу", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "Зняти зі стейкінгу та будьте готові до клейму", diff --git a/packages/suite-data/files/translations/vi.json b/packages/suite-data/files/translations/vi.json index b15e8edf10f..392d8300dfc 100644 --- a/packages/suite-data/files/translations/vi.json +++ b/packages/suite-data/files/translations/vi.json @@ -1690,7 +1690,7 @@ "TR_STAKE_STAKING_IS": "Staking involves temporarily locking your Ethereum assets to support the blockchain's operation. In return, you'll earn additional Ethereum as a reward.", "TR_STAKE_START_STAKING": "Start staking", "TR_STAKE_TIME_TO_CLAIM": "Time to claim", - "TR_STAKE_TOTAL_PENDING": "Total stake pending:", + "TR_STAKE_TOTAL_PENDING": "Total stake pending", "TR_STAKE_TREZOR_NO_LIABILITY": "When staking, the responsibility for your funds' security transitions from your Trezor to Everstake.", "TR_STAKE_UNSTAKE": "Unstake", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "Unstaked and ready to claim", diff --git a/packages/suite-data/files/translations/zh.json b/packages/suite-data/files/translations/zh.json index b9d063e0268..e95e47232a3 100644 --- a/packages/suite-data/files/translations/zh.json +++ b/packages/suite-data/files/translations/zh.json @@ -1773,7 +1773,7 @@ "TR_STAKE_STAKING_PROCESS": "质押过程", "TR_STAKE_START_STAKING": "开始质押", "TR_STAKE_TIME_TO_CLAIM": "认领奖励时间", - "TR_STAKE_TOTAL_PENDING": "总共待处理的质押: ", + "TR_STAKE_TOTAL_PENDING": "总共待处理的质押", "TR_STAKE_TREZOR_NO_LIABILITY": "在质押时、您的资金安全责任将从您的 Trezor 设备转移到 Everstake。", "TR_STAKE_UNSTAKE": "解除质押", "TR_STAKE_UNSTAKED_AND_READY_TO_CLAIM": "解除质押、随时可认领", diff --git a/packages/suite/src/components/dashboard/DashboardSection.tsx b/packages/suite/src/components/dashboard/DashboardSection.tsx index 4057e9f589f..0d688597f82 100644 --- a/packages/suite/src/components/dashboard/DashboardSection.tsx +++ b/packages/suite/src/components/dashboard/DashboardSection.tsx @@ -1,38 +1,31 @@ import { Ref, forwardRef, ReactElement, HTMLAttributes } from 'react'; -import styled from 'styled-components'; +import { H3, Column, Row } from '@trezor/components'; +import { spacings } from '@trezor/theme'; -import { H3 } from '@trezor/components'; - -const Wrapper = styled.section` - display: flex; - flex-direction: column; -`; -const Header = styled.header` - display: flex; - justify-content: space-between; - padding-bottom: 25px; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const Title = styled(H3)` - display: flex; - align-items: center; -`; - -interface DashboardSectionProps extends HTMLAttributes { +type DashboardSectionProps = HTMLAttributes & { heading: ReactElement; actions?: ReactElement; -} + 'data-testid'?: string; +}; export const DashboardSection = forwardRef( - ({ heading, actions, children, ...rest }: DashboardSectionProps, ref: Ref) => ( - -
- {heading && {heading}} - {actions &&
{actions}
} -
- {children} -
+ ( + { heading, actions, children, 'data-testid': dataTestId, ...rest }: DashboardSectionProps, + ref: Ref, + ) => ( +
+ + + {heading && ( +

+ {heading} +

+ )} + {actions &&
{actions}
} +
+ {children} +
+
), ); diff --git a/packages/suite/src/components/suite/ChangeDeviceLabel.tsx b/packages/suite/src/components/suite/ChangeDeviceLabel.tsx index ba0582c1b98..90626fc69fc 100644 --- a/packages/suite/src/components/suite/ChangeDeviceLabel.tsx +++ b/packages/suite/src/components/suite/ChangeDeviceLabel.tsx @@ -81,7 +81,6 @@ export const ChangeDeviceLabel = ({ inputState={error ? 'error' : undefined} onChange={handleChange} data-testid="@settings/device/label-input" - hasBottomPadding={false} size={isVertical ? 'small' : 'large'} /> - - - ); -}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ClaimModal/ClaimModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ClaimModal/ClaimModal.tsx index ce45d30c33a..5f358aed748 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ClaimModal/ClaimModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ClaimModal/ClaimModal.tsx @@ -1,39 +1,137 @@ -import styled from 'styled-components'; +import { useEffect } from 'react'; -import { useSelector } from 'src/hooks/suite'; -import { Modal, Translation } from 'src/components/suite'; +import { Paragraph, Tooltip, Banner, Card, Column, InfoRow, NewModal } from '@trezor/components'; +import { spacings } from '@trezor/theme'; +import { getAccountEverstakeStakingPool } from '@suite-common/wallet-utils'; +import type { SelectedAccountLoaded } from '@suite-common/wallet-types'; -import { ClaimModalContent } from './ClaimModalContent'; - -const StyledModal = styled(Modal)` - width: 512px; - text-align: left; -`; +import { Fees } from 'src/components/wallet/Fees/Fees'; +import { Translation, FiatValue, FormattedCryptoAmount } from 'src/components/suite'; +import { useDevice, useSelector } from 'src/hooks/suite'; +import { useClaimEthForm } from 'src/hooks/wallet/useClaimEthForm'; +import { CRYPTO_INPUT } from 'src/types/wallet/stakeForms'; +import { useMessageSystemStaking } from 'src/hooks/suite/useMessageSystemStaking'; interface ClaimModalModalProps { onCancel?: () => void; } export const ClaimModal = ({ onCancel }: ClaimModalModalProps) => { - const selectedAccount = useSelector(state => state.wallet.selectedAccount); + const { device, isLocked } = useDevice(); + const selectedAccount = useSelector( + state => state.wallet.selectedAccount, + ) as SelectedAccountLoaded; + const { isClaimingDisabled, claimingMessageContent } = useMessageSystemStaking(); + + const { + account, + formState: { errors, isSubmitting }, + register, + control, + setValue, + getValues, + changeFeeLevel, + feeInfo, + composedLevels, + watch, + isComposing, + handleSubmit, + onClaimChange, + signTx, + } = useClaimEthForm({ selectedAccount }); + + const hasValues = Boolean(watch(CRYPTO_INPUT)); + // used instead of formState.isValid, which is sometimes returning false even if there are no errors + const formIsValid = Object.keys(errors).length === 0; + + const { claimableAmount = '0' } = getAccountEverstakeStakingPool(selectedAccount.account) ?? {}; + const isDisabled = + !(formIsValid && hasValues) || isSubmitting || isLocked() || !device?.available; + + useEffect(() => { + onClaimChange(claimableAmount); + }, [onClaimChange, claimableAmount]); - const { account, status } = selectedAccount; // it shouldn't be possible to open this modal without having selected account - if (!account || status !== 'loaded') return null; + if (!selectedAccount?.account || selectedAccount?.status !== 'loaded') return null; return ( - } - subheading={ - - } + size="small" onCancel={onCancel} + bottomContent={ + <> + + + + + + + + + + } > - - +
+ + }> + + + + + + + + + } + > + + + + + } + showFeeWhilePending={false} + /> + + + {errors[CRYPTO_INPUT] ? ( + {errors[CRYPTO_INPUT]?.message} + ) : ( + + + + )} + +
+ ); }; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ClaimModal/ClaimModalContent.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ClaimModal/ClaimModalContent.tsx deleted file mode 100644 index 14b23016c5d..00000000000 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ClaimModal/ClaimModalContent.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { SelectedAccountLoaded } from '@suite-common/wallet-types'; - -import { ClaimEthFormContext, useClaimEthForm } from 'src/hooks/wallet/useClaimEthForm'; - -import { ClaimEthForm } from './ClaimEthForm'; - -interface ClaimModalContentProps { - selectedAccount: SelectedAccountLoaded; -} - -export const ClaimModalContent = ({ selectedAccount }: ClaimModalContentProps) => { - const claimEthContextValues = useClaimEthForm({ selectedAccount }); - - return ( - - - - ); -}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ClaimModal/Fees.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ClaimModal/Fees.tsx deleted file mode 100644 index 760f7319b75..00000000000 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/ClaimModal/Fees.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import styled from 'styled-components'; - -import { Fees } from 'src/components/wallet/Fees/Fees'; -import { useClaimEthFormContext } from 'src/hooks/wallet/useClaimEthForm'; -import { Translation } from 'src/components/suite'; - -const StyledCard = styled.div` - display: flex; - flex-direction: column; - justify-items: space-between; - margin: 25px 0; -`; - -const ClaimFees = () => { - const { - formState: { errors }, - register, - control, - setValue, - getValues, - account, - changeFeeLevel, - feeInfo, - composedLevels, - } = useClaimEthFormContext(); - - return ( - - } - showFeeWhilePending={false} - /> - - ); -}; - -export default ClaimFees; diff --git a/packages/suite/src/components/wallet/Fees/CustomFee.tsx b/packages/suite/src/components/wallet/Fees/CustomFee.tsx index fad956e1dfa..2007dd54f58 100644 --- a/packages/suite/src/components/wallet/Fees/CustomFee.tsx +++ b/packages/suite/src/components/wallet/Fees/CustomFee.tsx @@ -162,7 +162,6 @@ export const CustomFee = ({ name={FEE_LIMIT} data-testid={FEE_LIMIT} onChange={changeFeeLimit} - hasBottomPadding={false} bottomText={ feeLimitError?.message ? ( ({ name={FEE_PER_UNIT} data-testid={FEE_PER_UNIT} rules={feeRules} - hasBottomPadding={false} bottomText={feePerUnitError?.message || null} /> diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index 606cb4a31ea..6d1360b65a0 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -8911,7 +8911,7 @@ const messages = defineMessagesWithTypeCheck({ }, TR_STAKE_TOTAL_PENDING: { id: 'TR_STAKE_TOTAL_PENDING', - defaultMessage: 'Total stake pending:', + defaultMessage: 'Total stake pending', }, TR_STAKE_UNSTAKING: { id: 'TR_STAKE_UNSTAKING', diff --git a/packages/suite/src/views/settings/SettingsGeneral/TorSnowflake.tsx b/packages/suite/src/views/settings/SettingsGeneral/TorSnowflake.tsx index 6849e111a5e..acb15cff5dd 100644 --- a/packages/suite/src/views/settings/SettingsGeneral/TorSnowflake.tsx +++ b/packages/suite/src/views/settings/SettingsGeneral/TorSnowflake.tsx @@ -108,7 +108,6 @@ export const TorSnowflake = () => { placeholder="" inputState={error ? 'error' : undefined} onChange={handleChange} - hasBottomPadding={false} size="small" /> + + + + ); +}; diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/InstantStakeBanner.tsx b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/InstantStakeBanner.tsx index 952ef01b78d..885d6df5704 100644 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/InstantStakeBanner.tsx +++ b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/InstantStakeBanner.tsx @@ -1,10 +1,9 @@ import { useEffect, useRef, useState } from 'react'; -import styled, { useTheme } from 'styled-components'; import { fromWei } from 'web3-utils'; -import { Banner, Column, H3, Icon, Paragraph, Row } from '@trezor/components'; -import { spacings, spacingsPx } from '@trezor/theme'; +import { Banner, Column, H3, Paragraph } from '@trezor/components'; +import { spacings } from '@trezor/theme'; import { StakeType, WalletAccountTransaction } from '@suite-common/wallet-types'; import { InternalTransfer } from '@trezor/connect'; @@ -13,16 +12,6 @@ import { Translation } from 'src/components/suite'; import { getChangedInternalTx, getInstantStakeType } from 'src/utils/suite/stake'; import { selectSelectedAccount } from 'src/reducers/wallet/selectedAccountReducer'; -const IconWrapper = styled.div` - background: ${({ theme }) => theme.backgroundAlertYellowBold}; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - min-width: ${spacingsPx.xxxxl}; - min-height: ${spacingsPx.xxxxl}; -`; - const getSubheadingTranslationId = (stakeType: StakeType) => { if (stakeType === 'stake') return 'TR_STAKING_INSTANTLY_STAKED'; @@ -51,7 +40,6 @@ export const InstantStakeBanner = ({ const [instantStakeTransfer, setInstantStakeTransfer] = useState(null); const [isBannerShown, setIsBannerShown] = useState(false); - const theme = useTheme(); const prevTxs = useRef(txs); useEffect(() => { @@ -81,40 +69,35 @@ export const InstantStakeBanner = ({ return ( } > - - - - - -

- -

- - - -
-
+ +

+ +

+ + + +
); }; diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/PayoutCard.tsx b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/PayoutCard.tsx index 439da9ccfae..54b0f44f014 100644 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/PayoutCard.tsx +++ b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/PayoutCard.tsx @@ -1,9 +1,8 @@ import { useMemo } from 'react'; -import { useTheme } from 'styled-components'; - import { BigNumber } from '@trezor/utils/src/bigNumber'; -import { Card, Column, Icon } from '@trezor/components'; +import { Card, Column, Icon, Paragraph } from '@trezor/components'; +import { spacings } from '@trezor/theme'; import { BACKUP_REWARD_PAYOUT_DAYS } from '@suite-common/wallet-constants'; import { getAccountAutocompoundBalance } from '@suite-common/wallet-utils'; @@ -11,8 +10,6 @@ import { Translation } from 'src/components/suite'; import { selectSelectedAccount } from 'src/reducers/wallet/selectedAccountReducer'; import { useSelector } from 'src/hooks/suite'; -import { AccentP, CardBottomContent, GreyP } from './styled'; - interface PayoutCardProps { nextRewardPayout?: number | null; daysToAddToPool?: number; @@ -24,7 +21,6 @@ export const PayoutCard = ({ daysToAddToPool, validatorWithdrawTime, }: PayoutCardProps) => { - const theme = useTheme(); const selectedAccount = useSelector(selectSelectedAccount); const autocompoundBalance = getAccountAutocompoundBalance(selectedAccount); @@ -41,12 +37,12 @@ export const PayoutCard = ({ }, [autocompoundBalance, daysToAddToPool, nextRewardPayout, validatorWithdrawTime]); return ( - - - + + + - - + + {payout === undefined ? ( )} - - + + - - + + ); diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/ProgressLabels/ProgressLabel.tsx b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/ProgressLabels/ProgressLabel.tsx index 2d687afd428..b8088193895 100644 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/ProgressLabels/ProgressLabel.tsx +++ b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/ProgressLabels/ProgressLabel.tsx @@ -1,55 +1,69 @@ import { ReactNode, useEffect, useRef, useState } from 'react'; -import styled, { DefaultTheme, useTheme } from 'styled-components'; +import styled, { DefaultTheme } from 'styled-components'; -import { Icon, variables } from '@trezor/components'; -import { borders, spacingsPx } from '@trezor/theme'; +import { IconCircle, Text, Row } from '@trezor/components'; +import { borders, spacings, spacingsPx } from '@trezor/theme'; +import { IconCirclePaddingType } from '@trezor/components/src/components/IconCircle/types'; import { ProgressLabelState } from './types'; const DEFAULT_LABEL_HEIGHT = 48; -const getProgressStateColor = ({ +const mapProgressStateToBackground = ({ theme, $progressState, }: { theme: DefaultTheme; $progressState: ProgressLabelState; }) => { - if ($progressState === 'active') { - return theme.backgroundAlertYellowSubtleOnElevation2; + switch ($progressState) { + case 'active': + return theme.backgroundAlertYellowSubtleOnElevation2; + case 'done': + return theme.backgroundPrimarySubtleOnElevation1; + default: + return theme.backgroundSurfaceElevation2; } +}; + +const getProgressStateIcon = (progressState: ProgressLabelState) => { + const props = { + paddingType: 'small' as IconCirclePaddingType, + size: 18, + hasBorder: false, + }; - if ($progressState === 'done') { - return theme.backgroundPrimarySubtleOnElevation1; + switch (progressState) { + case 'active': + return ; + case 'done': + return ; + default: + return ; } +}; - return theme.backgroundSurfaceElevation2; +const getProgressStateVariant = (progressState: ProgressLabelState) => { + switch (progressState) { + case 'active': + return 'warning'; + case 'done': + return 'primary'; + default: + return 'tertiary'; + } }; const ProgressLabelItem = styled.div<{ $progressState: ProgressLabelState; $currentHeight?: number; }>` - background: ${({ theme, $progressState }) => getProgressStateColor({ theme, $progressState })}; - display: flex; - gap: ${spacingsPx.sm}; + background: ${mapProgressStateToBackground}; + flex: 1 0 220px; padding: ${spacingsPx.xs} ${spacingsPx.sm}; - align-items: center; border-radius: ${borders.radii.full}; min-height: ${DEFAULT_LABEL_HEIGHT}px; - font-weight: ${variables.FONT_WEIGHT.MEDIUM}; - font-size: ${variables.FONT_SIZE.SMALL}; - color: ${({ theme, $progressState }) => { - if ($progressState === 'active') { - return theme.textAlertYellow; - } - if ($progressState === 'done') { - return theme.textPrimaryDefault; - } - - return theme.textSubdued; - }}; &:not(:last-of-type) { position: relative; @@ -64,8 +78,7 @@ const ProgressLabelItem = styled.div<{ top: 0; right: -12px; z-index: 2; - border-left: 12px solid - ${({ theme, $progressState }) => getProgressStateColor({ theme, $progressState })}; + border-left: 12px solid ${mapProgressStateToBackground}; border-top: ${({ $currentHeight = DEFAULT_LABEL_HEIGHT }) => $currentHeight / 2}px solid transparent; border-bottom: ${({ $currentHeight = DEFAULT_LABEL_HEIGHT }) => $currentHeight / 2}px @@ -94,40 +107,12 @@ const ProgressLabelItem = styled.div<{ } `; -const IconWrapper = styled.div<{ $progressState: ProgressLabelState }>` - background: ${({ theme, $progressState }) => { - if ($progressState === 'active') { - return theme.backgroundAlertYellowSubtleOnElevation0; - } - if ($progressState === 'done') { - return theme.backgroundPrimarySubtleOnElevation0; - } - - return theme.backgroundSurfaceElevationNegative; - }}; - border-radius: 100%; - min-width: 24px; - min-height: 24px; - display: flex; - align-items: center; - justify-content: center; -`; - -const IconDot = styled.div` - width: 4px; - height: 4px; - border-radius: 100%; - background: ${({ theme }) => theme.backgroundNeutralBold}; -`; - interface ProgressLabelProps { children: ReactNode; progressState: ProgressLabelState; } export const ProgressLabel = ({ children, progressState = 'stale' }: ProgressLabelProps) => { - const theme = useTheme(); - // Watch height to adjust element's edge shape sizes (triangle, flag tale) const ref = useRef(null); const [currentHeight, setCurrentHeight] = useState(DEFAULT_LABEL_HEIGHT); @@ -148,22 +133,18 @@ export const ProgressLabel = ({ children, progressState = 'stale' }: ProgressLab }; }, [currentHeight]); - const getProgressStateIcon = () => { - if (progressState === 'active') { - return ; - } - - if (progressState === 'done') { - return ; - } - - return ; - }; - return ( - {getProgressStateIcon()} - {children} + + {getProgressStateIcon(progressState)} + + {children} + + ); }; diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/ProgressLabels/ProgressLabels.tsx b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/ProgressLabels/ProgressLabels.tsx index 0fe2d51d825..9f8a677a950 100644 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/ProgressLabels/ProgressLabels.tsx +++ b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/ProgressLabels/ProgressLabels.tsx @@ -1,30 +1,19 @@ -import styled from 'styled-components'; - -import { spacingsPx } from '@trezor/theme'; +import { spacings } from '@trezor/theme'; +import { Row } from '@trezor/components'; import { ProgressLabelData } from './types'; import { ProgressLabel } from './ProgressLabel'; -const ProgressLabelsList = styled.div` - display: flex; - flex-wrap: wrap; - row-gap: ${spacingsPx.xs}; - - & > div { - flex: 1 0 220px; - } -`; - interface ProgressLabelsProps { labels: ProgressLabelData[]; } export const ProgressLabels = ({ labels }: ProgressLabelsProps) => ( - + {labels.map(label => ( {label.children} ))} - + ); diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/StakingCard.tsx b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/StakingCard.tsx index f9d14778222..d7677bfca87 100644 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/StakingCard.tsx +++ b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/StakingCard.tsx @@ -1,84 +1,78 @@ -import styled, { useTheme } from 'styled-components'; - import { BigNumber } from '@trezor/utils/src/bigNumber'; -import { Badge, Button, Card, Icon, Row, Tooltip, variables } from '@trezor/components'; -import { spacings, spacingsPx } from '@trezor/theme'; +import { + Badge, + Button, + Card, + Icon, + Row, + Grid, + Column, + Tooltip, + InfoRow, + Paragraph, + IconName, + useMediaQuery, + variables, +} from '@trezor/components'; +import { spacings } from '@trezor/theme'; import { selectAccountStakeTransactions } from '@suite-common/wallet-core'; import { getAccountEverstakeStakingPool, isPending } from '@suite-common/wallet-utils'; -import { FiatValue, Translation } from 'src/components/suite'; +import { FiatValue, Translation, FormattedCryptoAmount } from 'src/components/suite'; import { useDispatch, useSelector } from 'src/hooks/suite'; import { openModal } from 'src/actions/suite/modalActions'; import { selectSelectedAccount } from 'src/reducers/wallet/selectedAccountReducer'; import { useMessageSystemStaking } from 'src/hooks/suite/useMessageSystemStaking'; -import { InfoBox, ProgressBar } from './styled'; +import { ProgressBar } from './styled'; import { ProgressLabels } from './ProgressLabels/ProgressLabels'; import { useProgressLabelsData } from '../hooks/useProgressLabelsData'; import { useIsTxStatusShown } from '../hooks/useIsTxStatusShown'; -import { TrimmedCryptoAmount } from './TrimmedCryptoAmount'; - -const AmountsWrapper = styled.div<{ $isStakeOrUnstakePending: boolean }>` - display: flex; - gap: ${spacingsPx.sm} ${spacingsPx.xs}; - flex-wrap: wrap; - justify-content: ${({ $isStakeOrUnstakePending }) => - $isStakeOrUnstakePending ? 'space-between' : 'flex-start'}; - - & > div { - margin-right: ${({ $isStakeOrUnstakePending }) => - $isStakeOrUnstakePending ? '0' : 'auto'}; - } -`; - -const AmountHeading = styled.div` - display: flex; - gap: ${spacingsPx.xxs}; - align-items: center; - font-size: ${variables.FONT_SIZE.TINY}; - color: ${({ theme }) => theme.textSubdued}; -`; - -const StyledFiatValue = styled(FiatValue)` - display: block; - font-size: ${variables.FONT_SIZE.SMALL}; - color: ${({ theme }) => theme.textSubdued}; -`; -const ProgressBarWrapper = styled.div` - margin-top: ${spacingsPx.xxxl}; -`; - -const ButtonsWrapper = styled.div` - margin-top: 66px; - display: flex; - gap: ${spacingsPx.xs}; - flex-wrap: wrap; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledButton = styled(Button).attrs(props => ({ - ...props, - variant: 'tertiary', - type: 'button', -}))` - padding: 9px 22px; - font-size: ${variables.FONT_SIZE.NORMAL}; -`; +type ItemProps = { + label: React.ReactNode; + iconName: IconName; + symbol: string; + cryptoAmount: string; + fiatAmount: string; + isReward?: boolean; + 'data-testid': string; +}; -interface StakingCardProps { +const Item = ({ + label, + symbol, + cryptoAmount, + fiatAmount, + iconName, + isReward = false, + 'data-testid': dataTestId, +}: ItemProps) => ( + + + + + + + {({ value }) => (value ? {value} : null)} + + + +); + +type StakingCardProps = { isValidatorsQueueLoading?: boolean; daysToAddToPool?: number; daysToUnstake?: number; -} +}; export const StakingCard = ({ isValidatorsQueueLoading, daysToAddToPool, daysToUnstake, }: StakingCardProps) => { - const theme = useTheme(); const selectedAccount = useSelector(selectSelectedAccount); + const isBelowLaptop = useMediaQuery(`(max-width: ${variables.SCREEN_SIZE.LG})`); const { isStakingDisabled, @@ -140,134 +134,92 @@ export const StakingCard = ({ return ( - {(isStakeConfirming || isTxStatusShown) && ( - + + {(isStakeConfirming || isTxStatusShown) && ( - - )} - - - {isStakePending && ( -
- - - - + )} - + {isStakePending && ( + } + iconName="spinnerGap" symbol={selectedAccount?.symbol} + cryptoAmount={totalPendingStakeBalance} + fiatAmount={totalPendingStakeBalance} + data-testid="@account/staking/pending" /> + )} - - {({ value }) => (value ? {value} : null)} - -
- )} - -
- - - - - - - - } + iconName="lock" symbol={selectedAccount?.symbol} - showApproximationIndicator - > - {({ value }) => (value ? {value} : null)} - -
- -
- - - - - } - > - - - - - - - - - - - - {({ value }) => (value ? {value} : null)} - -
- - {isPendingUnstakeShown && ( -
- - - - {' '} - {isDaysToUnstakeShown && ( - <> - (~ + + + - ) - - )} - - + } + > + + + + + + + + + } + iconName="plusCircle" + isReward + cryptoAmount={restakedReward} + fiatAmount={restakedReward} + data-testid="@account/staking/rewards" + symbol={selectedAccount?.symbol} + /> - + {' '} + {isDaysToUnstakeShown && ( + <> + (~ + + ) + + )} + + } + iconName="spinnerGap" symbol={selectedAccount?.symbol} + cryptoAmount={withdrawTotalAmount} + fiatAmount={withdrawTotalAmount} + data-testid="@account/staking/unstaking" /> + )} + - - {({ value }) => (value ? {value} : null)} - -
- )} -
- - - - - - - - - - - - - - - + + + + + + + + +
); }; diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/StakingDashboard.tsx b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/StakingDashboard.tsx index 3be19d3928b..b64c483a6ad 100644 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/StakingDashboard.tsx +++ b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/StakingDashboard.tsx @@ -1,9 +1,7 @@ import { useEffect, useMemo } from 'react'; -import styled from 'styled-components'; - -import { variables } from '@trezor/components'; -import { spacingsPx } from '@trezor/theme'; +import { Column, Grid, useMediaQuery, variables } from '@trezor/components'; +import { spacings } from '@trezor/theme'; import { fetchAllTransactionsForAccountThunk, selectAccountStakeTransactions, @@ -15,45 +13,21 @@ import { import { selectSelectedAccount } from 'src/reducers/wallet/selectedAccountReducer'; import { useDispatch, useSelector } from 'src/hooks/suite'; -import { Divider, Translation } from 'src/components/suite'; +import { Translation } from 'src/components/suite'; import { DashboardSection } from 'src/components/dashboard'; import { getDaysToAddToPool, getDaysToUnstake } from 'src/utils/suite/stake'; import { StakingCard } from './StakingCard'; import { ApyCard } from './ApyCard'; import { PayoutCard } from './PayoutCard'; -import { ClaimCard } from './claim/ClaimCard'; +import { ClaimCard } from './ClaimCard'; import { Transactions } from './Transactions'; import { InstantStakeBanner } from './InstantStakeBanner'; -const FlexCol = styled.div` - display: flex; - flex-direction: column; - gap: ${spacingsPx.xs}; -`; - -const FlexRow = styled.div` - display: flex; - flex-wrap: wrap; - gap: ${spacingsPx.xs}; - - & > div { - flex: 1 0 205px; - } - - ${variables.SCREEN_QUERY.BELOW_LAPTOP} { - flex-direction: column; - gap: ${spacingsPx.xs}; - - & > div { - flex: 1 0 auto; - } - } -`; - export const StakingDashboard = () => { const account = useSelector(selectSelectedAccount); const accountKey = account?.key ?? ''; + const isBelowLaptop = useMediaQuery(`(max-width: ${variables.SCREEN_SIZE.LG})`); const { data, isLoading } = useSelector(state => selectValidatorsQueue(state, account?.symbol)) || {}; @@ -85,37 +59,34 @@ export const StakingDashboard = () => { const daysToUnstake = getDaysToUnstake(unstakeTxs, data); return ( - <> + }> - - - - - + + + + + + + + + - - - - - - + - - - + ); }; diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/TrimmedCryptoAmount.tsx b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/TrimmedCryptoAmount.tsx deleted file mode 100644 index 6ea5fe53dd7..00000000000 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/TrimmedCryptoAmount.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import styled from 'styled-components'; - -import { spacingsPx } from '@trezor/theme'; -import { Tooltip, variables } from '@trezor/components'; -import { BigNumber } from '@trezor/utils/src/bigNumber'; - -import { FormattedCryptoAmount } from 'src/components/suite'; - -const StyledFormattedCryptoAmount = styled(FormattedCryptoAmount)<{ - $isRewards?: boolean; - $isSmall?: boolean; -}>` - display: block; - margin-top: ${spacingsPx.xs}; - font-size: ${({ $isSmall }) => ($isSmall ? variables.FONT_SIZE.SMALL : variables.FONT_SIZE.H2)}; - color: ${({ $isRewards = false, theme }) => ($isRewards ? theme.textPrimaryDefault : '')}; -`; - -const DEFAULT_MAX_DECIMAL_PLACES = 5; - -interface TrimmedCryptoAmountProps { - value: string | number; - symbol: string; - maxDecimalPlaces?: number; - isRewards?: boolean; - 'data-testid'?: string; -} - -export const TrimmedCryptoAmount = ({ - value, - symbol, - maxDecimalPlaces = DEFAULT_MAX_DECIMAL_PLACES, - isRewards, - 'data-testid': dataTest, -}: TrimmedCryptoAmountProps) => { - const hasDecimals = value.toString().includes('.'); - - if (!hasDecimals) { - return ( - - ); - } - - const valueBig = new BigNumber(value); - const trimmedAmount = valueBig.toFixed(maxDecimalPlaces, 1); - - return ( - }> - - - ); -}; diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/claim/ClaimCard.tsx b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/claim/ClaimCard.tsx deleted file mode 100644 index 6ca42d02b8c..00000000000 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/claim/ClaimCard.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { useEffect, useMemo, useRef } from 'react'; - -import { getAccountEverstakeStakingPool, isPending } from '@suite-common/wallet-utils'; -import { selectAccountClaimTransactions } from '@suite-common/wallet-core'; -import { notificationsActions } from '@suite-common/toast-notifications'; - -import { selectSelectedAccount } from 'src/reducers/wallet/selectedAccountReducer'; -import { useDispatch, useSelector } from 'src/hooks/suite'; - -import { ClaimReadyCard } from './ClaimReadyCard'; -import { ClaimPendingCard } from './ClaimPendingCard'; - -export const ClaimCard = () => { - const selectedAccount = useSelector(selectSelectedAccount); - const claimTxs = useSelector(state => - selectAccountClaimTransactions(state, selectedAccount?.key || ''), - ); - - const isClaimPending = useMemo(() => claimTxs.some(tx => isPending(tx)), [claimTxs]); - - const { canClaim = false, claimableAmount = '0' } = - getAccountEverstakeStakingPool(selectedAccount) ?? {}; - - // Show success message when claim tx confirmation is complete. - const prevIsClaimPending = useRef(false); - const dispatch = useDispatch(); - - useEffect(() => { - // Reset prevIsClaimPending when account changes - prevIsClaimPending.current = false; - }, [selectedAccount?.key]); - - useEffect(() => { - if (prevIsClaimPending.current && !isClaimPending) { - dispatch( - notificationsActions.addToast({ - type: 'successful-claim', - symbol: selectedAccount?.symbol.toUpperCase() || '', - }), - ); - prevIsClaimPending.current = false; - } - - prevIsClaimPending.current = isClaimPending; - }, [dispatch, isClaimPending, selectedAccount?.symbol, selectedAccount?.key]); - - if (!canClaim) return null; - - return isClaimPending ? ( - - ) : ( - - ); -}; diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/claim/ClaimPendingCard.tsx b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/claim/ClaimPendingCard.tsx deleted file mode 100644 index 758f5cddf17..00000000000 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/claim/ClaimPendingCard.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import styled, { useTheme } from 'styled-components'; - -import { Icon } from '@trezor/components'; -import { variables } from '@trezor/components/src/config'; -import { borders, spacingsPx } from '@trezor/theme'; - -import { FiatValue, FormattedCryptoAmount, Translation } from 'src/components/suite'; -import { useSelector } from 'src/hooks/suite'; -import { selectSelectedAccount } from 'src/reducers/wallet/selectedAccountReducer'; - -import { FiatValueWrapper, FormattedCryptoAmountWrapper } from './styled'; - -const StyledCard = styled.div` - border-radius: ${borders.radii.md}; - padding: ${spacingsPx.sm} ${spacingsPx.xxl} ${spacingsPx.md}; - margin-bottom: ${spacingsPx.sm}; - background: ${({ theme }) => theme.backgroundPrimarySubtleOnElevation1}; - position: relative; - overflow: hidden; - - &::before { - content: ''; - display: block; - position: absolute; - left: 0; - top: 0; - width: 8px; - height: 100%; - background: ${({ theme }) => theme.backgroundPrimaryDefault}; - } -`; - -const Flex = styled.div` - display: flex; - gap: ${spacingsPx.lg}; - align-items: center; - flex-wrap: wrap; -`; - -const Heading = styled.div` - margin-bottom: ${spacingsPx.xxs}; - color: ${({ theme }) => theme.textSubdued}; - font-size: ${variables.FONT_SIZE.TINY}; -`; - -interface ClaimPendingCardProps { - claimAmount: string; -} - -export const ClaimPendingCard = ({ claimAmount }: ClaimPendingCardProps) => { - const theme = useTheme(); - const { symbol } = useSelector(selectSelectedAccount) ?? {}; - - if (!symbol) { - return null; - } - - return ( - - - - -
- - - - - - - - - - - -
-
-
- ); -}; diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/claim/ClaimReadyCard.tsx b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/claim/ClaimReadyCard.tsx deleted file mode 100644 index 1335c7417bf..00000000000 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/claim/ClaimReadyCard.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import styled, { useTheme } from 'styled-components'; - -import { Button, Icon, Paragraph, Tooltip, variables } from '@trezor/components'; -import { borders, spacingsPx } from '@trezor/theme'; - -import { FiatValue, FormattedCryptoAmount, Translation } from 'src/components/suite'; -import { openModal } from 'src/actions/suite/modalActions'; -import { useDispatch, useSelector } from 'src/hooks/suite'; -import { selectSelectedAccount } from 'src/reducers/wallet/selectedAccountReducer'; -import { useMessageSystemStaking } from 'src/hooks/suite/useMessageSystemStaking'; - -import { FiatValueWrapper, FormattedCryptoAmountWrapper } from './styled'; - -const StyledCard = styled.div` - border-radius: ${borders.radii.md}; - padding: ${spacingsPx.md} ${spacingsPx.xxl} ${spacingsPx.xxl} ${spacingsPx.md}; - margin-bottom: ${spacingsPx.xs}; - - background: linear-gradient( - 87deg, - ${({ theme }) => theme.backgroundPrimarySubtleOnElevation1} 0%, - ${({ theme }) => theme.backgroundNeutralBoldInverted} 73.33% - ); - position: relative; - overflow: hidden; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledIcon = styled(Icon)` - transform: rotate(20deg); -`; - -const BgImgWrapper = styled.div<{ $top: number; $left: number }>` - opacity: ${({ theme }) => (theme.legacy.THEME === 'dark' ? '0.5' : '0.1')}; - position: absolute; - left: ${({ $left = 0 }) => $left}px; - top: ${({ $top = 30 }) => $top}px; -`; - -const Flex = styled.div` - display: flex; - justify-content: space-between; - align-items: center; - flex-wrap: wrap; - row-gap: ${spacingsPx.sm}; -`; - -const InfoWrapper = styled.div` - display: flex; - flex-wrap: wrap; - gap: ${spacingsPx.lg} 50px; -`; - -const InfoHeading = styled.div` - display: flex; - align-items: center; - gap: ${spacingsPx.xxs}; - color: ${({ theme }) => theme.textSubdued}; - font-size: ${variables.FONT_SIZE.TINY}; - margin-bottom: ${spacingsPx.sm}; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -const StyledP = styled(Paragraph)` - font-size: ${variables.FONT_SIZE.H2}; - line-height: 24px; -`; - -interface ClaimReadyCardProps { - claimAmount: string; -} - -export const ClaimReadyCard = ({ claimAmount }: ClaimReadyCardProps) => { - const theme = useTheme(); - const { symbol } = useSelector(selectSelectedAccount) ?? {}; - const { isClaimingDisabled, claimingMessageContent } = useMessageSystemStaking(); - - const dispatch = useDispatch(); - const openClaimModal = () => { - if (!isClaimingDisabled) { - dispatch(openModal({ type: 'claim' })); - } - }; - - if (!symbol) { - return null; - } - - return ( - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - -
-
- - - - - - - - -
-
- - - - -
-
- ); -}; diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/claim/styled.ts b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/claim/styled.ts deleted file mode 100644 index ab6da9bae41..00000000000 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/claim/styled.ts +++ /dev/null @@ -1,13 +0,0 @@ -import styled from 'styled-components'; - -import { variables } from '@trezor/components'; - -export const FormattedCryptoAmountWrapper = styled.div` - font-size: ${variables.FONT_SIZE.H2}; - color: ${({ theme }) => theme.textPrimaryDefault}; -`; - -export const FiatValueWrapper = styled.div` - color: ${({ theme }) => theme.textSubdued}; - font-size: ${variables.FONT_SIZE.SMALL}; -`; diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/styled.ts b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/styled.ts index 49d6db87fa5..0494c550564 100644 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/styled.ts +++ b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/styled.ts @@ -1,56 +1,5 @@ import styled from 'styled-components'; -import { Paragraph, variables } from '@trezor/components'; -import { borders, spacingsPx } from '@trezor/theme'; - -export const CardBottomContent = styled.div` - margin-top: ${spacingsPx.lg}; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -export const AccentP = styled(Paragraph)` - color: ${({ theme }) => theme.textDefault}; - font-size: ${variables.FONT_SIZE.H2}; -`; - -// eslint-disable-next-line local-rules/no-override-ds-component -export const GreyP = styled(Paragraph)` - color: ${({ theme }) => theme.textSubdued}; - font-size: ${variables.FONT_SIZE.SMALL}; -`; - -export const InfoBox = styled.div` - margin: -10px -10px ${spacingsPx.md} -10px; - padding: 6px; - border: 1px solid ${({ theme }) => theme.borderElevation2}; - border-radius: ${borders.radii.md}; - position: relative; - - &::after { - content: ''; - display: block; - position: absolute; - bottom: -6px; - left: 12px; - background-color: ${({ theme }) => theme.backgroundSurfaceElevation1}; - height: 14px; - width: 16px; - clip-path: polygon(100% 50%, 0 50%, 50% 100%); - } - - &::before { - content: ''; - display: block; - position: absolute; - bottom: -7px; - left: 12px; - background-color: ${({ theme }) => theme.borderElevation2}; - height: 14px; - width: 16px; - clip-path: polygon(100% 50%, 0 50%, 50% 100%); - } -`; - export const ProgressBar = styled.div<{ $rewards?: number; $unstaking?: number; diff --git a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/hooks/useProgressLabelsData.tsx b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/hooks/useProgressLabelsData.tsx index cf9b2038781..ae3c8d715d3 100644 --- a/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/hooks/useProgressLabelsData.tsx +++ b/packages/suite/src/views/wallet/staking/components/EthStakingDashboard/hooks/useProgressLabelsData.tsx @@ -1,25 +1,17 @@ import { useMemo } from 'react'; -import styled from 'styled-components'; - -import { variables } from '@trezor/components'; +import { Paragraph, Column } from '@trezor/components'; import { Translation } from 'src/components/suite'; import { ProgressLabelData } from '../components/ProgressLabels/types'; -const DaysToAddToPool = styled.div` - font-size: ${variables.FONT_SIZE.TINY}; - color: ${({ theme }) => theme.legacy.TYPE_LIGHT_GREY}; - line-height: 12px; -`; - -interface UseProgressLabelsData { +type UseProgressLabelsData = { daysToAddToPool?: number; isDaysToAddToPoolShown: boolean; isStakeConfirming: boolean; isStakePending: boolean; -} +}; export const useProgressLabelsData = ({ daysToAddToPool, @@ -51,10 +43,10 @@ export const useProgressLabelsData = ({ return 'stale'; })(), children: ( -
+ {isDaysToAddToPoolShown && ( - + ~ - + )} -
+ ), }, {