mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 18:00:18 +01:00
added AvatarFavicon component (#16135)
* added AvatarFavicon component * updated AvatarFavicon Readme * updated avatar favicon component * added fallback props to avatar favicon * updated test for avatar favicon * updated avatar favicon component * updated typo
This commit is contained in:
parent
47f7096d35
commit
9372ce0ec7
44
ui/components/component-library/avatar-favicon/README.mdx
Normal file
44
ui/components/component-library/avatar-favicon/README.mdx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { Story, Canvas, ArgsTable } from '@storybook/addon-docs';
|
||||||
|
|
||||||
|
import { AvatarFavicon } from './avatar-favicon';
|
||||||
|
|
||||||
|
# AvatarFavicon
|
||||||
|
|
||||||
|
The `AvatarFavicon` is an image component that renders an icon that is provided in the form of a URL.
|
||||||
|
|
||||||
|
<Canvas>
|
||||||
|
<Story id="ui-components-component-library-avatar-favicon-avatar-favicon-stories-js--default-story" />
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
The `AvatarFavicon` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story) component props
|
||||||
|
|
||||||
|
<ArgsTable of={AvatarFavicon} />
|
||||||
|
|
||||||
|
### Size
|
||||||
|
|
||||||
|
Use the `size` prop to set the size of the `AvatarFavicon`.
|
||||||
|
|
||||||
|
Possible sizes include:
|
||||||
|
|
||||||
|
- `xs` 16px
|
||||||
|
- `sm` 24px
|
||||||
|
- `md` 32px
|
||||||
|
- `lg` 40px
|
||||||
|
- `xl` 48px
|
||||||
|
|
||||||
|
Defaults to `md`
|
||||||
|
|
||||||
|
<Canvas>
|
||||||
|
<Story id="ui-components-component-library-avatar-favicon-avatar-favicon-stories-js--size" />
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
### Image Source
|
||||||
|
|
||||||
|
Use the `imageSource` prop to set the image to be rendered of the `AvatarFavicon`.
|
||||||
|
|
||||||
|
### Fallback Icon Props
|
||||||
|
|
||||||
|
If there is no `imageSource` then in that case an [icon](/docs/ui-components-component-library-icon-icon-stories-js--default-story) will be used as the fallback display and it can be customised via `fallbackIconProps`.
|
||||||
|
|
@ -0,0 +1,82 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import { BaseAvatar } from '../base-avatar';
|
||||||
|
import Box from '../../ui/box/box';
|
||||||
|
import { ICON_NAMES, Icon } from '../icon';
|
||||||
|
import {
|
||||||
|
COLORS,
|
||||||
|
BORDER_COLORS,
|
||||||
|
SIZES,
|
||||||
|
DISPLAY,
|
||||||
|
ALIGN_ITEMS,
|
||||||
|
JUSTIFY_CONTENT,
|
||||||
|
} from '../../../helpers/constants/design-system';
|
||||||
|
|
||||||
|
export const AvatarFavicon = ({
|
||||||
|
size = SIZES.MD,
|
||||||
|
imageSource,
|
||||||
|
imgAlt = 'avatar-favicon',
|
||||||
|
className,
|
||||||
|
fallbackIconProps,
|
||||||
|
borderColor = BORDER_COLORS.TRANSPARENT,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<BaseAvatar
|
||||||
|
size={size}
|
||||||
|
display={DISPLAY.FLEX}
|
||||||
|
alignItems={ALIGN_ITEMS.CENTER}
|
||||||
|
justifyContent={JUSTIFY_CONTENT.CENTER}
|
||||||
|
className={classnames('avatar-favicon', className)}
|
||||||
|
{...{ borderColor, ...props }}
|
||||||
|
>
|
||||||
|
{imageSource ? (
|
||||||
|
<img className="avatar-favicon__image" src={imageSource} alt={imgAlt} />
|
||||||
|
) : (
|
||||||
|
<Icon
|
||||||
|
name={ICON_NAMES.GLOBAL_FILLED}
|
||||||
|
color={COLORS.ICON_DEFAULT}
|
||||||
|
size={size}
|
||||||
|
aria-label={imgAlt}
|
||||||
|
{...fallbackIconProps}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</BaseAvatar>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
AvatarFavicon.propTypes = {
|
||||||
|
/**
|
||||||
|
* The imageSource accepts the string of the image to be rendered
|
||||||
|
*/
|
||||||
|
imageSource: PropTypes.string,
|
||||||
|
/**
|
||||||
|
* The alt text for the favicon avatar to be rendered
|
||||||
|
*/
|
||||||
|
imgAlt: PropTypes.string,
|
||||||
|
/**
|
||||||
|
* Props for the fallback icon. All Icon props can be used
|
||||||
|
*/
|
||||||
|
fallbackIconProps: PropTypes.shape(Icon.PropTypes),
|
||||||
|
/**
|
||||||
|
* The size of the AvatarFavicon
|
||||||
|
* 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 border color of the AvatarFavicon
|
||||||
|
* Defaults to COLORS.TRANSPARENT
|
||||||
|
*/
|
||||||
|
borderColor: Box.propTypes.borderColor,
|
||||||
|
/**
|
||||||
|
* Additional classNames to be added to the AvatarFavicon
|
||||||
|
*/
|
||||||
|
className: PropTypes.string,
|
||||||
|
/**
|
||||||
|
* AvatarFavicon also accepts all Box props including but not limited to
|
||||||
|
* className, as(change root element of HTML element) and margin props
|
||||||
|
*/
|
||||||
|
...Box.propTypes,
|
||||||
|
};
|
@ -0,0 +1,5 @@
|
|||||||
|
.avatar-favicon {
|
||||||
|
&__image {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
SIZES,
|
||||||
|
DISPLAY,
|
||||||
|
ALIGN_ITEMS,
|
||||||
|
BORDER_COLORS,
|
||||||
|
} from '../../../helpers/constants/design-system';
|
||||||
|
|
||||||
|
import Box from '../../ui/box/box';
|
||||||
|
|
||||||
|
import README from './README.mdx';
|
||||||
|
import { AvatarFavicon } from './avatar-favicon';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Components/ComponentLibrary/AvatarFavicon',
|
||||||
|
id: __filename,
|
||||||
|
component: AvatarFavicon,
|
||||||
|
parameters: {
|
||||||
|
docs: {
|
||||||
|
page: README,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
size: {
|
||||||
|
control: 'select',
|
||||||
|
options: Object.values(SIZES),
|
||||||
|
},
|
||||||
|
imageSource: {
|
||||||
|
control: 'text',
|
||||||
|
},
|
||||||
|
borderColor: {
|
||||||
|
options: Object.values(BORDER_COLORS),
|
||||||
|
control: 'select',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
imageSource: 'https://uniswap.org/favicon.ico',
|
||||||
|
size: SIZES.MD,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const Template = (args) => {
|
||||||
|
return <AvatarFavicon {...args} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DefaultStory = Template.bind({});
|
||||||
|
DefaultStory.storyName = 'Default';
|
||||||
|
|
||||||
|
export const Size = (args) => (
|
||||||
|
<Box display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.BASELINE} gap={1}>
|
||||||
|
<AvatarFavicon {...args} size={SIZES.XS} />
|
||||||
|
<AvatarFavicon {...args} size={SIZES.SM} />
|
||||||
|
<AvatarFavicon {...args} size={SIZES.MD} />
|
||||||
|
<AvatarFavicon {...args} size={SIZES.LG} />
|
||||||
|
<AvatarFavicon {...args} size={SIZES.XL} />
|
||||||
|
</Box>
|
||||||
|
);
|
@ -0,0 +1,46 @@
|
|||||||
|
/* eslint-disable jest/require-top-level-describe */
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { AvatarFavicon } from './avatar-favicon';
|
||||||
|
|
||||||
|
describe('AvatarFavicon', () => {
|
||||||
|
const args = {
|
||||||
|
imageSource: './images/eth_logo.svg',
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should render correctly', () => {
|
||||||
|
const { getByTestId } = render(
|
||||||
|
<AvatarFavicon data-testid="avatar-favicon" />,
|
||||||
|
);
|
||||||
|
expect(getByTestId('avatar-favicon')).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render image of Avatar Favicon', () => {
|
||||||
|
render(<AvatarFavicon data-testid="avatar-favicon" {...args} />);
|
||||||
|
const image = screen.getByRole('img');
|
||||||
|
expect(image).toBeDefined();
|
||||||
|
expect(image).toHaveAttribute('src', args.imageSource);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render fallback image if no ImageSource is provided', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<AvatarFavicon data-testid="avatar-favicon" />,
|
||||||
|
);
|
||||||
|
expect(container.getElementsByClassName('icon')).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render fallback image with custom fallbackIconProps if no ImageSource is provided', () => {
|
||||||
|
const container = (
|
||||||
|
<AvatarFavicon
|
||||||
|
data-testid="avatar-favicon"
|
||||||
|
fallbackIconProps={{
|
||||||
|
'data-testid': 'fallback-icon',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
expect(container.props.fallbackIconProps['data-testid']).toStrictEqual(
|
||||||
|
'fallback-icon',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
1
ui/components/component-library/avatar-favicon/index.js
Normal file
1
ui/components/component-library/avatar-favicon/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { AvatarFavicon } from './avatar-favicon';
|
@ -1,5 +1,6 @@
|
|||||||
/** Please import your files in alphabetical order **/
|
/** Please import your files in alphabetical order **/
|
||||||
@import 'avatar-account/avatar-account';
|
@import 'avatar-account/avatar-account';
|
||||||
|
@import 'avatar-favicon/avatar-favicon';
|
||||||
@import 'avatar-network/avatar-network';
|
@import 'avatar-network/avatar-network';
|
||||||
@import 'avatar-token/avatar-token';
|
@import 'avatar-token/avatar-token';
|
||||||
@import 'avatar-with-badge/avatar-with-badge';
|
@import 'avatar-with-badge/avatar-with-badge';
|
||||||
|
Loading…
Reference in New Issue
Block a user