mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Added AvatarBadge component (#15676)
* avatar badge component added * resolved conflicts * added badge prop * updated avatar badge children/badge props * updated badge token size to be 16px * added AvatarBadge Test component * added avatar badge test * updated avatarBadge props * added Readme and test files to AvatarWithBadge Component * resolved conflicts * removed unused change * updated badge and badge props * updated avatar badge stories * updated constants for avatar badge * updated avatar badge test * replaced avatar-badge with avatar-with-badge * updated avatar badge tests * updated test for badgeProps
This commit is contained in:
parent
6781171d06
commit
0fe3633e4d
37
ui/components/component-library/avatar-with-badge/README.mdx
Normal file
37
ui/components/component-library/avatar-with-badge/README.mdx
Normal file
@ -0,0 +1,37 @@
|
||||
import { Story, Canvas, ArgsTable } from '@storybook/addon-docs';
|
||||
|
||||
import { AvatarWithBadge } from './avatar-with-badge';
|
||||
|
||||
# AvatarWithBadge
|
||||
|
||||
The `AvatarWithBadge` is a wrapper component that adds badge display options to avatars.
|
||||
|
||||
<Canvas>
|
||||
<Story id="ui-components-component-library-avatar-with-badge-avatar-with-badge-stories-js--default-story" />
|
||||
</Canvas>
|
||||
|
||||
## Props
|
||||
|
||||
The `AvatarWithBadge` accepts all props below
|
||||
|
||||
<ArgsTable of={AvatarWithBadge} />
|
||||
|
||||
### Badge Position
|
||||
|
||||
Use the `badgePosition` prop to set the position of the badge, it can have two values `Top` and `Bottom`
|
||||
|
||||
<Canvas>
|
||||
<Story id="ui-components-component-library-avatar-with-badge-avatar-with-badge-stories-js--badge-positions" />
|
||||
</Canvas>
|
||||
|
||||
### Badge
|
||||
|
||||
Used to define the badge component to be rendered inside the `AvatarWithBadge`
|
||||
|
||||
### Badge Props
|
||||
|
||||
The required props to be passed to the badge.
|
||||
|
||||
### Children
|
||||
|
||||
The children to be rendered inside the AvatarWithBadge. Generally used with the `AvatarAccount`
|
@ -0,0 +1,4 @@
|
||||
export const BADGE_POSITIONS = {
|
||||
TOP: 'top',
|
||||
BOTTOM: 'bottom',
|
||||
};
|
@ -0,0 +1,56 @@
|
||||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import Box from '../../ui/box/box';
|
||||
import { BADGE_POSITIONS } from './avatar-with-badge.constants';
|
||||
|
||||
export const AvatarWithBadge = ({
|
||||
children,
|
||||
badgePosition,
|
||||
className,
|
||||
badge,
|
||||
badgeWrapperProps,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<Box className={classnames('avatar-with-badge', className)} {...props}>
|
||||
{/* Generally the AvatarAccount */}
|
||||
{children}
|
||||
<Box
|
||||
className={
|
||||
badgePosition === 'top'
|
||||
? 'avatar-with-badge__badge-wrapper--position-top'
|
||||
: 'avatar-with-badge__badge-wrapper--position-bottom'
|
||||
}
|
||||
{...badgeWrapperProps}
|
||||
>
|
||||
{/* Generally the AvatarNetwork at SIZES.XS */}
|
||||
{badge}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
AvatarWithBadge.propTypes = {
|
||||
/**
|
||||
* The position of the Badge
|
||||
* Possible values could be 'top', 'bottom',
|
||||
*/
|
||||
badgePosition: PropTypes.oneOf(Object.values(BADGE_POSITIONS)),
|
||||
/**
|
||||
* The Badge Wrapper props of the component. All Box props can be used
|
||||
*/
|
||||
badgeWrapperProps: PropTypes.shape(Box.PropTypes),
|
||||
/**
|
||||
* The children to be rendered inside the AvatarWithBadge
|
||||
*/
|
||||
children: PropTypes.node,
|
||||
/**
|
||||
* The badge to be rendered inside the AvatarWithBadge
|
||||
*/
|
||||
badge: PropTypes.object,
|
||||
/**
|
||||
* Add custom css class
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
.avatar-with-badge {
|
||||
position: relative;
|
||||
width: fit-content;
|
||||
|
||||
&__badge-wrapper--position-top {
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
right: -4px;
|
||||
}
|
||||
|
||||
&__badge-wrapper--position-bottom {
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
right: -4px;
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
import React from 'react';
|
||||
import { AvatarAccount } from '../avatar-account';
|
||||
import { TYPES } from '../avatar-account/avatar-account.constants';
|
||||
import { AvatarNetwork } from '../avatar-network';
|
||||
import Box from '../../ui/box/box';
|
||||
import {
|
||||
ALIGN_ITEMS,
|
||||
DISPLAY,
|
||||
SIZES,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import { BADGE_POSITIONS } from './avatar-with-badge.constants';
|
||||
import README from './README.mdx';
|
||||
import { AvatarWithBadge } from './avatar-with-badge';
|
||||
|
||||
export default {
|
||||
title: 'Components/ComponentLibrary/AvatarWithBadge',
|
||||
id: __filename,
|
||||
component: AvatarWithBadge,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: README,
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
badgePosition: {
|
||||
options: Object.values(BADGE_POSITIONS),
|
||||
control: 'select',
|
||||
},
|
||||
},
|
||||
args: {
|
||||
badgePosition: BADGE_POSITIONS.top,
|
||||
},
|
||||
};
|
||||
|
||||
export const DefaultStory = (args) => (
|
||||
<AvatarWithBadge
|
||||
badge={
|
||||
<AvatarNetwork
|
||||
size={SIZES.XS}
|
||||
networkName="Arbitrum One"
|
||||
networkImageUrl="./images/arbitrum.svg"
|
||||
/>
|
||||
}
|
||||
{...args}
|
||||
>
|
||||
<AvatarAccount
|
||||
address="0x5CfE73b6021E818B776b421B1c4Db2474086a7e1"
|
||||
size={SIZES.MD}
|
||||
type={TYPES.JAZZICON}
|
||||
/>
|
||||
</AvatarWithBadge>
|
||||
);
|
||||
DefaultStory.storyName = 'Default';
|
||||
|
||||
export const BadgePosition = () => (
|
||||
<Box display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.BASELINE} gap={1}>
|
||||
<AvatarWithBadge
|
||||
badgePosition={BADGE_POSITIONS.BOTTOM}
|
||||
badge={
|
||||
<AvatarNetwork
|
||||
size={SIZES.XS}
|
||||
networkName="Arbitrum One"
|
||||
networkImageUrl="./images/arbitrum.svg"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<AvatarAccount
|
||||
address="0x5CfE73b6021E818B776b421B1c4Db2474086a7e1"
|
||||
size={SIZES.MD}
|
||||
type={TYPES.JAZZICON}
|
||||
/>
|
||||
</AvatarWithBadge>
|
||||
|
||||
<AvatarWithBadge
|
||||
badgePosition={BADGE_POSITIONS.TOP}
|
||||
badge={
|
||||
<AvatarNetwork
|
||||
size={SIZES.XS}
|
||||
networkName="Arbitrum One"
|
||||
networkImageUrl="./images/arbitrum.svg"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<AvatarAccount
|
||||
address="0x5CfE73b6021E818B776b421B1c4Db2474086a7e1"
|
||||
size={SIZES.MD}
|
||||
type={TYPES.JAZZICON}
|
||||
/>
|
||||
</AvatarWithBadge>
|
||||
</Box>
|
||||
);
|
@ -0,0 +1,90 @@
|
||||
/* eslint-disable jest/require-top-level-describe */
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { AvatarNetwork } from '../avatar-network/avatar-network';
|
||||
import { COLORS } from '../../../helpers/constants/design-system';
|
||||
import { AvatarWithBadge } from './avatar-with-badge';
|
||||
import { BADGE_POSITIONS } from './avatar-with-badge.constants';
|
||||
|
||||
describe('AvatarWithBadge', () => {
|
||||
it('should render correctly', () => {
|
||||
const { getByTestId } = render(
|
||||
<AvatarWithBadge
|
||||
badgePosition={BADGE_POSITIONS.BOTTOM}
|
||||
data-testid="avatar-with-badge"
|
||||
badge={
|
||||
<AvatarNetwork
|
||||
networkName="Arbitrum One"
|
||||
networkImageUrl="./images/arbitrum.svg"
|
||||
data-testid="badge"
|
||||
/>
|
||||
}
|
||||
/>,
|
||||
);
|
||||
expect(getByTestId('avatar-with-badge')).toBeDefined();
|
||||
expect(getByTestId('badge')).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render badge network with bottom right position correctly', () => {
|
||||
const { container } = render(
|
||||
<AvatarWithBadge
|
||||
data-testid="avatar-with-badge"
|
||||
badgePosition={BADGE_POSITIONS.BOTTOM}
|
||||
badge={
|
||||
<AvatarNetwork
|
||||
networkName="Arbitrum One"
|
||||
networkImageUrl="./images/arbitrum.svg"
|
||||
data-testid="badge"
|
||||
/>
|
||||
}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(
|
||||
container.getElementsByClassName(
|
||||
'avatar-with-badge__badge-wrapper--position-bottom',
|
||||
),
|
||||
).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should render badge network with top right position correctly', () => {
|
||||
const { container } = render(
|
||||
<AvatarWithBadge
|
||||
data-testid="avatar-with-badge"
|
||||
badgePosition={BADGE_POSITIONS.TOP}
|
||||
badge={
|
||||
<AvatarNetwork
|
||||
networkName="Arbitrum One"
|
||||
networkImageUrl="./images/arbitrum.svg"
|
||||
data-testid="badge"
|
||||
/>
|
||||
}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(
|
||||
container.getElementsByClassName(
|
||||
'avatar-with-badge__badge-wrapper--position-top',
|
||||
),
|
||||
).toHaveLength(1);
|
||||
});
|
||||
it('should render badge network with badgeWrapperProps', () => {
|
||||
const container = (
|
||||
<AvatarWithBadge
|
||||
data-testid="avatar-with-badge"
|
||||
badgePosition={BADGE_POSITIONS.TOP}
|
||||
badgeWrapperProps={{ borderColor: COLORS.ERROR_DEFAULT }}
|
||||
badge={
|
||||
<AvatarNetwork
|
||||
networkName="Arbitrum One"
|
||||
networkImageUrl="./images/arbitrum.svg"
|
||||
data-testid="badge"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
expect(container.props.badgeWrapperProps.borderColor).toStrictEqual(
|
||||
'error-default',
|
||||
);
|
||||
});
|
||||
});
|
@ -0,0 +1 @@
|
||||
export { AvatarWithBadge } from './avatar-with-badge';
|
@ -2,6 +2,7 @@
|
||||
@import 'avatar-account/avatar-account';
|
||||
@import 'avatar-network/avatar-network';
|
||||
@import 'avatar-token/avatar-token';
|
||||
@import 'avatar-with-badge/avatar-with-badge';
|
||||
@import 'base-avatar/base-avatar';
|
||||
@import 'button-base/button-base';
|
||||
@import 'button-primary/button-primary';
|
||||
|
Loading…
Reference in New Issue
Block a user