Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove legacy Icons, use only new icons #13997

Merged
merged 3 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 1 addition & 2 deletions packages/components/src/components/Badge/Badge.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from 'react';
import styled, { css, DefaultTheme, useTheme } from 'styled-components';
import { IconName } from '@suite-common/icons';
import { Icon } from '@suite-common/icons/src/webComponents';
import { borders, Color, CSSColor, spacings, spacingsPx, typography } from '@trezor/theme';
import { focusStyleTransition, getFocusShadowStyle } from '../../utils/utils';
import type { UISize, UIVariant } from '../../config/types';
import { FrameProps, FramePropsKeys, withFrameProps } from '../../utils/frameProps';
import { TransientProps } from '../../utils/transientProps';
import { Icon, IconName } from '../Icon/Icon';

export const allowedBadgeFrameProps: FramePropsKeys[] = ['margin'];
type AllowedFrameProps = Pick<FrameProps, (typeof allowedBadgeFrameProps)[number]>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
mapElevationToBackground,
mapElevationToBorder,
} from '@trezor/theme';
import { Icon } from '@suite-common/icons/src/webComponents';
import { Icon } from '../Icon/Icon';
import { motionEasing } from '../../config/motion';
import { ElevationUp, useElevation } from './../ElevationContext/ElevationContext';
import { FrameProps, FramePropsKeys, withFrameProps } from '../../utils/frameProps';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const Dropdown: StoryObj<DropdownProps> = {
console.log('navigate somewhere');
},
label: 'some link',
icon: 'ARROW_RIGHT_LONG',
icon: 'arrowRightLong',
},
alignMenu: 'right-top',
items: [
Expand Down Expand Up @@ -95,15 +95,15 @@ export const Dropdown: StoryObj<DropdownProps> = {
onClick: () => {
console.log('item 2 clicked - disabled');
},
icon: 'LIGHTBULB',
icon: 'lightbulb',
isDisabled: true,
},
{
label: 'disabled item with iconRight',
onClick: () => {
console.log('item 3 clicked - disabled');
},
iconRight: 'ARROW_RIGHT',
iconRight: 'chevronRight',
isDisabled: true,
},
{
Expand All @@ -117,7 +117,7 @@ export const Dropdown: StoryObj<DropdownProps> = {
onClick: () => {
console.log('item 5 clicked');
},
iconRight: 'ARROW_RIGHT',
iconRight: 'chevronRight',
separatorBefore: true,
},
],
Expand Down
4 changes: 2 additions & 2 deletions packages/components/src/components/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const Container = styled.div<{ $disabled?: boolean; $hasCustomChildren: boolean
${getFocusShadowStyle()};
cursor: ${({ $disabled }) => ($disabled ? 'default' : 'pointer')};

/**
/**
This must be here to reduce clickable area to the "circle" of the (...) children.
However, if you use custom children its your own responsibility to handle it.
*/
Expand Down Expand Up @@ -203,7 +203,7 @@ export const Dropdown = forwardRef(
<MoreIcon
size="small"
variant="tertiary"
icon="MORE"
icon="more"
tabIndex={-1}
onClick={e => e.stopPropagation()}
$isToggled={isToggled}
Expand Down
14 changes: 7 additions & 7 deletions packages/components/src/components/Dropdown/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import {
mapElevationToBackground,
nextElevation,
} from '@trezor/theme';
import { IconLegacy, IconLegacyProps } from '../Icon/IconLegacy';
import type { Coords } from './getAdjustedCoords';
import { menuStyle } from './menuStyle';
import { useElevation } from '../ElevationContext/ElevationContext';
import { Icon, IconName } from '../Icon/Icon';

const addonAnimation = keyframes`
from {
Expand Down Expand Up @@ -130,7 +130,7 @@ const MenuItemContainer = styled.li<MenuItemContainerProps>`

type AddonProps = {
label: React.ReactNode;
icon: IconLegacyProps['icon'];
icon: IconName;
onClick?: () => void;
};

Expand All @@ -145,7 +145,7 @@ const Addon = ({ label, icon, onClick, isKeyboardSelected, onMouseOver }: AddonC
return (
<AddonContainer onClick={onClick} $isFocused={isKeyboardSelected} onMouseOver={onMouseOver}>
<span>{label}</span>
<IconLegacy icon={icon} size={spacings.sm} color={theme.iconPrimaryDefault} />
<Icon name={icon} size={spacings.sm} color={theme.iconPrimaryDefault} />
</AddonContainer>
);
};
Expand All @@ -154,8 +154,8 @@ export type DropdownMenuItemProps = {
label: React.ReactNode;
onClick?: () => any | Promise<any>;
shouldCloseOnClick?: boolean;
icon?: IconLegacyProps['icon'];
iconRight?: IconLegacyProps['icon'];
icon?: IconName;
iconRight?: IconName;
isDisabled?: boolean;
isHidden?: boolean;
separatorBefore?: boolean;
Expand Down Expand Up @@ -205,9 +205,9 @@ const MenuItem = ({
$separatorBefore={separatorBefore}
data-testid={dataTest}
>
{icon && <IconLegacy icon={icon} size={spacings.md} />}
{icon && <Icon name={icon} size={spacings.md} />}
<span>{label}</span>
{iconRight && <IconLegacy icon={iconRight} size={spacings.md} />}
{iconRight && <Icon name={iconRight} size={spacings.md} />}
</MenuItemContainer>
);
};
Expand Down
14 changes: 8 additions & 6 deletions packages/components/src/components/Icon/Icon.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { Meta, StoryObj } from '@storybook/react';
import { Icon as IconComponent, IconProps } from './Icon';
import { allowedIconFrameProps, Icon as IconComponent, IconProps, iconVariants } from './Icon';
import { IconName, icons } from '@suite-common/icons/src/icons';
import { colorVariants } from '@trezor/theme';
import { getFramePropsStory } from '../../utils/frameProps';
const meta: Meta = {
title: 'Icons',
component: IconComponent,
} as Meta;
export default meta;

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

export const Icon: StoryObj<IconProps> = {
args: {
name: 'discover',
color: 'iconDefault',
color: undefined,
variant: 'primary',
...getFramePropsStory(allowedIconFrameProps).args,
},
argTypes: {
name: {
Expand All @@ -23,11 +24,12 @@ export const Icon: StoryObj<IconProps> = {
type: 'select',
},
},
color: {
options: colors,
variant: {
options: iconVariants,
control: {
type: 'select',
},
},
...getFramePropsStory(allowedIconFrameProps).argTypes,
},
};
189 changes: 187 additions & 2 deletions packages/components/src/components/Icon/Icon.tsx
Original file line number Diff line number Diff line change
@@ -1,2 +1,187 @@
export { Icon, type WebIconProps as IconProps } from '@suite-common/icons/src/webComponents';
export { type IconName, icons } from '@suite-common/icons/src/icons';
import { ReactSVG } from 'react-svg';
import { forwardRef, MouseEvent, Ref } from 'react';

import styled, { css, DefaultTheme } from 'styled-components';
import {
IconProps as IconCommonProps,
getIconSize,
icons,
} from '@suite-common/icons/src/webComponents';
import { UIVariant } from '../../config/types';

import { CSSColor, Color } from '@trezor/theme';

import { TransientProps } from '../../utils/transientProps';
import { FrameProps, FramePropsKeys, withFrameProps } from '../../utils/frameProps';

export const iconVariants = ['primary', 'tertiary', 'info', 'warning', 'destructive'] as const;
export type IconVariant = Extract<UIVariant, (typeof iconVariants)[number]>;

type ExclusiveColorOrVariant =
| { variant?: IconVariant; color?: undefined }
| {
variant?: undefined;
/** @deprecated Use only is case of absolute desperation. Prefer using `variant`. */
color?: string;
};

export const allowedIconFrameProps: FramePropsKeys[] = ['margin'];
type AllowedFrameProps = Pick<FrameProps, (typeof allowedIconFrameProps)[number]>;

const variantColorMap: Record<IconVariant, Color> = {
primary: 'iconPrimaryDefault',
tertiary: 'iconSubdued',
info: 'iconAlertBlue',
warning: 'iconAlertYellow',
destructive: 'iconAlertRed',
};

const getColorForIconVariant = ({
variant,
theme,
color,
}: Pick<IconProps, 'color' | 'variant'> & { theme: DefaultTheme }):
| CSSColor
| 'inherit'
| string => {
if (color !== undefined) {
return color;
}

return variant === undefined ? theme.iconDefault : theme[variantColorMap[variant]];
};

type SvgWrapperProps = TransientProps<Pick<IconProps, 'color' | 'variant'>> & {
$cursorPointer?: boolean;
$hoverColor?: string;
};

const SvgWrapper = styled.div<SvgWrapperProps & TransientProps<AllowedFrameProps>>`
${({ $cursorPointer }) =>
$cursorPointer &&
css`
cursor: pointer;
`}

path {
fill: ${({ $variant, $color, theme }) =>
getColorForIconVariant({ variant: $variant, color: $color, theme })};
transition: fill 0.14s;
}

&:hover {
path {
fill: ${({ $hoverColor }) => $hoverColor};
}
}

${withFrameProps}
`;

const SVG = styled(ReactSVG)`
display: flex;
align-items: center;
justify-content: center;

div {
display: flex;
align-items: center;
justify-content: center;
}

path {
transition:
stroke 0.15s,
fill 0.15s;
}

${({ onClick }) =>
onClick &&
css`
cursor: pointer;

&:focus-visible {
svg {
transition: opacity 0.2s;
opacity: 0.5;
}
}
`}
` as typeof ReactSVG;

export type IconProps = AllowedFrameProps &
Omit<IconCommonProps, 'color'> & {
onClick?: (e: any) => void;
className?: string;
'data-testid'?: string;

/**
* @deprecated This should not be used, only for back-compatibility.
* Use Link or some other clickable wrapping component.
*/
cursorPointer?: boolean;

hoverColor?: string;
} & ExclusiveColorOrVariant;

export const Icon = forwardRef(
(
{
name,
size = 'large',
color,
variant,
onClick,
className,
'data-testid': dataTest,
cursorPointer,
hoverColor,
margin,
}: IconProps,
ref?: Ref<HTMLDivElement>,
) => {
const iconSize = getIconSize(size);

const handleOnKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Enter' || e.key === ' ') {
onClick?.(e);
}
};

const handleInjection = (svg: SVGSVGElement) => {
svg.setAttribute('width', `${iconSize}px`);
svg.setAttribute('height', `${iconSize}px`);
};

const handleClick = (e: MouseEvent<any>) => {
onClick?.(e);

// We need to stop default/propagation in case the icon is rendered in popup/modal so it won't close it.
e.preventDefault();
e.stopPropagation();
};

return (
<SvgWrapper
$cursorPointer={cursorPointer}
$hoverColor={hoverColor}
$margin={margin}
$color={color}
$variant={variant}
data-testid={dataTest}
onClick={onClick ? handleClick : undefined}
className={className}
ref={ref}
>
<SVG
tabIndex={onClick ? 0 : undefined}
onKeyDown={handleOnKeyDown}
src={icons[name]}
beforeInjection={handleInjection}
/>
</SvgWrapper>
);
},
);

export { type IconName, icons, type IconSize } from '@suite-common/icons/src/webComponents';
36 changes: 0 additions & 36 deletions packages/components/src/components/Icon/IconLegacy.stories.tsx

This file was deleted.

Loading
Loading