From 6e5ab2a9457207e3e527132383ac62534887704c Mon Sep 17 00:00:00 2001 From: Binij Shrestha <93417120+thebinij@users.noreply.github.com> Date: Thu, 27 Jul 2023 03:03:36 +0545 Subject: [PATCH] Migrate AvatarIcon (#19107) Migrate AvatarIcon to TS --------- Co-authored-by: georgewrmarshall --- .../component-library/avatar-base/README.mdx | 2 +- .../component-library/avatar-icon/README.mdx | 31 +++--- ...test.js.snap => avatar-icon.test.tsx.snap} | 0 .../avatar-icon/avatar-icon.constants.js | 9 -- .../avatar-icon/avatar-icon.js | 96 ------------------- ...con.stories.js => avatar-icon.stories.tsx} | 95 ++++++------------ ...atar-icon.test.js => avatar-icon.test.tsx} | 48 +++++----- .../avatar-icon/avatar-icon.tsx | 59 ++++++++++++ .../avatar-icon/avatar-icon.types.ts | 50 ++++++++++ .../component-library/avatar-icon/index.js | 2 - .../component-library/avatar-icon/index.ts | 3 + ui/components/component-library/index.js | 2 +- 12 files changed, 180 insertions(+), 217 deletions(-) rename ui/components/component-library/avatar-icon/__snapshots__/{avatar-icon.test.js.snap => avatar-icon.test.tsx.snap} (100%) delete mode 100644 ui/components/component-library/avatar-icon/avatar-icon.constants.js delete mode 100644 ui/components/component-library/avatar-icon/avatar-icon.js rename ui/components/component-library/avatar-icon/{avatar-icon.stories.js => avatar-icon.stories.tsx} (69%) rename ui/components/component-library/avatar-icon/{avatar-icon.test.js => avatar-icon.test.tsx} (68%) create mode 100644 ui/components/component-library/avatar-icon/avatar-icon.tsx create mode 100644 ui/components/component-library/avatar-icon/avatar-icon.types.ts delete mode 100644 ui/components/component-library/avatar-icon/index.js create mode 100644 ui/components/component-library/avatar-icon/index.ts diff --git a/ui/components/component-library/avatar-base/README.mdx b/ui/components/component-library/avatar-base/README.mdx index da27d6677790..c02f1fb34a50 100644 --- a/ui/components/component-library/avatar-base/README.mdx +++ b/ui/components/component-library/avatar-base/README.mdx @@ -14,7 +14,7 @@ The `AvatarBase` is a wrapper component responsible for enforcing dimensions and ## Props -The `AvatarBase` accepts all props below as well as all [Box](/docs/components-ui-box--default-story#props) component props. +The `AvatarBase` accepts all props below as well as all [Box](/docs/components-componentlibrary-box--docs#props) component props. diff --git a/ui/components/component-library/avatar-icon/README.mdx b/ui/components/component-library/avatar-icon/README.mdx index 92e713184470..bd2e6fdb3f41 100644 --- a/ui/components/component-library/avatar-icon/README.mdx +++ b/ui/components/component-library/avatar-icon/README.mdx @@ -13,7 +13,7 @@ The `AvatarIcon` is an avatar component that renders only an icon inside and is ## Props -The `AvatarIcon` accepts all props below as well as all [Box](/docs/components-ui-box--default-story#props) component props +The `AvatarIcon` accepts all props below as well as all [Box](/docs/components-componentlibrary-box--docs#props) component props @@ -24,33 +24,30 @@ component props ### Size -Use the `size` prop and the `Size` object from `./ui/helpers/constants/design-system.js` to change the size of `AvatarIcon` - -Optional: `AVATAR_ICON_SIZES` from `./ui/components/component-library` object can be used instead of `Size` +Use the `size` prop and the `AvatarIconSize` enum to change the size of `AvatarIcon` Possible sizes include: -- `Size.XS` 16px -- `Size.SM` 24px -- `Size.MD` 32px -- `Size.LG` 40px -- `Size.XL` 48px +- `AvatarIconSize.Xs` 16px +- `AvatarIconSize.Sm` 24px +- `AvatarIconSize.Md` 32px +- `AvatarIconSize.Lg` 40px +- `AvatarIconSize.Xl` 48px -Defaults to `Size.MD` +Defaults to `AvatarIconSize.Md` ```jsx -import { Size } from '../../../helpers/constants/design-system'; -import { AvatarIcon, IconName } from '../ui/component-library'; +import { AvatarIcon, AvatarIconSize } from '../ui/component-library'; - - - - - + + + + + ``` ### Icon Name\* diff --git a/ui/components/component-library/avatar-icon/__snapshots__/avatar-icon.test.js.snap b/ui/components/component-library/avatar-icon/__snapshots__/avatar-icon.test.tsx.snap similarity index 100% rename from ui/components/component-library/avatar-icon/__snapshots__/avatar-icon.test.js.snap rename to ui/components/component-library/avatar-icon/__snapshots__/avatar-icon.test.tsx.snap diff --git a/ui/components/component-library/avatar-icon/avatar-icon.constants.js b/ui/components/component-library/avatar-icon/avatar-icon.constants.js deleted file mode 100644 index 142bba1110af..000000000000 --- a/ui/components/component-library/avatar-icon/avatar-icon.constants.js +++ /dev/null @@ -1,9 +0,0 @@ -import { Size } from '../../../helpers/constants/design-system'; - -export const AVATAR_ICON_SIZES = { - XS: Size.XS, - SM: Size.SM, - MD: Size.MD, - LG: Size.LG, - XL: Size.XL, -}; diff --git a/ui/components/component-library/avatar-icon/avatar-icon.js b/ui/components/component-library/avatar-icon/avatar-icon.js deleted file mode 100644 index 69c6ac57de85..000000000000 --- a/ui/components/component-library/avatar-icon/avatar-icon.js +++ /dev/null @@ -1,96 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classnames from 'classnames'; -import { - BorderColor, - Size, - AlignItems, - JustifyContent, - BackgroundColor, - IconColor, - TextColor, - Display, -} from '../../../helpers/constants/design-system'; - -import { Box } from '../box'; -import { IconName, Icon } from '../icon'; -import { AvatarBase } from '../avatar-base'; - -import { AVATAR_ICON_SIZES } from './avatar-icon.constants'; - -export const AvatarIcon = React.forwardRef( - ( - { - size = Size.MD, - color = TextColor.primaryDefault, - backgroundColor = BackgroundColor.primaryMuted, - className, - iconProps, - iconName, - ...props - }, - ref, - ) => ( - - - - ), -); - -AvatarIcon.propTypes = { - /** - * - * The name of the icon to display. Should be one of IconName - */ - iconName: PropTypes.oneOf(Object.values(IconName)).isRequired, - /** - * Props for the icon inside AvatarIcon. All Icon props can be used - */ - iconProps: PropTypes.object, - /** - * The size of the AvatarIcon - * Possible values could be 'SIZES.XS' 16px, 'SIZES.SM' 24px, 'SIZES.MD' 32px, 'SIZES.LG' 40px, 'SIZES.XL' 48px - * Defaults to SIZES.MD - */ - size: PropTypes.oneOf(Object.values(AVATAR_ICON_SIZES)), - /** - * The background color of the AvatarIcon - * Defaults to BackgroundColor.primaryMuted - */ - backgroundColor: PropTypes.oneOf(Object.values(BackgroundColor)), - /** - * The color of the text inside the AvatarIcon - * Defaults to TextColor.primaryDefault - */ - color: PropTypes.oneOf([ - ...Object.values(TextColor), - ...Object.values(IconColor), - ]), - /** - * Additional classNames to be added to the AvatarIcon - */ - className: PropTypes.string, - /** - * AvatarIcon also accepts all Box props including but not limited to - * className, as(change root element of HTML element) and margin props - */ - ...Box.propTypes, -}; - -AvatarIcon.displayName = 'AvatarIcon'; diff --git a/ui/components/component-library/avatar-icon/avatar-icon.stories.js b/ui/components/component-library/avatar-icon/avatar-icon.stories.tsx similarity index 69% rename from ui/components/component-library/avatar-icon/avatar-icon.stories.js rename to ui/components/component-library/avatar-icon/avatar-icon.stories.tsx index ea5ab99555ce..bcd97d8ccee8 100644 --- a/ui/components/component-library/avatar-icon/avatar-icon.stories.js +++ b/ui/components/component-library/avatar-icon/avatar-icon.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; +import { StoryFn, Meta } from '@storybook/react'; import { - Size, AlignItems, BackgroundColor, IconColor, @@ -13,25 +13,7 @@ import { Box } from '../box'; import { IconName } from '..'; import README from './README.mdx'; -import { AvatarIcon, AVATAR_ICON_SIZES } from '.'; - -const marginSizeControlOptions = [ - undefined, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 'auto', -]; +import { AvatarIcon, AvatarIconSize } from '.'; export default { title: 'Components/ComponentLibrary/AvatarIcon', @@ -48,7 +30,7 @@ export default { }, size: { control: 'select', - options: Object.values(AVATAR_ICON_SIZES), + options: Object.values(AvatarIconSize), }, backgroundColor: { control: 'select', @@ -61,128 +43,105 @@ export default { className: { control: 'text', }, - marginTop: { - options: marginSizeControlOptions, - control: 'select', - table: { category: 'box props' }, - }, - marginRight: { - options: marginSizeControlOptions, - control: 'select', - table: { category: 'box props' }, - }, - marginBottom: { - options: marginSizeControlOptions, - control: 'select', - table: { category: 'box props' }, - }, - marginLeft: { - options: marginSizeControlOptions, - control: 'select', - table: { category: 'box props' }, - }, }, args: { - size: Size.MD, + size: AvatarIconSize.Md, + iconName: IconName.SwapHorizontal, }, -}; +} as Meta; -const Template = (args) => { - return ; +const Template: StoryFn = (args) => { + return ; }; export const DefaultStory = Template.bind({}); DefaultStory.storyName = 'Default'; -export const SizeStory = (args) => ( +export const SizeStory: StoryFn = (args) => ( - - - - - + + + + + ); SizeStory.storyName = 'Size'; -SizeStory.args = { - iconName: IconName.Confirmation, -}; - -export const IconNameStory = (args) => ( +export const IconNameStory: StoryFn = (args) => ( ); IconNameStory.storyName = 'Icon Name'; -export const ColorAndBackgroundColor = (args) => ( +export const ColorAndBackgroundColor: StoryFn = (args) => ( ); diff --git a/ui/components/component-library/avatar-icon/avatar-icon.test.js b/ui/components/component-library/avatar-icon/avatar-icon.test.tsx similarity index 68% rename from ui/components/component-library/avatar-icon/avatar-icon.test.js rename to ui/components/component-library/avatar-icon/avatar-icon.test.tsx index 4262b288b443..554ea0b0567b 100644 --- a/ui/components/component-library/avatar-icon/avatar-icon.test.js +++ b/ui/components/component-library/avatar-icon/avatar-icon.test.tsx @@ -7,7 +7,7 @@ import { BackgroundColor, IconColor, } from '../../../helpers/constants/design-system'; -import { AvatarIcon, AVATAR_ICON_SIZES } from '.'; +import { AvatarIcon, AvatarIconSize } from '.'; describe('AvatarIcon', () => { it('should render correctly', () => { @@ -26,45 +26,45 @@ describe('AvatarIcon', () => { <> , ); - expect(getByTestId(AVATAR_ICON_SIZES.XS)).toHaveClass( - `mm-avatar-base--size-${AVATAR_ICON_SIZES.XS}`, + expect(getByTestId(AvatarIconSize.Xs)).toHaveClass( + `mm-avatar-base--size-${AvatarIconSize.Xs}`, ); - expect(getByTestId(AVATAR_ICON_SIZES.SM)).toHaveClass( - `mm-avatar-base--size-${AVATAR_ICON_SIZES.SM}`, + expect(getByTestId(AvatarIconSize.Sm)).toHaveClass( + `mm-avatar-base--size-${AvatarIconSize.Sm}`, ); - expect(getByTestId(AVATAR_ICON_SIZES.MD)).toHaveClass( - `mm-avatar-base--size-${AVATAR_ICON_SIZES.MD}`, + expect(getByTestId(AvatarIconSize.Md)).toHaveClass( + `mm-avatar-base--size-${AvatarIconSize.Md}`, ); - expect(getByTestId(AVATAR_ICON_SIZES.LG)).toHaveClass( - `mm-avatar-base--size-${AVATAR_ICON_SIZES.LG}`, + expect(getByTestId(AvatarIconSize.Lg)).toHaveClass( + `mm-avatar-base--size-${AvatarIconSize.Lg}`, ); - expect(getByTestId(AVATAR_ICON_SIZES.XL)).toHaveClass( - `mm-avatar-base--size-${AVATAR_ICON_SIZES.XL}`, + expect(getByTestId(AvatarIconSize.Xl)).toHaveClass( + `mm-avatar-base--size-${AvatarIconSize.Xl}`, ); }); @@ -106,9 +106,11 @@ describe('AvatarIcon', () => { ); }); it('should forward a ref to the root html element', () => { - const ref = React.createRef(); + const ref = React.createRef(); render(); expect(ref.current).not.toBeNull(); - expect(ref.current.nodeName).toBe('DIV'); + if (ref.current) { + expect(ref.current.nodeName).toBe('DIV'); + } }); }); diff --git a/ui/components/component-library/avatar-icon/avatar-icon.tsx b/ui/components/component-library/avatar-icon/avatar-icon.tsx new file mode 100644 index 000000000000..f9032e7e354c --- /dev/null +++ b/ui/components/component-library/avatar-icon/avatar-icon.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import classnames from 'classnames'; +import { + BorderColor, + Display, + AlignItems, + JustifyContent, + BackgroundColor, + IconColor, + TextColor, +} from '../../../helpers/constants/design-system'; + +import { Icon } from '../icon'; +import type { PolymorphicRef } from '../box'; +import { AvatarBase, AvatarBaseProps } from '../avatar-base'; +import type { AvatarIconComponent } from './avatar-icon.types'; +import { + AvatarIconProps, + AvatarIconSize, + avatarIconSizeToIconSize, +} from './avatar-icon.types'; + +export const AvatarIcon: AvatarIconComponent = React.forwardRef( + ( + { + size = AvatarIconSize.Md, + color = TextColor.primaryDefault, + backgroundColor = BackgroundColor.primaryMuted, + className = '', + iconProps, + iconName, + ...props + }: AvatarIconProps, + ref?: PolymorphicRef, + ) => { + const iconSize = avatarIconSizeToIconSize[size]; + return ( + )} + > + + + ); + }, +); diff --git a/ui/components/component-library/avatar-icon/avatar-icon.types.ts b/ui/components/component-library/avatar-icon/avatar-icon.types.ts new file mode 100644 index 000000000000..6e157430ebe8 --- /dev/null +++ b/ui/components/component-library/avatar-icon/avatar-icon.types.ts @@ -0,0 +1,50 @@ +import { IconColor, TextColor } from '../../../helpers/constants/design-system'; +import { IconName, IconSize, IconStyleUtilityProps } from '../icon'; +import type { PolymorphicComponentPropWithRef } from '../box'; +import type { AvatarBaseStyleUtilityProps } from '../avatar-base/avatar-base.types'; + +export enum AvatarIconSize { + Xs = 'xs', + Sm = 'sm', + Md = 'md', + Lg = 'lg', + Xl = 'xl', +} + +export const avatarIconSizeToIconSize: Record = { + [AvatarIconSize.Xs]: IconSize.Xs, + [AvatarIconSize.Sm]: IconSize.Sm, + [AvatarIconSize.Md]: IconSize.Md, + [AvatarIconSize.Lg]: IconSize.Lg, + [AvatarIconSize.Xl]: IconSize.Xl, +}; + +export interface AvatarIconStyleUtilityProps + extends Omit { + /** + * The name of the icon to display. Should be one of IconName + */ + iconName: IconName; + /** + * Props for the icon inside AvatarIcon. All Icon props can be used + */ + iconProps?: IconStyleUtilityProps; + /** + * The size of the AvatarIcon + * Possible values could be 'AvatarIconSize.Xs' 16px, 'AvatarIconSize.Sm' 24px, 'AvatarIconSize.Md' 32px, 'AvatarIconSize.Lg' 40px, 'AvatarIconSize.Xl' 48px + * Defaults to AvatarIconSize.Md + */ + size?: AvatarIconSize; + /** + * The color of the text inside the AvatarIcon + * Defaults to TextColor.primaryDefault + */ + color?: TextColor | IconColor; +} + +export type AvatarIconProps = + PolymorphicComponentPropWithRef; + +export type AvatarIconComponent = ( + props: AvatarIconProps, +) => React.ReactElement | null; diff --git a/ui/components/component-library/avatar-icon/index.js b/ui/components/component-library/avatar-icon/index.js deleted file mode 100644 index 22612fd57096..000000000000 --- a/ui/components/component-library/avatar-icon/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { AvatarIcon } from './avatar-icon'; -export { AVATAR_ICON_SIZES } from './avatar-icon.constants'; diff --git a/ui/components/component-library/avatar-icon/index.ts b/ui/components/component-library/avatar-icon/index.ts new file mode 100644 index 000000000000..6a6597445e94 --- /dev/null +++ b/ui/components/component-library/avatar-icon/index.ts @@ -0,0 +1,3 @@ +export { AvatarIcon } from './avatar-icon'; +export { AvatarIconSize } from './avatar-icon.types'; +export type { AvatarIconProps } from './avatar-icon.types'; diff --git a/ui/components/component-library/index.js b/ui/components/component-library/index.js index d37a90c72389..be27c16f0a34 100644 --- a/ui/components/component-library/index.js +++ b/ui/components/component-library/index.js @@ -5,7 +5,7 @@ export { AvatarAccountDiameter, } from './avatar-account'; export { AvatarFavicon, AVATAR_FAVICON_SIZES } from './avatar-favicon'; -export { AvatarIcon, AVATAR_ICON_SIZES } from './avatar-icon'; +export { AvatarIcon, AvatarIconSize } from './avatar-icon'; export { AvatarNetwork, AvatarNetworkSize } from './avatar-network'; export { AvatarToken, AvatarTokenSize } from './avatar-token'; export { AvatarBase, AvatarBaseSize } from './avatar-base';