diff --git a/src/CONST.js b/src/CONST.js
index 86e819127c3b..7dbcb9dad56d 100755
--- a/src/CONST.js
+++ b/src/CONST.js
@@ -1109,6 +1109,10 @@ const CONST = {
HEADER: 'header',
MENTION_ICON: 'mention-icon',
},
+ AVATAR_ROW_SIZE: {
+ DEFAULT: 4,
+ LARGE_SCREEN: 8,
+ },
OPTION_MODE: {
COMPACT: 'compact',
DEFAULT: 'default',
diff --git a/src/components/MultipleAvatars.js b/src/components/MultipleAvatars.js
index c62fc387b815..2ac9724ccd14 100644
--- a/src/components/MultipleAvatars.js
+++ b/src/components/MultipleAvatars.js
@@ -1,4 +1,4 @@
-import React, {memo} from 'react';
+import React, {memo, useEffect, useState} from 'react';
import PropTypes from 'prop-types';
import {View} from 'react-native';
import _ from 'underscore';
@@ -32,6 +32,9 @@ const propTypes = {
/** Prop to identify if we should load avatars vertically instead of diagonally */
shouldStackHorizontally: PropTypes.bool,
+ /** Prop to identify if we should display avatars in rows */
+ shouldDisplayAvatarsInRows: PropTypes.bool,
+
/** Whether the avatars are hovered */
isHovered: PropTypes.bool,
@@ -49,6 +52,9 @@ const propTypes = {
/** Whether avatars are displayed with the highlighted background color instead of the app background color. This is primarily the case for IOU previews. */
shouldUseCardBackground: PropTypes.bool,
+
+ /** Prop to limit the amount of avatars displayed horizontally */
+ maxAvatarsInRow: PropTypes.number,
};
const defaultProps = {
@@ -57,20 +63,48 @@ const defaultProps = {
secondAvatarStyle: [StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)],
fallbackIcon: undefined,
shouldStackHorizontally: false,
+ shouldDisplayAvatarsInRows: false,
isHovered: false,
isPressed: false,
isFocusMode: false,
isInReportAction: false,
shouldShowTooltip: true,
shouldUseCardBackground: false,
+ maxAvatarsInRow: CONST.AVATAR_ROW_SIZE.DEFAULT,
};
function MultipleAvatars(props) {
+ const [avatarRows, setAvatarRows] = useState([props.icons]);
let avatarContainerStyles = props.size === CONST.AVATAR_SIZE.SMALL ? [styles.emptyAvatarSmall, styles.emptyAvatarMarginSmall] : [styles.emptyAvatar, styles.emptyAvatarMargin];
const singleAvatarStyles = props.size === CONST.AVATAR_SIZE.SMALL ? styles.singleAvatarSmall : styles.singleAvatar;
const secondAvatarStyles = [props.size === CONST.AVATAR_SIZE.SMALL ? styles.secondAvatarSmall : styles.secondAvatar, ...props.secondAvatarStyle];
const tooltipTexts = props.shouldShowTooltip ? _.pluck(props.icons, 'name') : [''];
+ const calculateAvatarRows = () => {
+ // If we're not displaying avatars in rows or the number of icons is less than or equal to the max avatars in a row, return a single row
+ if (!props.shouldDisplayAvatarsInRows || props.icons.length <= props.maxAvatarsInRow) {
+ setAvatarRows([props.icons]);
+ return;
+ }
+
+ // Calculate the size of each row
+ const rowSize = Math.min(Math.ceil(props.icons.length / 2), props.maxAvatarsInRow);
+
+ // Slice the icons array into two rows
+ const firstRow = props.icons.slice(rowSize);
+ const secondRow = props.icons.slice(0, rowSize);
+
+ // Update the state with the two rows as an array
+ setAvatarRows([firstRow, secondRow]);
+ };
+
+ useEffect(() => {
+ calculateAvatarRows();
+
+ // The only dependencies of the effect are based on props, so we can safely disable the exhaustive-deps rule
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [props.icons, props.maxAvatarsInRow, props.shouldDisplayAvatarsInRows]);
+
if (!props.icons.length) {
return null;
}
@@ -118,114 +152,126 @@ function MultipleAvatars(props) {
}
return (
-
+ <>
{props.shouldStackHorizontally ? (
- <>
- {_.map([...props.icons].splice(0, 4), (icon, index) => (
-
-
-
-
-
- ))}
- {props.icons.length > 4 && (
-
- (
+
+ {_.map([...avatars].splice(0, props.maxAvatarsInRow), (icon, index) => (
+
- {`+${props.icons.length - 4}`}
-
-
-
- )}
- >
- ) : (
-
-
- {/* View is necessary for tooltip to show for multiple avatars in LHN */}
-
-
-
-
-
- {props.icons.length === 2 ? (
-
-
- ) : (
-
-
- props.maxAvatarsInRow && (
+
+
+
- {`+${props.icons.length - 1}`}
-
+ {`+${avatars.length - props.maxAvatarsInRow}`}
+
)}
+ ))
+ ) : (
+
+
+
+ {/* View is necessary for tooltip to show for multiple avatars in LHN */}
+
+
+
+
+
+ {props.icons.length === 2 ? (
+
+
+
+
+
+ ) : (
+
+
+
+ {`+${props.icons.length - 1}`}
+
+
+
+ )}
+
+
)}
-
+ >
);
}
diff --git a/src/pages/home/report/ReportActionItemCreated.js b/src/pages/home/report/ReportActionItemCreated.js
index 3c68a366bd0a..095b6ac350c3 100644
--- a/src/pages/home/report/ReportActionItemCreated.js
+++ b/src/pages/home/report/ReportActionItemCreated.js
@@ -4,7 +4,6 @@ import lodashGet from 'lodash/get';
import {withOnyx} from 'react-native-onyx';
import PropTypes from 'prop-types';
import ONYXKEYS from '../../../ONYXKEYS';
-import RoomHeaderAvatars from '../../../components/RoomHeaderAvatars';
import ReportWelcomeText from '../../../components/ReportWelcomeText';
import participantPropTypes from '../../../components/participantPropTypes';
import * as ReportUtils from '../../../libs/ReportUtils';
@@ -18,6 +17,7 @@ import withWindowDimensions, {windowDimensionsPropTypes} from '../../../componen
import compose from '../../../libs/compose';
import withLocalize from '../../../components/withLocalize';
import PressableWithoutFeedback from '../../../components/Pressable/PressableWithoutFeedback';
+import MultipleAvatars from '../../../components/MultipleAvatars';
import CONST from '../../../CONST';
const propTypes = {
@@ -77,7 +77,13 @@ function ReportActionItemCreated(props) {
accessibilityLabel={props.translate('common.details')}
accessibilityRole={CONST.ACCESSIBILITY_ROLE.BUTTON}
>
-
+
diff --git a/src/pages/workspace/WorkspaceInviteMessagePage.js b/src/pages/workspace/WorkspaceInviteMessagePage.js
index fe422dea20aa..12caf96f283a 100644
--- a/src/pages/workspace/WorkspaceInviteMessagePage.js
+++ b/src/pages/workspace/WorkspaceInviteMessagePage.js
@@ -196,6 +196,7 @@ class WorkspaceInviteMessagePage extends React.Component {
size={CONST.AVATAR_SIZE.LARGE}
icons={OptionsListUtils.getAvatarsForAccountIDs(_.values(this.props.invitedEmailsToAccountIDsDraft), this.props.personalDetails)}
shouldStackHorizontally
+ shouldDisplayAvatarsInRows
secondAvatarStyle={[styles.secondAvatarInline]}
/>