From 7c8e084fed8282c556276905a0986a13a01b0957 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Tue, 29 Jul 2025 14:52:41 +0530 Subject: [PATCH 01/17] fix: Update "copy to clipboard" pattern to be more discoverable. Signed-off-by: krishna2323 --- src/components/CopyTextToClipboard.tsx | 19 ++++++-- src/components/MenuItem.tsx | 14 +++++- .../Pressable/PressableWithDelayToggle.tsx | 47 ++++++++++++++----- 3 files changed, 62 insertions(+), 18 deletions(-) diff --git a/src/components/CopyTextToClipboard.tsx b/src/components/CopyTextToClipboard.tsx index 3c99a85fd0e7..24e40e033a78 100644 --- a/src/components/CopyTextToClipboard.tsx +++ b/src/components/CopyTextToClipboard.tsx @@ -4,10 +4,11 @@ import useLocalize from '@hooks/useLocalize'; import Clipboard from '@libs/Clipboard'; import * as Expensicons from './Icon/Expensicons'; import PressableWithDelayToggle from './Pressable/PressableWithDelayToggle'; +import type {PressableWithDelayToggleProps} from './Pressable/PressableWithDelayToggle'; type CopyTextToClipboardProps = { /** The text to display and copy to the clipboard */ - text: string; + text?: string; /** Styles to apply to the text */ textStyles?: StyleProp; @@ -15,14 +16,22 @@ type CopyTextToClipboardProps = { urlToCopy?: string; accessibilityRole?: AccessibilityRole; -}; -function CopyTextToClipboard({text, textStyles, urlToCopy, accessibilityRole}: CopyTextToClipboardProps) { + shouldShowHoveredState?: boolean; + + /** Icon width */ + iconWidth?: number; + + /** Icon height */ + iconHeight?: number; +} & Pick; + +function CopyTextToClipboard({text, textStyles, urlToCopy, accessibilityRole, ...rest}: CopyTextToClipboardProps) { const {translate} = useLocalize(); const copyToClipboard = useCallback(() => { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- nullish coalescing doesn't achieve the same result in this case - Clipboard.setString(urlToCopy || text); + Clipboard.setString(urlToCopy || text || ''); }, [text, urlToCopy]); return ( @@ -36,6 +45,8 @@ function CopyTextToClipboard({text, textStyles, urlToCopy, accessibilityRole}: C accessible accessibilityLabel={translate('reportActionContextMenu.copyToClipboard')} accessibilityRole={accessibilityRole} + // eslint-disable-next-line react/jsx-props-no-spreading + {...rest} /> ); } diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 2aa8061b9757..d3b025fece9f 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -10,7 +10,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import ControlSelection from '@libs/ControlSelection'; import convertToLTR from '@libs/convertToLTR'; -import {canUseTouchScreen} from '@libs/DeviceCapabilities'; +import {canUseTouchScreen, hasHoverSupport} from '@libs/DeviceCapabilities'; import {containsCustomEmoji, containsOnlyCustomEmoji} from '@libs/EmojiUtils'; import getButtonState from '@libs/getButtonState'; import mergeRefs from '@libs/mergeRefs'; @@ -26,6 +26,7 @@ import type {TooltipAnchorAlignment} from '@src/types/utils/AnchorAlignment'; import type IconAsset from '@src/types/utils/IconAsset'; import Avatar from './Avatar'; import Badge from './Badge'; +import CopyTextToClipboard from './CopyTextToClipboard'; import DisplayNames from './DisplayNames'; import type {DisplayNameWithTooltip} from './DisplayNames/types'; import FormHelpMessage from './FormHelpMessage'; @@ -968,6 +969,17 @@ function MenuItem( additionalStyles={styles.alignSelfCenter} /> )} + {isHovered && !!copyValue && hasHoverSupport() && ( + + + + )} {!!errorText && ( diff --git a/src/components/Pressable/PressableWithDelayToggle.tsx b/src/components/Pressable/PressableWithDelayToggle.tsx index 68007c1c03ad..18ab3ec9fafe 100644 --- a/src/components/Pressable/PressableWithDelayToggle.tsx +++ b/src/components/Pressable/PressableWithDelayToggle.tsx @@ -17,7 +17,7 @@ import PressableWithoutFeedback from './PressableWithoutFeedback'; type PressableWithDelayToggleProps = PressableProps & { /** The text to display */ - text: string; + text?: string; /** The text to display once the pressable is pressed */ textChecked?: string; @@ -50,6 +50,15 @@ type PressableWithDelayToggleProps = PressableProps & { */ inline?: boolean; accessibilityRole?: string; + + /** For overriding hovered value from the PressableWithoutFeedback container and getting the BG based on that */ + shouldShowHoveredState?: boolean; + + /** Icon width */ + iconWidth?: number; + + /** Icon height */ + iconHeight?: number; }; function PressableWithDelayToggle( @@ -66,6 +75,9 @@ function PressableWithDelayToggle( iconStyles, icon, accessibilityRole, + shouldShowHoveredState, + iconWidth = variables.iconSizeSmall, + iconHeight = variables.iconSizeSmall, }: PressableWithDelayToggleProps, ref: PressableRef, ) { @@ -86,15 +98,16 @@ function PressableWithDelayToggle( // of a Pressable const PressableView = inline ? Text : PressableWithoutFeedback; const tooltipTexts = !isActive ? tooltipTextChecked : tooltipText; - const labelText = ( - - {!isActive && textChecked ? textChecked : text} -   - - ); + const labelText = + !text && !textChecked ? null : ( + + {!isActive && textChecked ? textChecked : text} +   + + ); return ( [ + styles.flexRow, + pressableStyle, + !isActive && styles.cursorDefault, + styles.reportActionContextMenuMiniButton, + StyleUtils.getButtonBackgroundColorStyle(getButtonState(!!shouldShowHoveredState || hovered, shouldShowHoveredState ? hovered : pressed, !isActive), true), + ]} > {({hovered, pressed}) => ( <> @@ -126,8 +145,8 @@ function PressableWithDelayToggle( src={!isActive ? iconChecked : icon} fill={StyleUtils.getIconFillColor(getButtonState(hovered, pressed, !isActive))} additionalStyles={iconStyles} - width={variables.iconSizeSmall} - height={variables.iconSizeSmall} + width={iconWidth} + height={iconHeight} inline={inline} /> )} @@ -143,3 +162,5 @@ function PressableWithDelayToggle( PressableWithDelayToggle.displayName = 'PressableWithDelayToggle'; export default forwardRef(PressableWithDelayToggle); + +export type {PressableWithDelayToggleProps}; From 4ad7ec644be0edaeb6882d884b3dbfa5cb25cc9b Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Wed, 30 Jul 2025 03:50:27 +0530 Subject: [PATCH 02/17] minor update. Signed-off-by: krishna2323 --- src/components/CopyTextToClipboard.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/components/CopyTextToClipboard.tsx b/src/components/CopyTextToClipboard.tsx index 24e40e033a78..ca4df4668ff5 100644 --- a/src/components/CopyTextToClipboard.tsx +++ b/src/components/CopyTextToClipboard.tsx @@ -18,12 +18,6 @@ type CopyTextToClipboardProps = { accessibilityRole?: AccessibilityRole; shouldShowHoveredState?: boolean; - - /** Icon width */ - iconWidth?: number; - - /** Icon height */ - iconHeight?: number; } & Pick; function CopyTextToClipboard({text, textStyles, urlToCopy, accessibilityRole, ...rest}: CopyTextToClipboardProps) { From 4e9da43fb467f30f561836dd90acca17396df865 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Wed, 30 Jul 2025 17:39:23 +0530 Subject: [PATCH 03/17] update as per suggestions. Signed-off-by: krishna2323 --- src/components/CopyTextToClipboard.tsx | 12 ++++++++---- src/components/MenuItem.tsx | 8 ++++---- .../Pressable/PressableWithDelayToggle.tsx | 16 ++++++++-------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/components/CopyTextToClipboard.tsx b/src/components/CopyTextToClipboard.tsx index ca4df4668ff5..a869c07674d0 100644 --- a/src/components/CopyTextToClipboard.tsx +++ b/src/components/CopyTextToClipboard.tsx @@ -17,10 +17,11 @@ type CopyTextToClipboardProps = { accessibilityRole?: AccessibilityRole; - shouldShowHoveredState?: boolean; + /** For using the hovered style by default, e.g. if we always need the hovered bg */ + shouldUseHoveredStyle?: boolean; } & Pick; -function CopyTextToClipboard({text, textStyles, urlToCopy, accessibilityRole, ...rest}: CopyTextToClipboardProps) { +function CopyTextToClipboard({text, textStyles, urlToCopy, accessibilityRole, iconHeight, iconStyles, iconWidth, shouldUseHoveredStyle, styles}: CopyTextToClipboardProps) { const {translate} = useLocalize(); const copyToClipboard = useCallback(() => { @@ -39,8 +40,11 @@ function CopyTextToClipboard({text, textStyles, urlToCopy, accessibilityRole, .. accessible accessibilityLabel={translate('reportActionContextMenu.copyToClipboard')} accessibilityRole={accessibilityRole} - // eslint-disable-next-line react/jsx-props-no-spreading - {...rest} + shouldUseHoveredStyle={shouldUseHoveredStyle} + iconWidth={iconWidth} + iconHeight={iconHeight} + iconStyles={iconStyles} + styles={styles} /> ); } diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index d3b025fece9f..71bef881c441 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -969,14 +969,14 @@ function MenuItem( additionalStyles={styles.alignSelfCenter} /> )} - {isHovered && !!copyValue && hasHoverSupport() && ( - + {hasHoverSupport() && isHovered && !!copyValue && ( + )} diff --git a/src/components/Pressable/PressableWithDelayToggle.tsx b/src/components/Pressable/PressableWithDelayToggle.tsx index 18ab3ec9fafe..e077563650eb 100644 --- a/src/components/Pressable/PressableWithDelayToggle.tsx +++ b/src/components/Pressable/PressableWithDelayToggle.tsx @@ -51,13 +51,13 @@ type PressableWithDelayToggleProps = PressableProps & { inline?: boolean; accessibilityRole?: string; - /** For overriding hovered value from the PressableWithoutFeedback container and getting the BG based on that */ - shouldShowHoveredState?: boolean; + /** For using the hovered style by default, e.g. if we always need the hovered bg */ + shouldUseHoveredStyle?: boolean; - /** Icon width */ + /** Copy icon width */ iconWidth?: number; - /** Icon height */ + /** Copy icon height */ iconHeight?: number; }; @@ -75,7 +75,7 @@ function PressableWithDelayToggle( iconStyles, icon, accessibilityRole, - shouldShowHoveredState, + shouldUseHoveredStyle, iconWidth = variables.iconSizeSmall, iconHeight = variables.iconSizeSmall, }: PressableWithDelayToggleProps, @@ -99,7 +99,7 @@ function PressableWithDelayToggle( const PressableView = inline ? Text : PressableWithoutFeedback; const tooltipTexts = !isActive ? tooltipTextChecked : tooltipText; const labelText = - !text && !textChecked ? null : ( + text && textChecked ? ( - ); + ) : null; return ( {({hovered, pressed}) => ( From 7522cfe75ecbbd7b37222eff94c7a370af18a0f6 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Thu, 31 Jul 2025 13:26:46 +0530 Subject: [PATCH 04/17] always use hovered bg color. Signed-off-by: krishna2323 --- src/components/CopyTextToClipboard.tsx | 23 +++++++++++++------ src/components/MenuItem.tsx | 4 +++- .../Pressable/PressableWithDelayToggle.tsx | 22 ++++++++++++++---- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/components/CopyTextToClipboard.tsx b/src/components/CopyTextToClipboard.tsx index a869c07674d0..249ad42b7e7f 100644 --- a/src/components/CopyTextToClipboard.tsx +++ b/src/components/CopyTextToClipboard.tsx @@ -16,12 +16,20 @@ type CopyTextToClipboardProps = { urlToCopy?: string; accessibilityRole?: AccessibilityRole; - - /** For using the hovered style by default, e.g. if we always need the hovered bg */ - shouldUseHoveredStyle?: boolean; -} & Pick; - -function CopyTextToClipboard({text, textStyles, urlToCopy, accessibilityRole, iconHeight, iconStyles, iconWidth, shouldUseHoveredStyle, styles}: CopyTextToClipboardProps) { +} & Pick; + +function CopyTextToClipboard({ + text, + textStyles, + urlToCopy, + accessibilityRole, + iconHeight, + iconStyles, + iconWidth, + shouldIconAlwaysUseHoveredStyle, + shouldIconUseBackgroundColor, + styles, +}: CopyTextToClipboardProps) { const {translate} = useLocalize(); const copyToClipboard = useCallback(() => { @@ -40,11 +48,12 @@ function CopyTextToClipboard({text, textStyles, urlToCopy, accessibilityRole, ic accessible accessibilityLabel={translate('reportActionContextMenu.copyToClipboard')} accessibilityRole={accessibilityRole} - shouldUseHoveredStyle={shouldUseHoveredStyle} + shouldIconAlwaysUseHoveredStyle={shouldIconAlwaysUseHoveredStyle} iconWidth={iconWidth} iconHeight={iconHeight} iconStyles={iconStyles} styles={styles} + shouldIconUseBackgroundColor={shouldIconUseBackgroundColor} /> ); } diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 71bef881c441..2a377cdc20f0 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -973,10 +973,12 @@ function MenuItem( )} diff --git a/src/components/Pressable/PressableWithDelayToggle.tsx b/src/components/Pressable/PressableWithDelayToggle.tsx index e077563650eb..30d3864bcee1 100644 --- a/src/components/Pressable/PressableWithDelayToggle.tsx +++ b/src/components/Pressable/PressableWithDelayToggle.tsx @@ -51,8 +51,11 @@ type PressableWithDelayToggleProps = PressableProps & { inline?: boolean; accessibilityRole?: string; + /** For using the background color, e.g. if we need bg for the icon */ + shouldIconUseBackgroundColor?: boolean; + /** For using the hovered style by default, e.g. if we always need the hovered bg */ - shouldUseHoveredStyle?: boolean; + shouldIconAlwaysUseHoveredStyle?: boolean; /** Copy icon width */ iconWidth?: number; @@ -75,9 +78,10 @@ function PressableWithDelayToggle( iconStyles, icon, accessibilityRole, - shouldUseHoveredStyle, + shouldIconAlwaysUseHoveredStyle, iconWidth = variables.iconSizeSmall, iconHeight = variables.iconSizeSmall, + shouldIconUseBackgroundColor = false, }: PressableWithDelayToggleProps, ref: PressableRef, ) { @@ -99,7 +103,8 @@ function PressableWithDelayToggle( const PressableView = inline ? Text : PressableWithoutFeedback; const tooltipTexts = !isActive ? tooltipTextChecked : tooltipText; const labelText = - text && textChecked ? ( + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null + text || textChecked ? ( {({hovered, pressed}) => ( From 65aaf211b7c6eb45d9215e80316ef432f4fbfa5c Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Sun, 3 Aug 2025 17:48:28 +0530 Subject: [PATCH 05/17] enable copy to clipboard icon for every readonly menu item. Signed-off-by: krishna2323 --- src/components/MenuItem.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 2a377cdc20f0..412107a2aba6 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -380,6 +380,9 @@ type MenuItemBaseProps = { /** The value to copy on secondary interaction */ copyValue?: string; + /** Should disable copy to clipboard action */ + disableCopyToClipboard?: boolean; + /** Plaid image for the bank */ plaidUrl?: string; }; @@ -501,8 +504,9 @@ function MenuItem( shouldBreakWord = false, pressableTestID, shouldTeleportPortalToModalLayer, - copyValue, plaidUrl, + copyValue = title, + disableCopyToClipboard = false, }: MenuItemProps, ref: PressableRef, ) { @@ -969,7 +973,7 @@ function MenuItem( additionalStyles={styles.alignSelfCenter} /> )} - {hasHoverSupport() && isHovered && !!copyValue && ( + {!disableCopyToClipboard && hasHoverSupport() && !interactive && isHovered && !!copyValue && ( Date: Thu, 7 Aug 2025 00:43:26 +0530 Subject: [PATCH 06/17] update disableCopyToClipboard prop name to copiable. Signed-off-by: krishna2323 --- src/components/AutoUpdateTime.tsx | 1 + src/components/MenuItem.tsx | 6 +++--- src/pages/KeyboardShortcutsPage.tsx | 1 + src/pages/ProfilePage.tsx | 3 +++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/AutoUpdateTime.tsx b/src/components/AutoUpdateTime.tsx index fca87a17aa68..b9ac1b78dbcd 100644 --- a/src/components/AutoUpdateTime.tsx +++ b/src/components/AutoUpdateTime.tsx @@ -53,6 +53,7 @@ function AutoUpdateTime({timezone}: AutoUpdateTimeProps) { title={`${DateUtils.formatToLocalTime(currentUserLocalTime)} ${timezoneName}`} description={translate('detailsPage.localTime')} interactive={false} + copiable /> ); diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 412107a2aba6..0a2f7f926a5c 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -381,7 +381,7 @@ type MenuItemBaseProps = { copyValue?: string; /** Should disable copy to clipboard action */ - disableCopyToClipboard?: boolean; + copiable?: boolean; /** Plaid image for the bank */ plaidUrl?: string; @@ -506,7 +506,7 @@ function MenuItem( shouldTeleportPortalToModalLayer, plaidUrl, copyValue = title, - disableCopyToClipboard = false, + copiable = false, }: MenuItemProps, ref: PressableRef, ) { @@ -973,7 +973,7 @@ function MenuItem( additionalStyles={styles.alignSelfCenter} /> )} - {!disableCopyToClipboard && hasHoverSupport() && !interactive && isHovered && !!copyValue && ( + {copiable && hasHoverSupport() && !interactive && isHovered && !!copyValue && ( ); diff --git a/src/pages/ProfilePage.tsx b/src/pages/ProfilePage.tsx index d920cb8bb8a0..1905da6397a6 100755 --- a/src/pages/ProfilePage.tsx +++ b/src/pages/ProfilePage.tsx @@ -218,6 +218,7 @@ function ProfilePage({route}: ProfilePageProps) { title={statusContent} description={translate('statusPage.status')} interactive={false} + copiable /> )} @@ -231,6 +232,7 @@ function ProfilePage({route}: ProfilePageProps) { copyValue={isSMSLogin ? formatPhoneNumber(phoneNumber ?? '') : login} description={translate(isSMSLogin ? 'common.phoneNumber' : 'common.email')} interactive={false} + copiable /> ) : null} @@ -241,6 +243,7 @@ function ProfilePage({route}: ProfilePageProps) { title={pronouns} description={translate('profilePage.preferredPronouns')} interactive={false} + copiable /> ) : null} From 6c2ed7358c5f7736554b535609ab05f9841e5755 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Sat, 9 Aug 2025 00:09:07 +0530 Subject: [PATCH 07/17] make card details copiable. Signed-off-by: krishna2323 --- src/pages/settings/Wallet/ExpensifyCardPage.tsx | 1 + src/pages/settings/Wallet/WalletPage/CardDetails.tsx | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/pages/settings/Wallet/ExpensifyCardPage.tsx b/src/pages/settings/Wallet/ExpensifyCardPage.tsx index 91fc2caf6b3e..444faea10665 100644 --- a/src/pages/settings/Wallet/ExpensifyCardPage.tsx +++ b/src/pages/settings/Wallet/ExpensifyCardPage.tsx @@ -255,6 +255,7 @@ function ExpensifyCardPage({ /> ) : undefined } + copiable /> )} {expiration?.length > 0 && ( @@ -56,6 +57,7 @@ function CardDetails({pan = '', expiration = '', cvv = '', domain}: CardDetailsP description={translate('cardPage.cardDetails.expiration')} title={expiration} interactive={false} + copiable /> )} {cvv?.length > 0 && ( @@ -63,6 +65,7 @@ function CardDetails({pan = '', expiration = '', cvv = '', domain}: CardDetailsP description={translate('cardPage.cardDetails.cvv')} title={cvv} interactive={false} + copiable /> )} {pan?.length > 0 && ( From 40c6d58651ffea4a57af532aa9a7911e1e60eb72 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Sat, 9 Aug 2025 00:14:43 +0530 Subject: [PATCH 08/17] make address and email copiable. Signed-off-by: krishna2323 --- src/pages/settings/Wallet/WalletPage/CardDetails.tsx | 1 + src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/src/pages/settings/Wallet/WalletPage/CardDetails.tsx b/src/pages/settings/Wallet/WalletPage/CardDetails.tsx index fd2467fdbf91..28f51ee2b1ab 100644 --- a/src/pages/settings/Wallet/WalletPage/CardDetails.tsx +++ b/src/pages/settings/Wallet/WalletPage/CardDetails.tsx @@ -75,6 +75,7 @@ function CardDetails({pan = '', expiration = '', cvv = '', domain}: CardDetailsP // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing title={getFormattedAddress(privatePersonalDetails || defaultPrivatePersonalDetails)} interactive={false} + copiable /> Date: Mon, 11 Aug 2025 02:28:56 +0530 Subject: [PATCH 09/17] fix failing tests. Signed-off-by: krishna2323 --- cspell.json | 3 ++- src/pages/settings/Wallet/WalletPage/CardDetails.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cspell.json b/cspell.json index e10037fa42ea..1a0f2374672b 100644 --- a/cspell.json +++ b/cspell.json @@ -732,7 +732,8 @@ "POLICYCHANGELOG_ADD_EMPLOYEE", "xcshareddata", "xcuserdata", - "inputmethod" + "inputmethod", + "copiable" ], "ignorePaths": [ "src/languages/de.ts", diff --git a/src/pages/settings/Wallet/WalletPage/CardDetails.tsx b/src/pages/settings/Wallet/WalletPage/CardDetails.tsx index 28f51ee2b1ab..7fd10612e2b1 100644 --- a/src/pages/settings/Wallet/WalletPage/CardDetails.tsx +++ b/src/pages/settings/Wallet/WalletPage/CardDetails.tsx @@ -39,7 +39,7 @@ type CardDetailsProps = { function CardDetails({pan = '', expiration = '', cvv = '', domain}: CardDetailsProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); - const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); + const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS, {canBeMissing: true}); return ( <> From c8575198fcb295485c02153e5993714f0040d85c Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Tue, 12 Aug 2025 21:47:01 +0530 Subject: [PATCH 10/17] make reportID and longID copiable. Signed-off-by: krishna2323 --- src/pages/ReportDetailsPage.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index e22e313fd2eb..5af1ccc0bbe7 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -881,6 +881,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail copyValue={base62ReportID} interactive={false} shouldBlockSelection + copiable /> )} From c6afea35350c243f723036389b6c4982800042aa Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Thu, 14 Aug 2025 03:49:35 +0530 Subject: [PATCH 11/17] fix comments and remove copiable prop from unqualified rows. Signed-off-by: krishna2323 --- src/components/CopyTextToClipboard.tsx | 10 ++++---- src/components/MenuItem.tsx | 11 +++++---- .../Pressable/PressableWithDelayToggle.tsx | 24 ++++++++----------- src/pages/KeyboardShortcutsPage.tsx | 1 - src/pages/ProfilePage.tsx | 2 -- .../Wallet/WalletPage/CardDetails.tsx | 1 - 6 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/components/CopyTextToClipboard.tsx b/src/components/CopyTextToClipboard.tsx index 249ad42b7e7f..5e1159941bfb 100644 --- a/src/components/CopyTextToClipboard.tsx +++ b/src/components/CopyTextToClipboard.tsx @@ -16,7 +16,7 @@ type CopyTextToClipboardProps = { urlToCopy?: string; accessibilityRole?: AccessibilityRole; -} & Pick; +} & Pick; function CopyTextToClipboard({ text, @@ -26,8 +26,8 @@ function CopyTextToClipboard({ iconHeight, iconStyles, iconWidth, - shouldIconAlwaysUseHoveredStyle, - shouldIconUseBackgroundColor, + shouldHaveActiveBackground, + shouldUseButtonBackground, styles, }: CopyTextToClipboardProps) { const {translate} = useLocalize(); @@ -48,12 +48,12 @@ function CopyTextToClipboard({ accessible accessibilityLabel={translate('reportActionContextMenu.copyToClipboard')} accessibilityRole={accessibilityRole} - shouldIconAlwaysUseHoveredStyle={shouldIconAlwaysUseHoveredStyle} + shouldHaveActiveBackground={shouldHaveActiveBackground} iconWidth={iconWidth} iconHeight={iconHeight} iconStyles={iconStyles} styles={styles} - shouldIconUseBackgroundColor={shouldIconUseBackgroundColor} + shouldUseButtonBackground={shouldUseButtonBackground} /> ); } diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index f56dbe05cde2..ce63c0b99fe1 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -367,10 +367,10 @@ type MenuItemBaseProps = { /** Whether to teleport the portal to the modal layer */ shouldTeleportPortalToModalLayer?: boolean; - /** The value to copy on secondary interaction */ + /** The value to copy in copy to clipboard action. Must be used in conjunction with `copiable=true`. Default value is `title` prop. */ copyValue?: string; - /** Should disable copy to clipboard action */ + /** Should enable copy to clipboard action */ copiable?: boolean; /** Plaid image for the bank */ @@ -513,6 +513,7 @@ function MenuItem( const {shouldUseNarrowLayout} = useResponsiveLayout(); const {isExecuting, singleExecution, waitForNavigate} = useContext(MenuItemGroupContext) ?? {}; const popoverAnchor = useRef(null); + const deviceHasHoverSupport = hasHoverSupport(); const isCompact = viewMode === CONST.OPTION_MODE.COMPACT; const isDeleted = style && Array.isArray(style) ? style.includes(styles.offlineFeedback.deleted) : false; @@ -958,16 +959,16 @@ function MenuItem( additionalStyles={styles.alignSelfCenter} /> )} - {copiable && hasHoverSupport() && !interactive && isHovered && !!copyValue && ( + {copiable && deviceHasHoverSupport && !interactive && isHovered && !!copyValue && ( )} diff --git a/src/components/Pressable/PressableWithDelayToggle.tsx b/src/components/Pressable/PressableWithDelayToggle.tsx index 30d3864bcee1..db6c01320d3f 100644 --- a/src/components/Pressable/PressableWithDelayToggle.tsx +++ b/src/components/Pressable/PressableWithDelayToggle.tsx @@ -51,16 +51,16 @@ type PressableWithDelayToggleProps = PressableProps & { inline?: boolean; accessibilityRole?: string; - /** For using the background color, e.g. if we need bg for the icon */ - shouldIconUseBackgroundColor?: boolean; + /** Whether to use background color based on button states, e.g., hovered, active, pressed... */ + shouldUseButtonBackground?: boolean; - /** For using the hovered style by default, e.g. if we always need the hovered bg */ - shouldIconAlwaysUseHoveredStyle?: boolean; + /** Whether to always use active (hovered) background by default */ + shouldHaveActiveBackground?: boolean; - /** Copy icon width */ + /** Icon width */ iconWidth?: number; - /** Copy icon height */ + /** Icon height */ iconHeight?: number; }; @@ -78,10 +78,10 @@ function PressableWithDelayToggle( iconStyles, icon, accessibilityRole, - shouldIconAlwaysUseHoveredStyle, + shouldHaveActiveBackground, iconWidth = variables.iconSizeSmall, iconHeight = variables.iconSizeSmall, - shouldIconUseBackgroundColor = false, + shouldUseButtonBackground = false, }: PressableWithDelayToggleProps, ref: PressableRef, ) { @@ -138,13 +138,9 @@ function PressableWithDelayToggle( styles.flexRow, pressableStyle, !isActive && styles.cursorDefault, - shouldIconUseBackgroundColor && + shouldUseButtonBackground && StyleUtils.getButtonBackgroundColorStyle( - getButtonState( - !!shouldIconAlwaysUseHoveredStyle || hovered, - shouldIconAlwaysUseHoveredStyle ? hovered : pressed, - !shouldIconAlwaysUseHoveredStyle && !isActive, - ), + getButtonState(!!shouldHaveActiveBackground || hovered, shouldHaveActiveBackground ? hovered : pressed, !shouldHaveActiveBackground && !isActive), true, ), ]} diff --git a/src/pages/KeyboardShortcutsPage.tsx b/src/pages/KeyboardShortcutsPage.tsx index a2b8c2550bcd..d68643e74a5a 100644 --- a/src/pages/KeyboardShortcutsPage.tsx +++ b/src/pages/KeyboardShortcutsPage.tsx @@ -38,7 +38,6 @@ function KeyboardShortcutsPage() { description={translate(`keyboardShortcutsPage.shortcuts.${shortcut.descriptionKey}`)} wrapperStyle={[styles.ph0, styles.cursorAuto]} interactive={false} - copiable /> ); diff --git a/src/pages/ProfilePage.tsx b/src/pages/ProfilePage.tsx index 1905da6397a6..73b2ac86e3c9 100755 --- a/src/pages/ProfilePage.tsx +++ b/src/pages/ProfilePage.tsx @@ -218,7 +218,6 @@ function ProfilePage({route}: ProfilePageProps) { title={statusContent} description={translate('statusPage.status')} interactive={false} - copiable /> )} @@ -243,7 +242,6 @@ function ProfilePage({route}: ProfilePageProps) { title={pronouns} description={translate('profilePage.preferredPronouns')} interactive={false} - copiable /> ) : null} diff --git a/src/pages/settings/Wallet/WalletPage/CardDetails.tsx b/src/pages/settings/Wallet/WalletPage/CardDetails.tsx index 7fd10612e2b1..ef50c4e2c590 100644 --- a/src/pages/settings/Wallet/WalletPage/CardDetails.tsx +++ b/src/pages/settings/Wallet/WalletPage/CardDetails.tsx @@ -57,7 +57,6 @@ function CardDetails({pan = '', expiration = '', cvv = '', domain}: CardDetailsP description={translate('cardPage.cardDetails.expiration')} title={expiration} interactive={false} - copiable /> )} {cvv?.length > 0 && ( From 4eed3c2b1c28bade360776b67e9f2d2ca0203a3f Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Thu, 14 Aug 2025 03:50:20 +0530 Subject: [PATCH 12/17] remove copiable prop for localTime Signed-off-by: krishna2323 --- src/components/AutoUpdateTime.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/AutoUpdateTime.tsx b/src/components/AutoUpdateTime.tsx index b9ac1b78dbcd..fca87a17aa68 100644 --- a/src/components/AutoUpdateTime.tsx +++ b/src/components/AutoUpdateTime.tsx @@ -53,7 +53,6 @@ function AutoUpdateTime({timezone}: AutoUpdateTimeProps) { title={`${DateUtils.formatToLocalTime(currentUserLocalTime)} ${timezoneName}`} description={translate('detailsPage.localTime')} interactive={false} - copiable /> ); From b466e26c1212fa87b2bb8b4c29796316adbb579a Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Thu, 14 Aug 2025 04:34:52 +0530 Subject: [PATCH 13/17] remove copiable prop for . Signed-off-by: krishna2323 --- src/pages/settings/Wallet/ExpensifyCardPage.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/settings/Wallet/ExpensifyCardPage.tsx b/src/pages/settings/Wallet/ExpensifyCardPage.tsx index 444faea10665..91fc2caf6b3e 100644 --- a/src/pages/settings/Wallet/ExpensifyCardPage.tsx +++ b/src/pages/settings/Wallet/ExpensifyCardPage.tsx @@ -255,7 +255,6 @@ function ExpensifyCardPage({ /> ) : undefined } - copiable /> Date: Sun, 17 Aug 2025 21:43:40 +0530 Subject: [PATCH 14/17] fix failing tests. Signed-off-by: krishna2323 --- .../Pressable/PressableWithDelayToggle.tsx | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/components/Pressable/PressableWithDelayToggle.tsx b/src/components/Pressable/PressableWithDelayToggle.tsx index 76149b9914bd..3e8914df5fde 100644 --- a/src/components/Pressable/PressableWithDelayToggle.tsx +++ b/src/components/Pressable/PressableWithDelayToggle.tsx @@ -51,7 +51,7 @@ type PressableWithDelayToggleProps = PressableProps & { inline?: boolean; accessibilityRole?: string; - /** + /** * Reference to the outer element */ ref?: PressableRef; @@ -69,28 +69,25 @@ type PressableWithDelayToggleProps = PressableProps & { iconHeight?: number; }; -function PressableWithDelayToggle( - { - iconChecked = Expensicons.Checkmark, - inline = true, - onPress, - text, - textChecked, - tooltipText, - tooltipTextChecked, - styles: pressableStyle, - textStyles, - iconStyles, - icon, - ref, - accessibilityRole, - shouldHaveActiveBackground, - iconWidth = variables.iconSizeSmall, - iconHeight = variables.iconSizeSmall, - shouldUseButtonBackground = false, - }: PressableWithDelayToggleProps, - ref: PressableRef, -) { +function PressableWithDelayToggle({ + iconChecked = Expensicons.Checkmark, + inline = true, + onPress, + text, + textChecked, + tooltipText, + tooltipTextChecked, + styles: pressableStyle, + textStyles, + iconStyles, + icon, + ref, + accessibilityRole, + shouldHaveActiveBackground, + iconWidth = variables.iconSizeSmall, + iconHeight = variables.iconSizeSmall, + shouldUseButtonBackground = false, +}: PressableWithDelayToggleProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const [isActive, temporarilyDisableInteractions] = useThrottledButtonState(); @@ -176,3 +173,4 @@ function PressableWithDelayToggle( PressableWithDelayToggle.displayName = 'PressableWithDelayToggle'; export default PressableWithDelayToggle; +export type {PressableWithDelayToggleProps}; From 0a908cac43962455081fcbc69e5762fda9540475 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Wed, 20 Aug 2025 21:43:34 +0530 Subject: [PATCH 15/17] make card expiration date copiable. Signed-off-by: krishna2323 --- src/pages/settings/Wallet/WalletPage/CardDetails.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/settings/Wallet/WalletPage/CardDetails.tsx b/src/pages/settings/Wallet/WalletPage/CardDetails.tsx index ef50c4e2c590..7fd10612e2b1 100644 --- a/src/pages/settings/Wallet/WalletPage/CardDetails.tsx +++ b/src/pages/settings/Wallet/WalletPage/CardDetails.tsx @@ -57,6 +57,7 @@ function CardDetails({pan = '', expiration = '', cvv = '', domain}: CardDetailsP description={translate('cardPage.cardDetails.expiration')} title={expiration} interactive={false} + copiable /> )} {cvv?.length > 0 && ( From c7a5a9b3f6c108028d5f022d5520a0df837a6f9f Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Wed, 20 Aug 2025 21:48:48 +0530 Subject: [PATCH 16/17] fix prettier. Signed-off-by: krishna2323 --- cspell.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cspell.json b/cspell.json index df610ecebf35..a97c9fe11587 100644 --- a/cspell.json +++ b/cspell.json @@ -738,7 +738,7 @@ "zxcv", "zxldvw", "inputmethod", - "copiable" + "copiable", "مثال" ], "ignorePaths": [ From 2d435c153dc9af7ac86b40e1edad882d4e8c792e Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Thu, 21 Aug 2025 02:04:59 +0530 Subject: [PATCH 17/17] use "copyable" instead of "copiable". Signed-off-by: krishna2323 --- cspell.json | 2 +- src/components/MenuItem.tsx | 8 ++++---- src/pages/ProfilePage.tsx | 2 +- src/pages/ReportDetailsPage.tsx | 4 ++-- src/pages/settings/Wallet/WalletPage/CardDetails.tsx | 8 ++++---- .../workspace/members/WorkspaceMemberDetailsPage.tsx | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/cspell.json b/cspell.json index a97c9fe11587..1bc661349281 100644 --- a/cspell.json +++ b/cspell.json @@ -738,7 +738,7 @@ "zxcv", "zxldvw", "inputmethod", - "copiable", + "copyable", "مثال" ], "ignorePaths": [ diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 46373d255bba..c9a7afff13cf 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -367,11 +367,11 @@ type MenuItemBaseProps = { /** Whether to teleport the portal to the modal layer */ shouldTeleportPortalToModalLayer?: boolean; - /** The value to copy in copy to clipboard action. Must be used in conjunction with `copiable=true`. Default value is `title` prop. */ + /** The value to copy in copy to clipboard action. Must be used in conjunction with `copyable=true`. Default value is `title` prop. */ copyValue?: string; /** Should enable copy to clipboard action */ - copiable?: boolean; + copyable?: boolean; /** Plaid image for the bank */ plaidUrl?: string; @@ -505,7 +505,7 @@ function MenuItem( shouldTeleportPortalToModalLayer, plaidUrl, copyValue = title, - copiable = false, + copyable = false, hasSubMenuItems = false, }: MenuItemProps, ref: PressableRef, @@ -970,7 +970,7 @@ function MenuItem( additionalStyles={styles.alignSelfCenter} /> )} - {copiable && deviceHasHoverSupport && !interactive && isHovered && !!copyValue && ( + {copyable && deviceHasHoverSupport && !interactive && isHovered && !!copyValue && ( ) : null} diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 5af1ccc0bbe7..b87d1bfa4bab 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -881,7 +881,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail copyValue={base62ReportID} interactive={false} shouldBlockSelection - copiable + copyable /> )} diff --git a/src/pages/settings/Wallet/WalletPage/CardDetails.tsx b/src/pages/settings/Wallet/WalletPage/CardDetails.tsx index 7fd10612e2b1..eb12d0c14c6e 100644 --- a/src/pages/settings/Wallet/WalletPage/CardDetails.tsx +++ b/src/pages/settings/Wallet/WalletPage/CardDetails.tsx @@ -49,7 +49,7 @@ function CardDetails({pan = '', expiration = '', cvv = '', domain}: CardDetailsP title={pan} interactive={false} copyValue={pan} - copiable + copyable /> )} {expiration?.length > 0 && ( @@ -57,7 +57,7 @@ function CardDetails({pan = '', expiration = '', cvv = '', domain}: CardDetailsP description={translate('cardPage.cardDetails.expiration')} title={expiration} interactive={false} - copiable + copyable /> )} {cvv?.length > 0 && ( @@ -65,7 +65,7 @@ function CardDetails({pan = '', expiration = '', cvv = '', domain}: CardDetailsP description={translate('cardPage.cardDetails.cvv')} title={cvv} interactive={false} - copiable + copyable /> )} {pan?.length > 0 && ( @@ -75,7 +75,7 @@ function CardDetails({pan = '', expiration = '', cvv = '', domain}: CardDetailsP // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing title={getFormattedAddress(privatePersonalDetails || defaultPrivatePersonalDetails)} interactive={false} - copiable + copyable />