Skip to content

Commit

Permalink
feat(suite): quick-action refactotring, simplification of the UI and …
Browse files Browse the repository at this point in the history
…adding a update icon
  • Loading branch information
peter-sanderson committed Aug 29, 2024
1 parent 517ee09 commit a88acab
Show file tree
Hide file tree
Showing 20 changed files with 372 additions and 109 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Meta, StoryObj } from '@storybook/react';
import { allowedIconFrameProps } from '../Icon/Icon';
import {
ComponentWithSubIcon as ComponentWithSubIconComponent,
ComponentWithSubIconProps,
} from './ComponentWithSubIcon';
import { IconName, icons } from '@suite-common/icons/src/icons';
import { getFramePropsStory } from '../../utils/frameProps';
import { Icon } from '@suite-common/icons';

const meta: Meta = {
title: 'IconWithSubIcon',
component: ComponentWithSubIconComponent,
} as Meta;
export default meta;

const iconNames = Object.keys(icons) as IconName[];

export const ComponentWithSubIcon: StoryObj<ComponentWithSubIconProps> = {
args: {
name: 'check',
subIconBackground: {
variant: 'destructive',
},
children: <Icon name="tor" />,
},
argTypes: {
name: {
options: iconNames,
control: {
type: 'select',
},
},
...getFramePropsStory(allowedIconFrameProps).argTypes,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import styled, { useTheme } from 'styled-components';
import { ExclusiveColorOrVariant, getColorForIconVariant, Icon, IconProps } from '../Icon/Icon';
import { borders, spacingsPx } from '@trezor/theme';
import { makePropsTransient, TransientProps } from '../../utils/transientProps';
import { getIconSize } from '@suite-common/icons';
import { ReactNode } from 'react';

const Container = styled.div`
position: relative;
`;

type SubIconWrapperProps = TransientProps<ExclusiveColorOrVariant> & {
$subIconColor: string;
$subIconSize: number;
};

const SubIconWrapper = styled.div<SubIconWrapperProps>`
position: absolute;
right: -${({ $subIconSize }) => $subIconSize / 2}px;
top: -${({ $subIconSize }) => $subIconSize / 2}px;
background-color: ${({ theme, $variant, $color }) =>
getColorForIconVariant({ theme, variant: $variant, color: $color })};
border-radius: ${borders.radii.full};
border: 1px solid ${({ $subIconColor }) => $subIconColor};
padding: ${spacingsPx.xxxs};
`;

export type ComponentWithSubIconProps = IconProps & {
subIconBackground: ExclusiveColorOrVariant;
children: ReactNode;
};

export const ComponentWithSubIcon = ({
subIconBackground,
children,
...subIconProps
}: ComponentWithSubIconProps) => {
const theme = useTheme();

const iconColor = getColorForIconVariant({
theme,
color: subIconProps.color,
variant: subIconProps.variant,
});

const subIconSize = getIconSize(subIconProps.size ?? 12);

return (
<Container>
{children}
<SubIconWrapper
{...makePropsTransient(subIconBackground)}
$subIconColor={iconColor}
$subIconSize={subIconSize}
>
<Icon {...subIconProps} size={subIconSize} />
</SubIconWrapper>
</Container>
);
};
4 changes: 2 additions & 2 deletions packages/components/src/components/Icon/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { FrameProps, FramePropsKeys, withFrameProps } from '../../utils/framePro
export const iconVariants = ['primary', 'tertiary', 'info', 'warning', 'destructive'] as const;
export type IconVariant = Extract<UIVariant, (typeof iconVariants)[number]>;

type ExclusiveColorOrVariant =
export type ExclusiveColorOrVariant =
| { variant?: IconVariant; color?: undefined }
| {
variant?: undefined;
Expand All @@ -36,7 +36,7 @@ const variantColorMap: Record<IconVariant, Color> = {
destructive: 'iconAlertRed',
};

const getColorForIconVariant = ({
export const getColorForIconVariant = ({
variant,
theme,
color,
Expand Down
5 changes: 3 additions & 2 deletions packages/components/src/components/buttons/Button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ButtonHTMLAttributes } from 'react';
import styled, { useTheme } from 'styled-components';
import { borders, spacingsPx, typography } from '@trezor/theme';
import { Borders, borders, spacingsPx, typography } from '@trezor/theme';
import { Spinner } from '../../loaders/Spinner/Spinner';
import {
ButtonSize,
Expand All @@ -26,6 +26,7 @@ type ButtonContainerProps = TransientProps<AllowedFrameProps> & {
$hasIcon?: boolean;
$isFullWidth?: boolean;
$isSubtle: boolean;
$borderRadius?: typeof borders.radii.sm | typeof borders.radii.full; // Do not allow all, we want consistency
};

export const ButtonContainer = styled.button<ButtonContainerProps>`
Expand All @@ -36,7 +37,7 @@ export const ButtonContainer = styled.button<ButtonContainerProps>`
gap: ${({ $hasIcon }) => $hasIcon && spacingsPx.xs};
padding: ${({ $size }) => getPadding($size, true)};
width: ${({ $isFullWidth }) => $isFullWidth && '100%'};
border-radius: ${borders.radii.full};
border-radius: ${({ $borderRadius }) => $borderRadius ?? borders.radii.full};
transition:
${focusStyleTransition},
background 0.1s ease-out;
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export * from './components/buttons/Button/Button';
export * from './components/buttons/ButtonGroup/ButtonGroup';
export * from './components/buttons/IconButton/IconButton';
export * from './components/Icon/Icon';
export { ComponentWithSubIcon } from './components/ComponentWithSubIcon/ComponentWithSubIcon';
export * from './components/buttons/PinButton/PinButton';
export * from './components/buttons/TextButton/TextButton';
export * from './components/buttons/TooltipButton/TooltipButton';
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useTheme } from 'styled-components';
import { useTranslation } from '../../../../../../hooks/suite';
import { useEnabledBackends } from '../../utils';
import { ComponentWithSubIcon, Icon } from '@trezor/components';
import { NavBackends } from './NavBackends';
import { QuickActionButton } from './QuickActionButton';
import { iconSizes } from '@suite-common/icons';

export const CustomBackend = () => {
const theme = useTheme();
const { translationString } = useTranslation();

const enabledBackends = useEnabledBackends();
const isCustomBackendIconVisible = enabledBackends.length > 0;

return (
isCustomBackendIconVisible && (
<NavBackends customBackends={enabledBackends}>
<QuickActionButton tooltip={translationString('TR_CUSTOM_BACKEND')}>
<ComponentWithSubIcon
subIconBackground={{ variant: 'primary' }}
name="check"
color={theme['iconDefaultInverted']}
size={iconSizes.extraSmall}
>
<Icon name="backend" size={iconSizes.medium} />
</ComponentWithSubIcon>
</QuickActionButton>
</NavBackends>
)
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Icon } from '@trezor/components';
import { useDispatch, useSelector, useTranslation } from 'src/hooks/suite';
import { goto } from 'src/actions/suite/routerActions';
import { SettingsAnchor } from 'src/constants/suite/anchors';
import { QuickActionButton } from './QuickActionButton';
import styled from 'styled-components';
import { getIconSize, iconSizes } from '@suite-common/icons';

const Relative = styled.div<{ $size: number }>`
position: relative;
width: ${({ $size }) => $size}px;
height: ${({ $size }) => $size}px;
`;

const Absolute = styled.div`
position: absolute;
top: 0;
left: 0;
`;

export const DebugAndExperimental = () => {
const isEapEnabled = useSelector(state => state.desktopUpdate.allowPrerelease);
const isExperimental = useSelector(state => state.suite.settings.experimental !== undefined);
const isDebugMode = useSelector(state => state.suite.settings.debug.showDebugMenu);

const { translationString } = useTranslation();
const dispatch = useDispatch();

const handleEapClick = () => {
dispatch(goto('settings-index', { anchor: SettingsAnchor.EarlyAccess }));
};

if (!isEapEnabled && !isExperimental && !isDebugMode) return null;

const tooltip = (
<>
{isDebugMode && <p>Debug mode active</p>}
{isEapEnabled && <p>{translationString('TR_EARLY_ACCESS')}</p>}
{isExperimental && <p>{translationString('TR_EXPERIMENTAL_FEATURES')}</p>}
</>
);

return (
<QuickActionButton tooltip={tooltip} onClick={handleEapClick}>
<Relative $size={getIconSize(iconSizes.medium)}>
{isDebugMode && (
<Absolute>
<Icon name="debug" variant="destructive" size={iconSizes.medium} />
</Absolute>
)}
{isExperimental && (
<Absolute>
<Icon name="experimental" variant="primary" size={iconSizes.medium} />
</Absolute>
)}
{isEapEnabled && (
<Absolute>
<Icon name="eap" variant="warning" size={iconSizes.medium} />
</Absolute>
)}
</Relative>
</QuickActionButton>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Icon } from '@trezor/components';
import { setDiscreetMode } from '../../../../../../actions/settings/walletSettingsActions';
import { useDispatch, useSelector, useTranslation } from '../../../../../../hooks/suite';
import { selectIsDiscreteModeActive } from '../../../../../../reducers/wallet/settingsReducer';
import { QuickActionButton } from './QuickActionButton';
import { iconSizes } from '@suite-common/icons';

export const HideBalances = () => {
const dispatch = useDispatch();
const { translationString } = useTranslation();

const isDiscreetModeActive = useSelector(selectIsDiscreteModeActive);
const translationLabel = isDiscreetModeActive ? 'TR_SHOW_BALANCES' : 'TR_HIDE_BALANCES';

const handleDiscreetModeClick = () => dispatch(setDiscreetMode(!isDiscreetModeActive));

return (
<QuickActionButton
tooltip={translationString(translationLabel)}
onClick={handleDiscreetModeClick}
>
<Icon
name={isDiscreetModeActive ? 'hide' : 'show'}
variant="tertiary"
size={iconSizes.medium}
/>
</QuickActionButton>
);
};
Loading

0 comments on commit a88acab

Please sign in to comment.