From 8fc594bc53a4cb4315650a6e5802e1fa413cf601 Mon Sep 17 00:00:00 2001 From: Thiago Brezinski Date: Mon, 28 Aug 2023 15:49:39 +0100 Subject: [PATCH 1/4] feat(selection-list): add tooltip --- .../SelectionList/BaseSelectionList.js | 7 +- .../SelectionList/CheckboxListItem.js | 66 ++++++++++++------- .../SelectionList/selectionListPropTypes.js | 3 + src/pages/workspace/WorkspaceMembersPage.js | 1 + 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index 046b64e9e5c0..1842abfe732a 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -242,8 +242,11 @@ function BaseSelectionList({ }; const renderItem = ({item, index, section}) => { + const normalizedIndex = index + lodashGet(section, 'indexOffset', 0); const isDisabled = section.isDisabled; - const isFocused = !isDisabled && focusedIndex === index + lodashGet(section, 'indexOffset', 0); + const isFocused = !isDisabled && focusedIndex === normalizedIndex; + // We only create tooltips for the first 10 users or so since some reports have hundreds of users, causing performance to degrade. + const showTooltip = normalizedIndex < 10; if (canSelectMultiple) { return ( @@ -252,6 +255,7 @@ function BaseSelectionList({ isFocused={isFocused} onSelectRow={() => selectRow(item, index)} onDismissError={onDismissError} + showTooltip={showTooltip} /> ); } @@ -262,6 +266,7 @@ function BaseSelectionList({ isFocused={isFocused} isDisabled={isDisabled} onSelectRow={() => selectRow(item, index)} + showTooltip={showTooltip} /> ); }; diff --git a/src/components/SelectionList/CheckboxListItem.js b/src/components/SelectionList/CheckboxListItem.js index 256182a38e8b..694e03bae632 100644 --- a/src/components/SelectionList/CheckboxListItem.js +++ b/src/components/SelectionList/CheckboxListItem.js @@ -13,10 +13,39 @@ import * as StyleUtils from '../../styles/StyleUtils'; import Icon from '../Icon'; import * as Expensicons from '../Icon/Expensicons'; import themeColors from '../../styles/themes/default'; +import Tooltip from '../Tooltip'; +import UserDetailsTooltip from '../UserDetailsTooltip'; -function CheckboxListItem({item, isFocused = false, onSelectRow, onDismissError = () => {}}) { +function CheckboxListItem({item, isFocused = false, showTooltip = false, onSelectRow, onDismissError = () => {}}) { const hasError = !_.isEmpty(item.errors); + const avatar = ( + + ); + + const text = ( + + {item.text} + + ); + + const alternateText = ( + + {item.alternateText} + + ); + return ( onDismissError(item)} @@ -53,29 +82,20 @@ function CheckboxListItem({item, isFocused = false, onSelectRow, onDismissError /> )} - {Boolean(item.avatar) && ( - - )} - - - {item.text} - - {Boolean(item.alternateText) && ( - - {item.alternateText} - - )} + {avatar} + + ) : ( + avatar + ))} + + {showTooltip ? {text} : text} + {Boolean(item.alternateText) && (showTooltip ? {alternateText} : alternateText)} {Boolean(item.rightElement) && item.rightElement} diff --git a/src/components/SelectionList/selectionListPropTypes.js b/src/components/SelectionList/selectionListPropTypes.js index 9adf42833ebc..c398050a6eae 100644 --- a/src/components/SelectionList/selectionListPropTypes.js +++ b/src/components/SelectionList/selectionListPropTypes.js @@ -46,6 +46,9 @@ const checkboxListItemPropTypes = { /** Whether this item is focused (for arrow key controls) */ isFocused: PropTypes.bool, + /** Whether this item should show Tooltip */ + showTooltip: PropTypes.bool, + /** Callback to fire when the item is pressed */ onSelectRow: PropTypes.func.isRequired, diff --git a/src/pages/workspace/WorkspaceMembersPage.js b/src/pages/workspace/WorkspaceMembersPage.js index d598f90e4326..734714477e47 100644 --- a/src/pages/workspace/WorkspaceMembersPage.js +++ b/src/pages/workspace/WorkspaceMembersPage.js @@ -307,6 +307,7 @@ function WorkspaceMembersPage(props) { result.push({ keyForList: accountID, + accountID, isSelected: _.contains(selectedEmployees, Number(accountID)), isDisabled: accountID === props.session.accountID || details.login === props.policy.owner || policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, text: props.formatPhoneNumber(details.displayName), From 883fb01b0aa99995914fa1528e9e64ec09419b6a Mon Sep 17 00:00:00 2001 From: Thiago Brezinski Date: Mon, 28 Aug 2023 16:48:16 +0100 Subject: [PATCH 2/4] fix(selection-list): accountID to number --- src/pages/workspace/WorkspaceMembersPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceMembersPage.js b/src/pages/workspace/WorkspaceMembersPage.js index 734714477e47..22c0a2aca2c4 100644 --- a/src/pages/workspace/WorkspaceMembersPage.js +++ b/src/pages/workspace/WorkspaceMembersPage.js @@ -307,7 +307,7 @@ function WorkspaceMembersPage(props) { result.push({ keyForList: accountID, - accountID, + accountID: Number(accountID), isSelected: _.contains(selectedEmployees, Number(accountID)), isDisabled: accountID === props.session.accountID || details.login === props.policy.owner || policyMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, text: props.formatPhoneNumber(details.displayName), From 5c67b87bafef168a37be90a81dcf1acad0e5f325 Mon Sep 17 00:00:00 2001 From: Thiago Brezinski Date: Wed, 30 Aug 2023 12:26:56 +0100 Subject: [PATCH 3/4] refactor(selection-list): rename CheckboxListItem to UserListItem --- src/components/SelectionList/BaseSelectionList.js | 4 ++-- .../{CheckboxListItem.js => UserListItem.js} | 10 +++++----- src/components/SelectionList/selectionListPropTypes.js | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) rename src/components/SelectionList/{CheckboxListItem.js => UserListItem.js} (92%) diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index 1842abfe732a..81d486b38b7e 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -11,7 +11,7 @@ import CONST from '../../CONST'; import variables from '../../styles/variables'; import {propTypes as selectionListPropTypes} from './selectionListPropTypes'; import RadioListItem from './RadioListItem'; -import CheckboxListItem from './CheckboxListItem'; +import UserListItem from './UserListItem'; import useKeyboardShortcut from '../../hooks/useKeyboardShortcut'; import SafeAreaConsumer from '../SafeAreaConsumer'; import withKeyboardState, {keyboardStatePropTypes} from '../withKeyboardState'; @@ -250,7 +250,7 @@ function BaseSelectionList({ if (canSelectMultiple) { return ( - selectRow(item, index)} diff --git a/src/components/SelectionList/CheckboxListItem.js b/src/components/SelectionList/UserListItem.js similarity index 92% rename from src/components/SelectionList/CheckboxListItem.js rename to src/components/SelectionList/UserListItem.js index 694e03bae632..0b3c05d6b752 100644 --- a/src/components/SelectionList/CheckboxListItem.js +++ b/src/components/SelectionList/UserListItem.js @@ -5,7 +5,7 @@ import lodashGet from 'lodash/get'; import PressableWithFeedback from '../Pressable/PressableWithFeedback'; import styles from '../../styles/styles'; import Text from '../Text'; -import {checkboxListItemPropTypes} from './selectionListPropTypes'; +import {userListItemPropTypes} from './selectionListPropTypes'; import Avatar from '../Avatar'; import OfflineWithFeedback from '../OfflineWithFeedback'; import CONST from '../../CONST'; @@ -16,7 +16,7 @@ import themeColors from '../../styles/themes/default'; import Tooltip from '../Tooltip'; import UserDetailsTooltip from '../UserDetailsTooltip'; -function CheckboxListItem({item, isFocused = false, showTooltip = false, onSelectRow, onDismissError = () => {}}) { +function UserListItem({item, isFocused = false, showTooltip = false, onSelectRow, onDismissError = () => {}}) { const hasError = !_.isEmpty(item.errors); const avatar = ( @@ -103,7 +103,7 @@ function CheckboxListItem({item, isFocused = false, showTooltip = false, onSelec ); } -CheckboxListItem.displayName = 'CheckboxListItem'; -CheckboxListItem.propTypes = checkboxListItemPropTypes; +UserListItem.displayName = 'UserListItem'; +UserListItem.propTypes = userListItemPropTypes; -export default CheckboxListItem; +export default UserListItem; diff --git a/src/components/SelectionList/selectionListPropTypes.js b/src/components/SelectionList/selectionListPropTypes.js index c398050a6eae..9946e3bfcc35 100644 --- a/src/components/SelectionList/selectionListPropTypes.js +++ b/src/components/SelectionList/selectionListPropTypes.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import _ from 'underscore'; import CONST from '../../CONST'; -const checkboxListItemPropTypes = { +const userListItemPropTypes = { /** The section list item */ item: PropTypes.shape({ /** Text to display */ @@ -93,7 +93,7 @@ const propTypes = { indexOffset: PropTypes.number, /** Array of options */ - data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape(checkboxListItemPropTypes.item), PropTypes.shape(radioListItemPropTypes.item)])), + data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape(userListItemPropTypes.item), PropTypes.shape(radioListItemPropTypes.item)])), /** Whether this section items disabled for selection */ isDisabled: PropTypes.bool, @@ -161,4 +161,4 @@ const propTypes = { showConfirmButton: PropTypes.bool, }; -export {propTypes, radioListItemPropTypes, checkboxListItemPropTypes}; +export {propTypes, radioListItemPropTypes, userListItemPropTypes}; From 0b2d4b473c175edb2739f64dcc9555c1a589b938 Mon Sep 17 00:00:00 2001 From: Thiago Brezinski Date: Wed, 30 Aug 2023 19:36:29 +0100 Subject: [PATCH 4/4] fix(selection-list): make showTooltip required --- src/components/SelectionList/BaseSelectionList.js | 1 - src/components/SelectionList/UserListItem.js | 2 +- src/components/SelectionList/selectionListPropTypes.js | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index 81d486b38b7e..d5cd96b9b029 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -266,7 +266,6 @@ function BaseSelectionList({ isFocused={isFocused} isDisabled={isDisabled} onSelectRow={() => selectRow(item, index)} - showTooltip={showTooltip} /> ); }; diff --git a/src/components/SelectionList/UserListItem.js b/src/components/SelectionList/UserListItem.js index 0b3c05d6b752..dd90fc750510 100644 --- a/src/components/SelectionList/UserListItem.js +++ b/src/components/SelectionList/UserListItem.js @@ -16,7 +16,7 @@ import themeColors from '../../styles/themes/default'; import Tooltip from '../Tooltip'; import UserDetailsTooltip from '../UserDetailsTooltip'; -function UserListItem({item, isFocused = false, showTooltip = false, onSelectRow, onDismissError = () => {}}) { +function UserListItem({item, isFocused = false, showTooltip, onSelectRow, onDismissError = () => {}}) { const hasError = !_.isEmpty(item.errors); const avatar = ( diff --git a/src/components/SelectionList/selectionListPropTypes.js b/src/components/SelectionList/selectionListPropTypes.js index 9946e3bfcc35..501de8314934 100644 --- a/src/components/SelectionList/selectionListPropTypes.js +++ b/src/components/SelectionList/selectionListPropTypes.js @@ -47,7 +47,7 @@ const userListItemPropTypes = { isFocused: PropTypes.bool, /** Whether this item should show Tooltip */ - showTooltip: PropTypes.bool, + showTooltip: PropTypes.bool.isRequired, /** Callback to fire when the item is pressed */ onSelectRow: PropTypes.func.isRequired,