diff --git a/ui/components/multichain/avatar-group/__snapshots__/avatar-group.test.tsx.snap b/ui/components/multichain/avatar-group/__snapshots__/avatar-group.test.tsx.snap
new file mode 100644
index 000000000000..3ef94f51374b
--- /dev/null
+++ b/ui/components/multichain/avatar-group/__snapshots__/avatar-group.test.tsx.snap
@@ -0,0 +1,80 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AvatarGroup should render AvatarGroup component 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/ui/components/multichain/avatar-group/avatar-group.stories.tsx b/ui/components/multichain/avatar-group/avatar-group.stories.tsx
new file mode 100644
index 000000000000..e83a85f2b652
--- /dev/null
+++ b/ui/components/multichain/avatar-group/avatar-group.stories.tsx
@@ -0,0 +1,57 @@
+import React from 'react';
+import { StoryFn, Meta } from '@storybook/react';
+import { AvatarGroup } from '.';
+
+export default {
+ title: 'Components/Multichain/AvatarGroup',
+ component: AvatarGroup,
+ argTypes: {
+ limit: {
+ control: 'number',
+ },
+ members: {
+ control: 'object',
+ },
+ },
+ args: {
+ members: [
+ { symbol: 'ETH', image: './images/eth_logo.png' },
+ { symbol: 'MATIC', image: './images/matic-token.png' },
+ { symbol: 'OP', image: './images/optimism.svg' },
+ { symbol: 'AVAX', image: './images/avax-token.png' },
+ ],
+ limit: 4,
+ },
+} as Meta;
+
+const Template = (args) => ;
+
+export const DefaultStory = Template.bind({});
+DefaultStory.storyName = 'Default';
+
+export const WithTag: StoryFn = (args) => (
+
+);
+WithTag.args = {
+ members: [
+ { symbol: 'ETH', image: './images/eth_logo.png' },
+ { symbol: 'MATIC', image: './images/matic-token.png' },
+ { symbol: 'OP', image: './images/optimism.svg' },
+ { symbol: 'AVAX', image: './images/avax-token.png' },
+ { symbol: 'PALM', image: './images/palm.svg' },
+ ],
+ limit: 2,
+};
+
+export const TokenWithOutSrc: StoryFn = (args) => (
+
+);
+TokenWithOutSrc.args = {
+ members: [
+ { symbol: 'ETH', image: '' },
+ { symbol: 'MATIC', image: '' },
+ { symbol: 'OP', image: '' },
+ { symbol: 'AVAX', image: '' },
+ ],
+ limit: 2,
+};
diff --git a/ui/components/multichain/avatar-group/avatar-group.test.tsx b/ui/components/multichain/avatar-group/avatar-group.test.tsx
new file mode 100644
index 000000000000..a9a891468165
--- /dev/null
+++ b/ui/components/multichain/avatar-group/avatar-group.test.tsx
@@ -0,0 +1,34 @@
+/* eslint-disable jest/require-top-level-describe */
+import { render, screen } from '@testing-library/react';
+import React from 'react';
+
+import { AvatarGroup } from './avatar-group';
+
+const members = [
+ { symbol: 'ETH', image: './images/eth_logo.png' },
+ { symbol: 'MATIC', image: './images/matic-token.png' },
+ { symbol: 'OP', image: './images/optimism.svg' },
+ { symbol: 'AVAX', image: './images/avax-token.png' },
+ { symbol: 'PALM', image: './images/palm.svg' },
+];
+
+describe('AvatarGroup', () => {
+ it('should render AvatarGroup component', () => {
+ const { getByTestId, container } = render(
+ ,
+ );
+ expect(getByTestId('avatar-group')).toBeDefined();
+ expect(container).toMatchSnapshot();
+ });
+
+ it('should render the tag +1 if members has a length greater than limit', () => {
+ render();
+
+ expect(screen.getByText('+1')).toBeDefined();
+ });
+
+ it('should not render the tag if members has a length less than or equal to limit', () => {
+ const { queryByText } = render();
+ expect(queryByText('+1')).not.toBeInTheDocument();
+ });
+});
diff --git a/ui/components/multichain/avatar-group/avatar-group.tsx b/ui/components/multichain/avatar-group/avatar-group.tsx
new file mode 100644
index 000000000000..fcfbe19c0395
--- /dev/null
+++ b/ui/components/multichain/avatar-group/avatar-group.tsx
@@ -0,0 +1,72 @@
+import * as React from 'react';
+import classnames from 'classnames';
+import {
+ Text,
+ Box,
+ AvatarToken,
+ AvatarTokenSize,
+} from '../../component-library';
+import {
+ AlignItems,
+ BorderColor,
+ BorderRadius,
+ Display,
+ TextColor,
+ TextVariant,
+} from '../../../helpers/constants/design-system';
+import { AvatarGroupProps } from './avatar-group.types';
+
+export const AvatarGroup: React.FC = ({
+ className = '',
+ limit = 4,
+ members = [],
+ size = AvatarTokenSize.Xs,
+ borderColor = BorderColor.transparent,
+}): JSX.Element => {
+ const membersCount = members.length;
+ const visibleMembers = members.slice(0, limit).reverse();
+ const showTag = membersCount > limit;
+ let marginLeftValue = '';
+ if (AvatarTokenSize.Xs) {
+ marginLeftValue = '-8px';
+ } else if (AvatarTokenSize.Sm) {
+ marginLeftValue = '-12px';
+ } else {
+ marginLeftValue = '-16px';
+ }
+ const tagValue = `+${(membersCount - limit).toLocaleString()}`;
+ return (
+
+
+ {visibleMembers.map((member, i) => (
+
+
+
+ ))}
+
+ {showTag ? (
+
+
+ {tagValue}
+
+
+ ) : null}
+
+ );
+};
diff --git a/ui/components/multichain/avatar-group/avatar-group.types.tsx b/ui/components/multichain/avatar-group/avatar-group.types.tsx
new file mode 100644
index 000000000000..b5673692de50
--- /dev/null
+++ b/ui/components/multichain/avatar-group/avatar-group.types.tsx
@@ -0,0 +1,21 @@
+import { BorderColor } from '../../../helpers/constants/design-system';
+import { AvatarTokenSize } from '../../component-library';
+import type { StyleUtilityProps } from '../../component-library/box';
+
+export interface AvatarGroupProps extends StyleUtilityProps {
+ /** * Additional class name for the AvatarGroup component */
+ className?: string;
+ /** * Limit to show only a certain number of tokens and extras in Text */
+ limit: number;
+ /** * List of Avatar Tokens */
+ members: {
+ /** * Image of Avatar Token */
+ image: string;
+ /** * Symbol of Avatar Token */
+ symbol?: string;
+ }[];
+ /** * Size of Avatar Tokens. For AvatarGroup we are considering AvatarTokenSize.Xs, AvatarTokenSize.Sm, AvatarTokenSize.Md */
+ size?: AvatarTokenSize;
+ /** * Border Color of Avatar Tokens */
+ borderColor?: BorderColor;
+}
diff --git a/ui/components/multichain/avatar-group/index.ts b/ui/components/multichain/avatar-group/index.ts
new file mode 100644
index 000000000000..59d3238f30af
--- /dev/null
+++ b/ui/components/multichain/avatar-group/index.ts
@@ -0,0 +1 @@
+export { AvatarGroup } from './avatar-group';
diff --git a/ui/components/multichain/index.js b/ui/components/multichain/index.js
index a2d8c5d7db17..2151c989addf 100644
--- a/ui/components/multichain/index.js
+++ b/ui/components/multichain/index.js
@@ -24,3 +24,4 @@ export { ImportTokensModal } from './import-tokens-modal';
export { SelectActionModal } from './select-action-modal';
export { SelectActionModalItem } from './select-action-modal-item';
export { AssetListConversionButton } from './asset-list-conversion-button';
+export { AvatarGroup } from './avatar-group';