From 527a53bf9f6e845201e045a97b9c6bc91506df26 Mon Sep 17 00:00:00 2001 From: Adam Havel Date: Wed, 6 Nov 2024 12:23:46 +0100 Subject: [PATCH] chore(suite): fix aborted discovery process in wallet switcher --- .../src/components/Card/Card.stories.tsx | 20 +- .../components/src/components/Card/Card.tsx | 26 +- .../components/src/components/Card/utils.tsx | 11 +- .../src/components/Divider/Divider.tsx | 32 ++- packages/components/src/utils/frameProps.tsx | 14 +- .../SwitchDevice/DeviceItem/EjectButton.tsx | 38 +-- .../DeviceItem/EjectConfirmation.tsx | 30 +- .../DeviceItem/WalletInstance.tsx | 262 ++++++++---------- packages/theme/src/spacings.ts | 3 +- 9 files changed, 213 insertions(+), 223 deletions(-) diff --git a/packages/components/src/components/Card/Card.stories.tsx b/packages/components/src/components/Card/Card.stories.tsx index 561f4fc4b0c..1d430859b2d 100644 --- a/packages/components/src/components/Card/Card.stories.tsx +++ b/packages/components/src/components/Card/Card.stories.tsx @@ -11,10 +11,23 @@ export default meta; export const Card: StoryObj = { args: { - children:

Lorem ipsum

, + children: ( +

+ Quos delectus veritatis est doloribus dolor. Odit fugit omnis magni ipsam quia rem + aut. Et alias sint non. Consequuntur dignissimos veritatis debitis corporis esse. + Quaerat voluptatem unde aut. Iusto laborum omnis quis amet atque. Sint culpa + delectus non soluta temporibus saepe. Sequi saepe corrupti aliquam ut sit assumenda + aspernatur consequuntur. Ut est ullam iusto facilis voluptatibus. Sit est cum quos. + Quasi deleniti non fugit iste alias consequuntur. Ullam ad ut culpa est reiciendis + molestiae. Reiciendis ab veritatis a totam inventore nihil voluptatem occaecati. + Quisquam atque odit quia nam. Laboriosam rem et ut. Maxime qui voluptatem + voluptatem. +

+ ), label: '', paddingType: 'normal', fillType: 'default', + isHiglighted: false, ...getFramePropsStory(allowedCardFrameProps).args, }, argTypes: { @@ -35,6 +48,11 @@ export const Card: StoryObj = { type: 'radio', }, }, + isHiglighted: { + control: { + type: 'boolean', + }, + }, ...getFramePropsStory(allowedCardFrameProps).argTypes, }, }; diff --git a/packages/components/src/components/Card/Card.tsx b/packages/components/src/components/Card/Card.tsx index 5d666651a65..59f8aa061af 100644 --- a/packages/components/src/components/Card/Card.tsx +++ b/packages/components/src/components/Card/Card.tsx @@ -1,5 +1,5 @@ import { forwardRef, HTMLAttributes, ReactNode } from 'react'; -import styled from 'styled-components'; +import styled, { css } from 'styled-components'; import { borders, Elevation, spacingsPx } from '@trezor/theme'; import { ElevationUp, useElevation } from '../ElevationContext/ElevationContext'; import { @@ -46,12 +46,14 @@ const CardContainer = styled.div< $paddingType: PaddingType; $fillType: FillType; $isClickable: boolean; + $isHiglighted: boolean; $hasLabel: boolean; } & TransientProps >` width: 100%; display: flex; flex-direction: column; + position: relative; padding: ${mapPaddingTypeToPadding}; border-radius: ${borders.radii.md}; transition: @@ -60,6 +62,23 @@ const CardContainer = styled.div< border-color 0.2s; cursor: ${({ $isClickable }) => ($isClickable ? 'pointer' : 'default')}; + ${({ theme, $isHiglighted, $paddingType }) => + $isHiglighted && + css` + overflow: hidden; + padding-left: calc(${spacingsPx.xxs} + ${mapPaddingTypeToPadding({ $paddingType })}); + + &::before { + content: ''; + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: ${spacingsPx.xxs}; + background: ${theme.backgroundSecondaryDefault}; + } + `} + ${mapFillTypeToCSS} ${withFrameProps} `; @@ -73,6 +92,7 @@ type CommonCardProps = AccessibilityProps & { children?: ReactNode; className?: string; label?: ReactNode; + isHiglighted?: boolean; 'data-testid'?: string; }; @@ -91,6 +111,7 @@ const CardComponent = forwardRef( className, tabIndex, label, + isHiglighted = false, 'data-testid': dataTest, ...rest }, @@ -105,6 +126,7 @@ const CardComponent = forwardRef( $paddingType={paddingType} $fillType={fillType} $isClickable={Boolean(onClick)} + $isHiglighted={isHiglighted} $hasLabel={Boolean(label)} onClick={onClick} onMouseEnter={onMouseEnter} @@ -133,6 +155,7 @@ export const Card = forwardRef( tabIndex, children, 'data-testid': dataTest, + isHiglighted, ...rest }, ref, @@ -147,6 +170,7 @@ export const Card = forwardRef( fillType, children, label, + isHiglighted, 'data-testid': dataTest, }; const frameProps = pickAndPrepareFrameProps(rest, allowedCardFrameProps); diff --git a/packages/components/src/components/Card/utils.tsx b/packages/components/src/components/Card/utils.tsx index ee2544b8c38..e0e39cd7659 100644 --- a/packages/components/src/components/Card/utils.tsx +++ b/packages/components/src/components/Card/utils.tsx @@ -3,6 +3,7 @@ import { Elevation, mapElevationToBackground, mapElevationToBorder, + SpacingPxValues, } from '@trezor/theme'; import { css, DefaultTheme, RuleSet } from 'styled-components'; import { PaddingType, FillType } from './types'; @@ -19,8 +20,8 @@ type FillTypeMapArgs = { theme: DefaultTheme; }; -export const mapPaddingTypeToLabelPadding = ({ $paddingType }: PaddingMapArgs): number | string => { - const paddingMap: Record = { +export const mapPaddingTypeToLabelPadding = ({ $paddingType }: PaddingMapArgs): string => { + const paddingMap: Record = { none: `${spacingsPx.xxs} 0`, small: `${spacingsPx.xxs} ${spacingsPx.sm}`, normal: `${spacingsPx.xs} ${spacingsPx.lg}`, @@ -30,9 +31,9 @@ export const mapPaddingTypeToLabelPadding = ({ $paddingType }: PaddingMapArgs): return paddingMap[$paddingType]; }; -export const mapPaddingTypeToPadding = ({ $paddingType }: PaddingMapArgs): number | string => { - const paddingMap: Record = { - none: 0, +export const mapPaddingTypeToPadding = ({ $paddingType }: PaddingMapArgs): SpacingPxValues => { + const paddingMap: Record = { + none: '0px', small: spacingsPx.sm, normal: spacingsPx.lg, large: spacingsPx.xl, diff --git a/packages/components/src/components/Divider/Divider.tsx b/packages/components/src/components/Divider/Divider.tsx index 3df4fcd2552..0defb36457f 100644 --- a/packages/components/src/components/Divider/Divider.tsx +++ b/packages/components/src/components/Divider/Divider.tsx @@ -1,4 +1,4 @@ -import styled from 'styled-components'; +import styled, { css } from 'styled-components'; import { Color, Elevation, mapElevationToBorder, spacings } from '@trezor/theme'; import { useElevation } from '../ElevationContext/ElevationContext'; import { @@ -8,13 +8,16 @@ import { withFrameProps, } from '../../utils/frameProps'; import { TransientProps } from '../../utils/transientProps'; -import { allowedHeadingFrameProps } from '../typography/Heading/Heading'; -export const allowedDividerFrameProps = ['margin'] as const satisfies FramePropsKeys[]; +export const allowedDividerFrameProps = [ + 'margin', + 'width', + 'overflow', +] as const satisfies FramePropsKeys[]; type AllowedFrameProps = Pick; type DividerOrientation = 'horizontal' | 'vertical'; -type DividerProps = AllowedFrameProps & { +export type DividerProps = AllowedFrameProps & { orientation?: DividerOrientation; strokeWidth?: number; color?: Color; @@ -30,15 +33,16 @@ const Line = styled.div< >` ${({ $orientation, $strokeWidth }) => $orientation === 'vertical' - ? ` - height: 100%; - width: ${$strokeWidth}px; - min-width: ${$strokeWidth}px;` - : ` - width: 100%; - height: ${$strokeWidth}px; - min-height: ${$strokeWidth}px; - `} + ? css` + height: 100%; + width: ${$strokeWidth}px; + min-width: ${$strokeWidth}px; + ` + : css` + width: 100%; + height: ${$strokeWidth}px; + min-height: ${$strokeWidth}px; + `} background: ${({ theme, $elevation, $color }) => $color ? theme[$color] : mapElevationToBorder({ theme, $elevation })}; @@ -56,7 +60,7 @@ export const Divider = ({ const frameProps = pickAndPrepareFrameProps( { ...rest, margin: rest.margin ?? { top: spacings.md, bottom: spacings.md } }, - allowedHeadingFrameProps, + allowedDividerFrameProps, ); return ( diff --git a/packages/components/src/utils/frameProps.tsx b/packages/components/src/utils/frameProps.tsx index 1c1307880c4..21b6ff0cac2 100644 --- a/packages/components/src/utils/frameProps.tsx +++ b/packages/components/src/utils/frameProps.tsx @@ -1,14 +1,14 @@ import { css } from 'styled-components'; import { makePropsTransient, TransientProps } from './transientProps'; -import { SpacingValues } from '@trezor/theme'; +import { SpacingValues, SpacingPxValues } from '@trezor/theme'; type Margin = { - top?: SpacingValues | 'auto'; - bottom?: SpacingValues | 'auto'; - left?: SpacingValues | 'auto'; - right?: SpacingValues | 'auto'; - horizontal?: SpacingValues | 'auto'; - vertical?: SpacingValues | 'auto'; + top?: SpacingValues | SpacingPxValues | 'auto'; + bottom?: SpacingValues | SpacingPxValues | 'auto'; + left?: SpacingValues | SpacingPxValues | 'auto'; + right?: SpacingValues | SpacingPxValues | 'auto'; + horizontal?: SpacingValues | SpacingPxValues | 'auto'; + vertical?: SpacingValues | SpacingPxValues | 'auto'; }; const overflows = [ 'auto', diff --git a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/EjectButton.tsx b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/EjectButton.tsx index ddf77186670..49dba19be77 100644 --- a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/EjectButton.tsx +++ b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/EjectButton.tsx @@ -1,19 +1,9 @@ -import styled, { useTheme } from 'styled-components'; +import { useTheme } from 'styled-components'; -import { Tooltip, Icon, useElevation } from '@trezor/components'; +import { Tooltip, Icon } from '@trezor/components'; import { Translation } from 'src/components/suite'; -import { Elevation, borders, mapElevationToBackground, spacingsPx } from '@trezor/theme'; import { ContentType } from '../types'; -const EjectContainer = styled.div<{ $elevation: Elevation }>` - position: absolute; - right: ${spacingsPx.xs}; - top: ${spacingsPx.xs}; - background-color: ${mapElevationToBackground}; - border-radius: ${borders.radii.full}; - padding: ${spacingsPx.xxs}; -`; - interface EjectButtonProps { setContentType: (contentType: ContentType) => void; 'data-testid'?: string; @@ -27,20 +17,16 @@ export const EjectButton = ({ setContentType, 'data-testid': dataTest }: EjectBu e.stopPropagation(); }; - const { elevation } = useElevation(); - return ( - - }> - - - + }> + + ); }; diff --git a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/EjectConfirmation.tsx b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/EjectConfirmation.tsx index caf21530560..944a8321122 100644 --- a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/EjectConfirmation.tsx +++ b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/EjectConfirmation.tsx @@ -1,28 +1,18 @@ import styled from 'styled-components'; import { useDispatch, useSelector } from 'src/hooks/suite'; -import { H3, Button, Text } from '@trezor/components'; +import { H4, Button, Paragraph, Row } from '@trezor/components'; import { Translation } from 'src/components/suite'; import { deviceActions } from '@suite-common/wallet-core'; import { analytics, EventType } from '@trezor/suite-analytics'; import { AcquiredDevice } from '@suite-common/suite-types'; import { MouseEventHandler, ReactNode } from 'react'; -import { spacings, spacingsPx } from '@trezor/theme'; +import { spacings } from '@trezor/theme'; import { selectSuiteSettings } from '../../../../reducers/suite/suiteReducer'; const Container = styled.div` - margin: 0 ${spacingsPx.xxs}; cursor: auto; `; -const Description = styled.div` - margin: ${spacingsPx.xs} 0 ${spacingsPx.md} 0; -`; - -const Buttons = styled.div` - display: flex; - gap: ${spacingsPx.xxs}; -`; - type EjectConfirmationProps = { onCancel: MouseEventHandler | undefined; onClick: (e: React.MouseEvent) => void; @@ -57,19 +47,19 @@ const EjectConfirmationContainer = ({ return ( -

{title}

- - {description} - - +

{title}

+ + {description} + + @@ -77,12 +67,12 @@ const EjectConfirmationContainer = ({ size="small" onClick={onCancel} variant="tertiary" - isFullWidth data-testid="@switch-device/cancelEject" + isFullWidth > -
+
); }; diff --git a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/WalletInstance.tsx b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/WalletInstance.tsx index b5aa45470c8..908b680c91b 100644 --- a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/WalletInstance.tsx +++ b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/WalletInstance.tsx @@ -1,13 +1,12 @@ -import styled, { css } from 'styled-components'; - import { selectDiscoveryByDeviceState, selectCurrentFiatRates, selectDeviceThunk, + selectDevice, } from '@suite-common/wallet-core'; -import { variables, Card, Divider, Icon, Tooltip } from '@trezor/components'; +import { Card, Icon, Tooltip, Row, Column, Text, Divider } from '@trezor/components'; import { getAllAccounts, getTotalFiatBalance } from '@suite-common/wallet-utils'; -import { spacingsPx, typography } from '@trezor/theme'; +import { spacings, negativeSpacings } from '@trezor/theme'; import { WalletLabeling, @@ -28,62 +27,8 @@ import { ContentType } from '../types'; import { ViewOnly } from './ViewOnly'; import { EjectButton } from './EjectButton'; import { redirectAfterWalletSelectedThunk } from 'src/actions/wallet/addWalletThunk'; +import { createDiscoveryThunk } from '@suite-common/wallet-core'; -const RelativeContainer = styled.div` - position: relative; - border-radius: 16px; - overflow: hidden; -`; - -const DividerWrapper = styled.div` - position: relative; - left: -${spacingsPx.xs}; - width: calc(100% + ${spacingsPx.lg}); -`; - -const InstanceType = styled.div<{ $isSelected: boolean }>` - display: flex; - gap: ${spacingsPx.xxs}; - align-items: center; - color: ${({ theme, $isSelected }) => ($isSelected ? theme.textDefault : theme.textSubdued)}; - ${({ $isSelected }) => $isSelected && typography.highlight} - /* these styles ensure proper metadata behavior */ - white-space: nowrap; - overflow: hidden; -`; - -const InstanceTitle = styled.div` - font-weight: 500; - line-height: 1.57; - color: ${({ theme }) => theme.legacy.TYPE_LIGHT_GREY}; - font-size: ${variables.FONT_SIZE.SMALL}; - font-variant-numeric: tabular-nums; -`; - -const Col = styled.div<{ $grow?: number; $centerItems?: boolean }>` - display: flex; - flex-grow: ${({ $grow }) => $grow || 0}; - flex-direction: column; - align-items: ${({ $centerItems }) => ($centerItems ? 'center' : 'flex-start')}; - - &:first-child { - cursor: pointer; - } -`; - -const SelectedHighlight = styled.div` - ${({ theme }) => css` - &::before { - content: ''; - position: absolute; - left: 0; - top: 0; - bottom: 0; - width: ${spacingsPx.xxs}; - background: ${theme.backgroundSecondaryDefault}; - } - `} -`; interface WalletInstanceProps { instance: AcquiredDevice; enabled: boolean; @@ -109,6 +54,7 @@ export const WalletInstance = ({ const discoveryProcess = useSelector(state => selectDiscoveryByDeviceState(state, instance.state), ); + const device = useSelector(selectDevice); const { defaultAccountLabelString } = useWalletLabeling(); const deviceAccounts = getAllAccounts(instance.state, accounts); @@ -133,13 +79,23 @@ export const WalletInstance = ({ e.stopPropagation(); }; - const handleClick = () => { - if (!editing) { - dispatch(selectDeviceThunk({ device: instance })); - dispatch(redirectAfterWalletSelectedThunk()); - onCancel(false); - } - }; + const handleClick = discoveryProcess + ? () => { + if (!editing) { + dispatch(selectDeviceThunk({ device: instance })); + dispatch(redirectAfterWalletSelectedThunk()); + onCancel(false); + } + } + : () => { + dispatch( + createDiscoveryThunk({ + deviceState: device?.state?.staticSessionId, + device, + }), + ); + onCancel(false); + }; const isViewOnlyRendered = contentType === 'default' && enabled && discoveryProcess; const isEjectConfirmationRendered = contentType === 'eject-confirmation'; @@ -147,93 +103,103 @@ export const WalletInstance = ({ contentType === 'disabling-view-only-ejects-wallet'; return ( - - - - {isSelected && } - - - {discoveryProcess && ( - - {!instance.useEmptyPassphrase && ( - }> - - - )} - {instance.state?.staticSessionId ? ( - + + + {discoveryProcess && ( + + + {discoveryProcess ? ( + + {!instance.useEmptyPassphrase && ( + + } + > + + + )} + {instance.state?.staticSessionId ? ( + + ) : ( + + )} + ) : ( - + )} - - )} - - {!discoveryProcess && ( - - - - )} - - - - - - - - - {(isViewOnlyRendered || - isEjectConfirmationRendered || - isDisablingViewOnlyEjectsWalletRendered) && ( - - - + + )} - {isViewOnlyRendered && ( - - )} - {isEjectConfirmationRendered && ( - - )} - {isDisablingViewOnlyEjectsWalletRendered && ( - + - )} - - + + + + {(isViewOnlyRendered || + isEjectConfirmationRendered || + isDisablingViewOnlyEjectsWalletRendered) && ( + + )} + + {isViewOnlyRendered && } + {isEjectConfirmationRendered && ( + + )} + {isDisablingViewOnlyEjectsWalletRendered && ( + + )} + ); }; diff --git a/packages/theme/src/spacings.ts b/packages/theme/src/spacings.ts index 2780d489841..f6ea27de5d2 100644 --- a/packages/theme/src/spacings.ts +++ b/packages/theme/src/spacings.ts @@ -32,7 +32,8 @@ export type Spacing = keyof Spacings; export type NegativeSpacings = typeof negativeSpacings; export type SpacingValues = Spacings[Spacing] | NegativeSpacings[Spacing]; export type SpacingPx = { [K in Spacing]: `${Spacings[K]}px` }; -export type SpacingPxValues = SpacingPx[Spacing]; +export type NegativeSpacingPx = { [K in Spacing]: `-${Spacings[K]}px` }; +export type SpacingPxValues = SpacingPx[Spacing] | NegativeSpacingPx[Spacing]; export const spacingsPx = (Object.keys(spacings) as Array).reduce((result, key) => { (result as Record)[key] = `${spacings[key]}px`;