diff --git a/ui/components/component-library/avatar-network/README.mdx b/ui/components/component-library/avatar-network/README.mdx new file mode 100644 index 000000000..e5b1b2243 --- /dev/null +++ b/ui/components/component-library/avatar-network/README.mdx @@ -0,0 +1,67 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { AvatarNetwork } from './avatar-network'; + +# AvatarNetwork + +The `AvatarNetwork` is a component responsible for display of the image of a given network + + + + + +## Props + +The `AvatarNetwork` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story) component props + + + +### Size + +Use the `size` prop to set the size of the `AvatarNetwork`. + +Possible sizes include: + +- `xs` 16px +- `sm` 24px +- `md` 32px +- `lg` 40px +- `xl` 48px + +Defaults to `md` + + + + + +### Network Name + +Use the `networkName` prop to set the initial alphabet of the `AvatarNetwork`. This will be used as the fallback display if no image url is passed to the `networkImageUrl` prop. + + + + + +### Network Image Url + +Use the `networkImageUrl` prop to set the image to be rendered of the `AvatarNetwork`. + + + + + +### Show Halo + +If we want to display the component with halo effect. Only works if an image url is supplied to `networkImageUrl` + + + + + +### Color, Background Color And Border Color + +Use the `color`, `backgroundColor` and `borderColor` props to set the text color, background-color and border-color of the `AvatarToken`. + + + + \ No newline at end of file diff --git a/ui/components/component-library/avatar-network/avatar-network.js b/ui/components/component-library/avatar-network/avatar-network.js new file mode 100644 index 000000000..e90013913 --- /dev/null +++ b/ui/components/component-library/avatar-network/avatar-network.js @@ -0,0 +1,123 @@ +import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { BaseAvatar } from '../base-avatar'; +import Box from '../../ui/box/box'; + +import { + COLORS, + SIZES, + DISPLAY, + ALIGN_ITEMS, + JUSTIFY_CONTENT, +} from '../../../helpers/constants/design-system'; + +export const AvatarNetwork = ({ + size = SIZES.MD, + networkName, + networkImageUrl, + showHalo, + color = COLORS.TEXT_DEFAULT, + backgroundColor = COLORS.BACKGROUND_ALTERNATIVE, + borderColor = COLORS.TRANSPARENT, + className, + ...props +}) => { + const [showFallback, setShowFallback] = useState(false); + + useEffect(() => { + setShowFallback(!networkImageUrl); + }, [networkImageUrl]); + + const fallbackString = networkName && networkName[0] ? networkName[0] : '?'; + + const handleOnError = () => { + setShowFallback(true); + }; + + return ( + + {showFallback ? ( + fallbackString + ) : ( + <> + {showHalo && ( + + )} + {networkName + + )} + + ); +}; + +AvatarNetwork.propTypes = { + /** + * The networkName accepts the string to render the first alphabet of the Avatar Name + */ + networkName: PropTypes.string, + /** + * The networkImageUrl accepts the string of the image to be rendered + */ + networkImageUrl: PropTypes.string, + /** + * The showHalo accepts a boolean prop to render the image with halo effect + */ + showHalo: PropTypes.bool, + /** + * The size of the AvatarNetwork + * Possible values could be 'SIZES.XS', 'SIZES.SM', 'SIZES.MD', 'SIZES.LG', 'SIZES.XL' + * Defaults to SIZES.MD + */ + size: PropTypes.oneOf(Object.values(SIZES)), + /** + * The background color of the AvatarNetwork + * Defaults to COLORS.BACKGROUND_ALTERNATIVE + */ + backgroundColor: Box.propTypes.backgroundColor, + /** + * The background color of the AvatarNetwork + * Defaults to COLORS.BORDER_DEFAULT + */ + borderColor: Box.propTypes.borderColor, + /** + * The color of the text inside the AvatarNetwork + * Defaults to COLORS.TEXT_DEFAULT + */ + color: Box.propTypes.color, + /** + * Additional classNames to be added to the AvatarNetwork + */ + className: PropTypes.string, + /** + * AvatarNetwork 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-network/avatar-network.scss b/ui/components/component-library/avatar-network/avatar-network.scss new file mode 100644 index 000000000..959edc11e --- /dev/null +++ b/ui/components/component-library/avatar-network/avatar-network.scss @@ -0,0 +1,23 @@ +.avatar-network { + &--with-halo { + position: relative; + } + + &__network-image { + width: 100%; + + &--blurred { + filter: blur(20px); + } + + &--size-reduced { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 62.5%; + height: 62.5%; + border-radius: 50%; + } + } +} diff --git a/ui/components/component-library/avatar-network/avatar-network.stories.js b/ui/components/component-library/avatar-network/avatar-network.stories.js new file mode 100644 index 000000000..b8eafc496 --- /dev/null +++ b/ui/components/component-library/avatar-network/avatar-network.stories.js @@ -0,0 +1,123 @@ +import React from 'react'; +import { + COLORS, + SIZES, + DISPLAY, + ALIGN_ITEMS, + TEXT_COLORS, + BACKGROUND_COLORS, + BORDER_COLORS, +} from '../../../helpers/constants/design-system'; + +import Box from '../../ui/box/box'; + +import README from './README.mdx'; +import { AvatarNetwork } from './avatar-network'; + +export default { + title: 'Components/ComponentLibrary/AvatarNetwork', + id: __filename, + component: AvatarNetwork, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + size: { + control: 'select', + options: Object.values(SIZES), + }, + color: { + options: Object.values(TEXT_COLORS), + control: 'select', + }, + backgroundColor: { + options: Object.values(BACKGROUND_COLORS), + control: 'select', + }, + borderColor: { + options: Object.values(BORDER_COLORS), + control: 'select', + }, + networkName: { + control: 'text', + }, + networkImageUrl: { + control: 'text', + }, + showHalo: { + control: 'boolean', + }, + }, + args: { + networkName: 'Arbitrum One', + networkImageUrl: './images/arbitrum.svg', + size: SIZES.MD, + showHalo: false, + }, +}; + +const Template = (args) => { + return ; +}; +export const DefaultStory = Template.bind({}); +DefaultStory.storyName = 'Default'; + +export const Size = (args) => ( + + + + + + + +); + +export const networkName = Template.bind({}); +networkName.args = { + networkImageUrl: '', +}; + +export const networkImageUrl = Template.bind({}); + +export const showHalo = Template.bind({}); +showHalo.args = { + showHalo: true, +}; + +export const ColorBackgroundColorAndBorderColor = (args) => ( + + + + + + +); +ColorBackgroundColorAndBorderColor.args = { + networkImageUrl: '', +}; diff --git a/ui/components/component-library/avatar-network/avatar-network.test.js b/ui/components/component-library/avatar-network/avatar-network.test.js new file mode 100644 index 000000000..ce9aced85 --- /dev/null +++ b/ui/components/component-library/avatar-network/avatar-network.test.js @@ -0,0 +1,56 @@ +/* eslint-disable jest/require-top-level-describe */ +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { AvatarNetwork } from './avatar-network'; + +describe('AvatarNetwork', () => { + const args = { + networkName: 'ethereum', + networkImageUrl: './images/eth_logo.svg', + showHalo: false, + }; + + it('should render correctly', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('avatar-network')).toBeDefined(); + }); + + it('should render image of Avatar Network', () => { + render(); + const image = screen.getByRole('img'); + expect(image).toBeDefined(); + expect(image).toHaveAttribute('src', args.networkImageUrl); + }); + + it('should render the first letter of the networkName prop if no networkImageUrl is provided', () => { + const { getByText } = render( + , + ); + expect(getByText('e')).toBeDefined(); + }); + + it('should render halo effect if showHalo is true and image url is there', () => { + render(); + const image = screen.getAllByRole('img', { hidden: true }); + expect(image[1]).toHaveClass('avatar-network__network-image--size-reduced'); + }); + + it('should render the first letter of the networkName prop when showHalo is true and no image url is provided', () => { + const { getByText } = render( + , + ); + expect(getByText('e')).toBeDefined(); + }); +}); diff --git a/ui/components/component-library/avatar-network/index.js b/ui/components/component-library/avatar-network/index.js new file mode 100644 index 000000000..8ee3e741d --- /dev/null +++ b/ui/components/component-library/avatar-network/index.js @@ -0,0 +1 @@ +export { AvatarNetwork } from './avatar-network'; diff --git a/ui/components/component-library/avatar-token/README.mdx b/ui/components/component-library/avatar-token/README.mdx index 45a817609..800a7aef6 100644 --- a/ui/components/component-library/avatar-token/README.mdx +++ b/ui/components/component-library/avatar-token/README.mdx @@ -36,7 +36,7 @@ Defaults to `md` ### Token Name -Use the ` tokenName` prop to set the initial letter of the `AvatarToken`. This will be used as the fallback display if no image url is passed to the `tokenImageUrl` prop. +Use the `tokenName` prop to set the initial letter of the `AvatarToken`. This will be used as the fallback display if no image url is passed to the `tokenImageUrl` prop. diff --git a/ui/components/component-library/avatar-token/avatar-token.test.js b/ui/components/component-library/avatar-token/avatar-token.test.js index 4f7a443bd..fe6c3b597 100644 --- a/ui/components/component-library/avatar-token/avatar-token.test.js +++ b/ui/components/component-library/avatar-token/avatar-token.test.js @@ -36,7 +36,7 @@ describe('AvatarToken', () => { expect(image[1]).toHaveClass('avatar-token__token-image--size-reduced'); }); - it('should render text showHalo is true and no image url is provided', () => { + it('should render the first letter of the tokenName prop when showHalo is true and no image url is provided', () => { const { getByText } = render(