Skip to content

Commit

Permalink
Merge pull request #26091 from thiagobrez/thiagobrez/selection-list-t…
Browse files Browse the repository at this point in the history
…ooltip

feat(selection-list): add tooltip
  • Loading branch information
aldo-expensify authored Sep 13, 2023
2 parents 1baf33a + 0b2d4b4 commit b7539df
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 33 deletions.
10 changes: 7 additions & 3 deletions src/components/SelectionList/BaseSelectionList.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,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';
Expand Down Expand Up @@ -242,16 +242,20 @@ 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 (
<CheckboxListItem
<UserListItem
item={item}
isFocused={isFocused}
onSelectRow={() => selectRow(item, index)}
onDismissError={onDismissError}
showTooltip={showTooltip}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,47 @@ 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';
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 UserListItem({item, isFocused = false, showTooltip, onSelectRow, onDismissError = () => {}}) {
const hasError = !_.isEmpty(item.errors);

const avatar = (
<Avatar
containerStyles={styles.pl5}
source={lodashGet(item, 'avatar.source', '')}
name={lodashGet(item, 'avatar.name', item.text)}
type={lodashGet(item, 'avatar.type', CONST.ICON_TYPE_AVATAR)}
/>
);

const text = (
<Text
style={[styles.optionDisplayName, isFocused ? styles.sidebarLinkActiveText : styles.sidebarLinkText, styles.sidebarLinkTextBold]}
numberOfLines={1}
>
{item.text}
</Text>
);

const alternateText = (
<Text
style={[isFocused ? styles.sidebarLinkActiveText : styles.sidebarLinkText, styles.optionAlternateText, styles.textLabelSupporting]}
numberOfLines={1}
>
{item.alternateText}
</Text>
);

return (
<OfflineWithFeedback
onClose={() => onDismissError(item)}
Expand Down Expand Up @@ -53,37 +82,28 @@ function CheckboxListItem({item, isFocused = false, onSelectRow, onDismissError
/>
)}
</View>
{Boolean(item.avatar) && (
<Avatar
containerStyles={styles.pl5}
source={lodashGet(item, 'avatar.source', '')}
name={lodashGet(item, 'avatar.name', item.text)}
type={lodashGet(item, 'avatar.type', CONST.ICON_TYPE_AVATAR)}
/>
)}
<View style={[styles.flex1, styles.flexColumn, styles.justifyContentCenter, styles.alignItemsStart, styles.pl3, styles.optionRow]}>
<Text
style={[styles.optionDisplayName, isFocused ? styles.sidebarLinkActiveText : styles.sidebarLinkText, styles.sidebarLinkTextBold]}
numberOfLines={1}
>
{item.text}
</Text>
{Boolean(item.alternateText) && (
<Text
style={[isFocused ? styles.sidebarLinkActiveText : styles.sidebarLinkText, styles.optionAlternateText, styles.textLabelSupporting]}
numberOfLines={1}
{Boolean(item.avatar) &&
(showTooltip ? (
<UserDetailsTooltip
accountID={item.accountID}
shiftHorizontal={styles.pl5.paddingLeft / 2}
>
{item.alternateText}
</Text>
)}
<View>{avatar}</View>
</UserDetailsTooltip>
) : (
avatar
))}
<View style={[styles.flex1, styles.flexColumn, styles.justifyContentCenter, styles.alignItemsStart, styles.pl3, styles.optionRow]}>
{showTooltip ? <Tooltip text={item.text}>{text}</Tooltip> : text}
{Boolean(item.alternateText) && (showTooltip ? <Tooltip text={item.alternateText}>{alternateText}</Tooltip> : alternateText)}
</View>
{Boolean(item.rightElement) && item.rightElement}
</PressableWithFeedback>
</OfflineWithFeedback>
);
}

CheckboxListItem.displayName = 'CheckboxListItem';
CheckboxListItem.propTypes = checkboxListItemPropTypes;
UserListItem.displayName = 'UserListItem';
UserListItem.propTypes = userListItemPropTypes;

export default CheckboxListItem;
export default UserListItem;
9 changes: 6 additions & 3 deletions src/components/SelectionList/selectionListPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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.isRequired,

/** Callback to fire when the item is pressed */
onSelectRow: PropTypes.func.isRequired,

Expand Down Expand Up @@ -90,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,
Expand Down Expand Up @@ -155,4 +158,4 @@ const propTypes = {
showConfirmButton: PropTypes.bool,
};

export {propTypes, radioListItemPropTypes, checkboxListItemPropTypes};
export {propTypes, radioListItemPropTypes, userListItemPropTypes};
1 change: 1 addition & 0 deletions src/pages/workspace/WorkspaceMembersPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ function WorkspaceMembersPage(props) {

result.push({
keyForList: 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),
Expand Down

0 comments on commit b7539df

Please sign in to comment.