diff --git a/ui/components/component-library/avatar-icon/README.mdx b/ui/components/component-library/avatar-icon/README.mdx new file mode 100644 index 000000000..0963998e1 --- /dev/null +++ b/ui/components/component-library/avatar-icon/README.mdx @@ -0,0 +1,97 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { AvatarBase } from '../'; +import { AvatarIcon } from './avatar-icon'; + +# AvatarIcon + +The `AvatarIcon` is an avatar component that renders only an icon inside and is built off the [AvatarBase](/docs/ui-components-component-library-avatar-base-avatar-base-stories-js--default-story#props) component + + + + + +## Props + +The `AvatarIcon` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story) component props + + + +`AvatarIcon` accepts all [AvatarBase](/docs/ui-components-component-library-avatar-base-avatar-base-stories-js--default-story#props) +component props + + + +### Size + +Use the `size` prop and the `SIZES` 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 `SIZES` + +Possible sizes include: + +- `SIZES.XS` 16px +- `SIZES.SM` 24px +- `SIZES.MD` 32px +- `SIZES.LG` 40px +- `SIZES.XL` 48px + +Defaults to `SIZES.MD` + + + + + +```jsx +import { SIZES } from '../../../helpers/constants/design-system'; +import { AvatarIcon, ICON_NAMES } from '../ui/component-library'; + + + + + + +``` + +### Icon Name\* + +Use the required `iconName` prop with `ICON_NAMES` object from `./ui/components/component-library` to select icon + +Use the [IconSearch](/story/ui-components-component-library-icon-icon-stories-js--default-story) story to find the icon you want to use. + + + + + +```jsx +import { AvatarIcon, ICON_NAMES } from '../ui/component-library'; + + + + + + +``` + +### Color and Background Color + +Use the `color` and `backgroundColor` props with the `COLORS` object from `./ui/helpers/constants/design-system.js` to change the icon color and background color of `AvatarIcon` + +`color` default: `COLORS.COLORS.PRIMARY_DEFAULT` +`backgroundColor` default: `COLORS.COLORS.PRIMARY_MUTED` + + + + + +```jsx +import { COLORS } from '../../../helpers/constants/design-system'; +import { AvatarIcon } from '../ui/component-library'; + + + + + + + +``` 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.js.snap new file mode 100644 index 000000000..94ba48ffc --- /dev/null +++ b/ui/components/component-library/avatar-icon/__snapshots__/avatar-icon.test.js.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AvatarIcon should render correctly 1`] = ` +
+
+
+
+
+`; diff --git a/ui/components/component-library/avatar-icon/avatar-icon.constants.js b/ui/components/component-library/avatar-icon/avatar-icon.constants.js new file mode 100644 index 000000000..a65ebe01c --- /dev/null +++ b/ui/components/component-library/avatar-icon/avatar-icon.constants.js @@ -0,0 +1,9 @@ +import { SIZES } from '../../../helpers/constants/design-system'; + +export const AVATAR_ICON_SIZES = { + XS: SIZES.XS, + SM: SIZES.SM, + MD: SIZES.MD, + LG: SIZES.LG, + XL: SIZES.XL, +}; diff --git a/ui/components/component-library/avatar-icon/avatar-icon.js b/ui/components/component-library/avatar-icon/avatar-icon.js new file mode 100644 index 000000000..b362e0174 --- /dev/null +++ b/ui/components/component-library/avatar-icon/avatar-icon.js @@ -0,0 +1,81 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { + COLORS, + BORDER_COLORS, + SIZES, + DISPLAY, + ALIGN_ITEMS, + JUSTIFY_CONTENT, +} from '../../../helpers/constants/design-system'; + +import Box from '../../ui/box/box'; + +import { Icon } from '../icon'; +import { AvatarBase } from '../avatar-base'; + +import { AVATAR_ICON_SIZES } from './avatar-icon.constants'; + +export const AvatarIcon = ({ + size = SIZES.MD, + color = COLORS.PRIMARY_DEFAULT, + backgroundColor = COLORS.PRIMARY_MUTED, + className, + iconProps, + iconName, + ...props +}) => { + return ( + + + + ); +}; + +AvatarIcon.propTypes = { + /** + * + * The name of the icon to display. Should be one of ICON_NAMES + */ + iconName: PropTypes.string.isRequired, // Can't set PropTypes.oneOf(ICON_NAMES) because ICON_NAMES is an environment variable + /** + * Props for the icon inside AvatarIcon. All Icon props can be used + */ + iconProps: PropTypes.shape(Icon.PropTypes), + /** + * 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 COLORS.PRIMARY_MUTED + */ + backgroundColor: Box.propTypes.backgroundColor, + /** + * The color of the text inside the AvatarIcon + * Defaults to COLORS.PRIMARY_DEFAULT + */ + color: Box.propTypes.color, + /** + * 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, +}; diff --git a/ui/components/component-library/avatar-icon/avatar-icon.stories.js b/ui/components/component-library/avatar-icon/avatar-icon.stories.js new file mode 100644 index 000000000..399b9d8ff --- /dev/null +++ b/ui/components/component-library/avatar-icon/avatar-icon.stories.js @@ -0,0 +1,185 @@ +import React from 'react'; +import { + SIZES, + DISPLAY, + ALIGN_ITEMS, + COLORS, + BACKGROUND_COLORS, +} from '../../../helpers/constants/design-system'; + +import Box from '../../ui/box/box'; + +import { ICON_NAMES } 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', +]; + +export default { + title: 'Components/ComponentLibrary/AvatarIcon', + id: __filename, + component: AvatarIcon, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + iconName: { + options: Object.values(ICON_NAMES), + control: 'select', + }, + size: { + control: 'select', + options: Object.values(AVATAR_ICON_SIZES), + }, + backgroundColor: { + control: 'select', + options: Object.values(BACKGROUND_COLORS), + }, + color: { + control: 'select', + options: Object.values(COLORS), + }, + 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: SIZES.MD, + }, +}; + +const Template = (args) => { + return ; +}; + +export const DefaultStory = Template.bind({}); +DefaultStory.storyName = 'Default'; + +export const Size = (args) => ( + + + + + + + +); + +Size.args = { + iconName: ICON_NAMES.CHECK_CIRCLE_ON_FILLED, +}; + +export const IconName = (args) => ( + + + + + + + +); + +export const ColorAndBackgroundColor = (args) => ( + + + + + + + + +); diff --git a/ui/components/component-library/avatar-icon/avatar-icon.test.js b/ui/components/component-library/avatar-icon/avatar-icon.test.js new file mode 100644 index 000000000..144a31492 --- /dev/null +++ b/ui/components/component-library/avatar-icon/avatar-icon.test.js @@ -0,0 +1,105 @@ +/* eslint-disable jest/require-top-level-describe */ +import { render } from '@testing-library/react'; +import React from 'react'; + +import { ICON_NAMES } from '..'; +import { COLORS } from '../../../helpers/constants/design-system'; +import { AvatarIcon, AVATAR_ICON_SIZES } from '.'; + +describe('AvatarIcon', () => { + it('should render correctly', () => { + const { getByTestId, container } = render( + , + ); + expect(getByTestId('avatar-icon')).toBeDefined(); + expect(container).toMatchSnapshot(); + }); + + it('should render with different size classes', () => { + const { getByTestId } = render( + <> + + + + + + , + ); + expect(getByTestId(AVATAR_ICON_SIZES.XS)).toHaveClass( + `mm-avatar-base--size-${AVATAR_ICON_SIZES.XS}`, + ); + expect(getByTestId(AVATAR_ICON_SIZES.SM)).toHaveClass( + `mm-avatar-base--size-${AVATAR_ICON_SIZES.SM}`, + ); + expect(getByTestId(AVATAR_ICON_SIZES.MD)).toHaveClass( + `mm-avatar-base--size-${AVATAR_ICON_SIZES.MD}`, + ); + expect(getByTestId(AVATAR_ICON_SIZES.LG)).toHaveClass( + `mm-avatar-base--size-${AVATAR_ICON_SIZES.LG}`, + ); + expect(getByTestId(AVATAR_ICON_SIZES.XL)).toHaveClass( + `mm-avatar-base--size-${AVATAR_ICON_SIZES.XL}`, + ); + }); + + it('should render with added classname', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('classname')).toHaveClass('mm-avatar-icon--test'); + }); + + it('should render with icon', () => { + const { getByTestId } = render( + , + ); + + expect(getByTestId('avatar-icon')).toBeDefined(); + }); + + it('should render with success color icon and background color', () => { + const { getByTestId } = render( + , + ); + + expect(getByTestId('success')).toHaveClass('box--color-success-default'); + expect(getByTestId('success')).toHaveClass( + 'box--background-color-success-muted', + ); + }); +}); diff --git a/ui/components/component-library/avatar-icon/index.js b/ui/components/component-library/avatar-icon/index.js new file mode 100644 index 000000000..22612fd57 --- /dev/null +++ b/ui/components/component-library/avatar-icon/index.js @@ -0,0 +1,2 @@ +export { AvatarIcon } from './avatar-icon'; +export { AVATAR_ICON_SIZES } from './avatar-icon.constants'; diff --git a/ui/components/component-library/index.js b/ui/components/component-library/index.js index 01305770b..547d29f69 100644 --- a/ui/components/component-library/index.js +++ b/ui/components/component-library/index.js @@ -1,5 +1,6 @@ export { AvatarAccount } from './avatar-account'; export { AvatarFavicon } from './avatar-favicon'; +export { AvatarIcon, AVATAR_ICON_SIZES } from './avatar-icon'; export { AvatarNetwork } from './avatar-network'; export { AvatarToken } from './avatar-token'; export { AvatarWithBadge } from './avatar-with-badge';