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 typofeature/default_network_editable
parent
47f7096d35
commit
9372ce0ec7
@ -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', |
||||
); |
||||
}); |
||||
}); |
@ -0,0 +1 @@ |
||||
export { AvatarFavicon } from './avatar-favicon'; |
Loading…
Reference in new issue