From 5b80f80585d46793d4eada308a79ac60b4f68134 Mon Sep 17 00:00:00 2001 From: Dariusz Biela Date: Fri, 12 Dec 2025 16:55:29 +0100 Subject: [PATCH 1/8] feat: add sentryLabel to FloatingActionButton and FloatingReceiptButton --- src/CONST/index.ts | 2 ++ src/components/FloatingActionButton.tsx | 7 ++++++- src/components/FloatingReceiptButton.tsx | 6 +++++- src/pages/home/sidebar/FloatingActionButtonAndPopover.tsx | 2 ++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 975cbd0052a7..cd4d9e84190a 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -7524,6 +7524,8 @@ const CONST = { REPORTS: 'NavigationTabBar-Reports', WORKSPACES: 'NavigationTabBar-Workspaces', ACCOUNT: 'NavigationTabBar-Account', + FLOATING_ACTION_BUTTON: 'NavigationTabBar-FloatingActionButton', + FLOATING_RECEIPT_BUTTON: 'NavigationTabBar-FloatingReceiptButton', }, }, } as const; diff --git a/src/components/FloatingActionButton.tsx b/src/components/FloatingActionButton.tsx index 20036f30144a..dd6c14091e29 100644 --- a/src/components/FloatingActionButton.tsx +++ b/src/components/FloatingActionButton.tsx @@ -42,9 +42,12 @@ type FloatingActionButtonProps = { /** Reference to the outer element */ ref?: ForwardedRef; + + /** Label for Sentry INP tracking */ + sentryLabel?: string; }; -function FloatingActionButton({onPress, onLongPress, isActive, accessibilityLabel, role, ref}: FloatingActionButtonProps) { +function FloatingActionButton({onPress, onLongPress, isActive, accessibilityLabel, role, ref, sentryLabel}: FloatingActionButtonProps) { const {buttonDefaultBG, buttonHoveredBG, icon} = useTheme(); const styles = useThemeStyles(); const borderRadius = styles.floatingActionButton.borderRadius; @@ -115,6 +118,7 @@ function FloatingActionButton({onPress, onLongPress, isActive, accessibilityLabe role={role} shouldUseHapticsOnLongPress testID="floating-action-button" + sentryLabel={sentryLabel} > {({hovered}) => { isHovered.set(hovered); @@ -154,6 +158,7 @@ function FloatingActionButton({onPress, onLongPress, isActive, accessibilityLabe styles.flex1, ]} testID="create-action-button" + sentryLabel={sentryLabel} > {({hovered}) => ( )} ); From 86e138f8ff070469b863a4a0242baa7b1533505d Mon Sep 17 00:00:00 2001 From: Dariusz Biela Date: Fri, 12 Dec 2025 17:32:24 +0100 Subject: [PATCH 2/8] eat: add sentryLabel to MenuItem and FAB menu items --- src/CONST/index.ts | 11 +++++++++++ src/components/MenuItem.tsx | 5 +++++ .../home/sidebar/FloatingActionButtonAndPopover.tsx | 10 ++++++++++ 3 files changed, 26 insertions(+) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index cd4d9e84190a..dceb5fd5d081 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -7527,6 +7527,17 @@ const CONST = { FLOATING_ACTION_BUTTON: 'NavigationTabBar-FloatingActionButton', FLOATING_RECEIPT_BUTTON: 'NavigationTabBar-FloatingReceiptButton', }, + FAB_MENU: { + CREATE_EXPENSE: 'FABMenu-CreateExpense', + TRACK_DISTANCE: 'FABMenu-TrackDistance', + CREATE_REPORT: 'FABMenu-CreateReport', + START_CHAT: 'FABMenu-StartChat', + SEND_INVOICE: 'FABMenu-SendInvoice', + BOOK_TRAVEL: 'FABMenu-BookTravel', + TEST_DRIVE: 'FABMenu-TestDrive', + NEW_WORKSPACE: 'FABMenu-NewWorkspace', + QUICK_ACTION: 'FABMenu-QuickAction', + }, }, } as const; diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 7d65a8c4294a..395f8032f112 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -394,6 +394,9 @@ type MenuItemBaseProps = ForwardedFSClassProps & { /** Whether the screen containing the item is focused */ isFocused?: boolean; + + /** Label for Sentry INP tracking */ + sentryLabel?: string; }; type MenuItemProps = (IconProps | AvatarProps | NoIcon) & MenuItemBaseProps; @@ -522,6 +525,7 @@ function MenuItem({ forwardedFSClass, ref, isFocused, + sentryLabel, }: MenuItemProps) { const theme = useTheme(); const styles = useThemeStyles(); @@ -722,6 +726,7 @@ function MenuItem({ accessibilityLabel={title ? title.toString() : ''} accessible onFocus={onFocus} + sentryLabel={sentryLabel} > {({pressed}) => ( diff --git a/src/pages/home/sidebar/FloatingActionButtonAndPopover.tsx b/src/pages/home/sidebar/FloatingActionButtonAndPopover.tsx index bd77c57557f9..35f90fd580e8 100644 --- a/src/pages/home/sidebar/FloatingActionButtonAndPopover.tsx +++ b/src/pages/home/sidebar/FloatingActionButtonAndPopover.tsx @@ -406,6 +406,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, ref } startMoneyRequest(CONST.IOU.TYPE.CREATE, reportID, undefined, undefined, undefined, allTransactionDrafts); }), + sentryLabel: CONST.SENTRY_LABEL.FAB_MENU.CREATE_EXPENSE, }, ]; }, [translate, shouldRedirectToExpensifyClassic, shouldUseNarrowLayout, allTransactionDrafts, reportID]); @@ -459,6 +460,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, ref onSelected, shouldCallAfterModalHide: shouldUseNarrowLayout, rightIconReportID: quickActionReport?.reportID, + sentryLabel: CONST.SENTRY_LABEL.FAB_MENU.QUICK_ACTION, }, ]; } @@ -485,6 +487,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, ref shouldCallAfterModalHide: shouldUseNarrowLayout, onSelected, rightIconReportID: policyChatForActivePolicy?.reportID, + sentryLabel: CONST.SENTRY_LABEL.FAB_MENU.QUICK_ACTION, }, ]; } @@ -550,6 +553,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, ref startDistanceRequest(CONST.IOU.TYPE.CREATE, reportID, lastDistanceExpenseType); }); }, + sentryLabel: CONST.SENTRY_LABEL.FAB_MENU.TRACK_DISTANCE, }, ...(shouldShowCreateReportOption ? [ @@ -585,6 +589,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, ref Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(workspaceIDForReportCreation)); }); }, + sentryLabel: CONST.SENTRY_LABEL.FAB_MENU.CREATE_REPORT, }, ] : []), @@ -593,6 +598,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, ref text: translate('sidebarScreen.fabNewChat'), shouldCallAfterModalHide: shouldUseNarrowLayout, onSelected: () => interceptAnonymousUser(startNewChat), + sentryLabel: CONST.SENTRY_LABEL.FAB_MENU.START_CHAT, }, ...(canSendInvoice ? [ @@ -609,6 +615,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, ref startMoneyRequest(CONST.IOU.TYPE.INVOICE, reportID, undefined, undefined, undefined, allTransactionDrafts); }), + sentryLabel: CONST.SENTRY_LABEL.FAB_MENU.SEND_INVOICE, }, ] : []), @@ -618,6 +625,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, ref text: translate('travel.bookTravel'), rightIcon: isTravelEnabled && shouldOpenTravelDotLinkWeb() ? icons.NewWindow : undefined, onSelected: () => interceptAnonymousUser(() => openTravel()), + sentryLabel: CONST.SENTRY_LABEL.FAB_MENU.BOOK_TRAVEL, }, ], ...(!hasSeenTour @@ -628,6 +636,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, ref iconFill: theme.icon, text: translate('testDrive.quickAction.takeATwoMinuteTestDrive'), onSelected: () => interceptAnonymousUser(() => startTestDrive(introSelected, tryNewDot?.hasBeenAddedToNudgeMigration ?? false, isUserPaidPolicyMember)), + sentryLabel: CONST.SENTRY_LABEL.FAB_MENU.TEST_DRIVE, }, ] : []), @@ -643,6 +652,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, ref description: translate('workspace.new.getTheExpensifyCardAndMore'), shouldCallAfterModalHide: shouldUseNarrowLayout, onSelected: () => interceptAnonymousUser(() => Navigation.navigate(ROUTES.WORKSPACE_CONFIRMATION.getRoute(Navigation.getActiveRoute()))), + sentryLabel: CONST.SENTRY_LABEL.FAB_MENU.NEW_WORKSPACE, }, ] : []), From c8a47f39474383db81b30e8b5ed00dc03ee9acd2 Mon Sep 17 00:00:00 2001 From: Dariusz Biela Date: Tue, 16 Dec 2025 13:08:15 +0100 Subject: [PATCH 3/8] feat: add sentryLabel to attachment, video player and header components --- src/CONST/index.ts | 31 +++++++++++++++++++ .../AttachmentCarousel/CarouselButtons.tsx | 3 ++ .../AttachmentCarousel/CarouselItem.tsx | 2 ++ .../AttachmentViewImage/index.tsx | 1 + .../Attachments/AttachmentView/index.tsx | 1 + .../HTMLRenderers/ImageRenderer.tsx | 1 + src/components/HeaderWithBackButton/index.tsx | 3 ++ src/components/ImageView/index.tsx | 1 + .../ReportActionItemImage.tsx | 1 + .../VideoPlayer/BaseVideoPlayer.tsx | 1 + src/components/VideoPlayer/IconButton.tsx | 4 ++- .../VolumeButton/index.tsx | 2 ++ .../VideoPlayer/VideoPlayerControls/index.tsx | 3 ++ .../VideoPlayerThumbnail.tsx | 1 + src/components/VideoPlayerPreview/index.tsx | 1 + .../AttachmentModalBaseContent/index.tsx | 1 + 16 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index dceb5fd5d081..46733bf30104 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -7538,6 +7538,37 @@ const CONST = { NEW_WORKSPACE: 'FABMenu-NewWorkspace', QUICK_ACTION: 'FABMenu-QuickAction', }, + ATTACHMENT_CAROUSEL: { + PREVIOUS_BUTTON: 'AttachmentCarousel-PreviousButton', + NEXT_BUTTON: 'AttachmentCarousel-NextButton', + ITEM: 'AttachmentCarousel-Item', + MODERATION_BUTTON: 'AttachmentCarousel-ModerationButton', + RETRY_BUTTON: 'AttachmentView-RetryButton', + }, + ATTACHMENT_MODAL: { + SEND_BUTTON: 'AttachmentModal-SendButton', + IMAGE_ZOOM: 'AttachmentModal-ImageZoom', + }, + HEADER: { + BACK_BUTTON: 'Header-BackButton', + DOWNLOAD_BUTTON: 'Header-DownloadButton', + CLOSE_BUTTON: 'Header-CloseButton', + }, + VIDEO_PLAYER: { + PLAY_PAUSE_BUTTON: 'VideoPlayer-PlayPauseButton', + FULLSCREEN_BUTTON: 'VideoPlayer-FullscreenButton', + MORE_BUTTON: 'VideoPlayer-MoreButton', + EXPAND_BUTTON: 'VideoPlayer-ExpandButton', + THUMBNAIL: 'VideoPlayer-Thumbnail', + MUTE_BUTTON: 'VideoPlayer-MuteButton', + VIDEO: 'VideoPlayer-Video', + }, + HTML_RENDERER: { + IMAGE: 'HTMLRenderer-Image', + }, + RECEIPT: { + IMAGE: 'Receipt-Image', + }, }, } as const; diff --git a/src/components/Attachments/AttachmentCarousel/CarouselButtons.tsx b/src/components/Attachments/AttachmentCarousel/CarouselButtons.tsx index 04fd1163af44..20c70383ca01 100644 --- a/src/components/Attachments/AttachmentCarousel/CarouselButtons.tsx +++ b/src/components/Attachments/AttachmentCarousel/CarouselButtons.tsx @@ -8,6 +8,7 @@ import useLocalize from '@hooks/useLocalize'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import CONST from '@src/CONST'; type CarouselButtonsProps = { /** Where the arrows should be visible */ @@ -53,6 +54,7 @@ function CarouselButtons({page, attachments, shouldShowArrows, onBack, onForward onPress={onBack} onPressIn={cancelAutoHideArrow} onPressOut={autoHideArrow} + sentryLabel={CONST.SENTRY_LABEL.ATTACHMENT_CAROUSEL.PREVIOUS_BUTTON} /> @@ -68,6 +70,7 @@ function CarouselButtons({page, attachments, shouldShowArrows, onBack, onForward onPress={onForward} onPressIn={cancelAutoHideArrow} onPressOut={autoHideArrow} + sentryLabel={CONST.SENTRY_LABEL.ATTACHMENT_CAROUSEL.NEXT_BUTTON} /> diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.tsx b/src/components/Attachments/AttachmentCarousel/CarouselItem.tsx index 4724b3afaf48..71660219378b 100644 --- a/src/components/Attachments/AttachmentCarousel/CarouselItem.tsx +++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.tsx @@ -46,6 +46,7 @@ function CarouselItem({item, onPress, isFocused, isModalHovered, reportID}: Caro style={style} onPress={() => setIsHidden(!isHidden)} testID="moderationButton" + sentryLabel={CONST.SENTRY_LABEL.ATTACHMENT_CAROUSEL.MODERATION_BUTTON} > {children} diff --git a/src/components/Attachments/AttachmentView/AttachmentViewImage/index.tsx b/src/components/Attachments/AttachmentView/AttachmentViewImage/index.tsx index 5a009f0eb5ea..22dd374b237e 100644 --- a/src/components/Attachments/AttachmentView/AttachmentViewImage/index.tsx +++ b/src/components/Attachments/AttachmentView/AttachmentViewImage/index.tsx @@ -38,6 +38,7 @@ function AttachmentViewImage({attachmentID, url, file, isAuthTokenRequired, load accessibilityRole={CONST.ROLE.BUTTON} // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing accessibilityLabel={file?.name || translate('attachmentView.unknownFilename')} + sentryLabel={CONST.SENTRY_LABEL.ATTACHMENT_CAROUSEL.ITEM} > {children} diff --git a/src/components/Attachments/AttachmentView/index.tsx b/src/components/Attachments/AttachmentView/index.tsx index c74fa704e581..abdebd1554b2 100644 --- a/src/components/Attachments/AttachmentView/index.tsx +++ b/src/components/Attachments/AttachmentView/index.tsx @@ -301,6 +301,7 @@ function AttachmentView({ } setImageError(false); }} + sentryLabel={CONST.SENTRY_LABEL.ATTACHMENT_CAROUSEL.RETRY_BUTTON} /> ); diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx index f8584ae5f1f5..7bef8ba5dbcc 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx @@ -129,6 +129,7 @@ function ImageRenderer({tnode}: CustomRendererProps) { shouldUseHapticsOnLongPress role={getButtonRole(true)} accessibilityLabel={translate('accessibilityHints.viewAttachment')} + sentryLabel={CONST.SENTRY_LABEL.HTML_RENDERER.IMAGE} > {thumbnailImageComponent} diff --git a/src/components/HeaderWithBackButton/index.tsx b/src/components/HeaderWithBackButton/index.tsx index 68d9a99b4644..574cc9583452 100755 --- a/src/components/HeaderWithBackButton/index.tsx +++ b/src/components/HeaderWithBackButton/index.tsx @@ -221,6 +221,7 @@ function HeaderWithBackButton({ role={CONST.ROLE.BUTTON} accessibilityLabel={translate('common.back')} id={CONST.BACK_BUTTON_NATIVE_ID} + sentryLabel={CONST.SENTRY_LABEL.HEADER.BACK_BUTTON} > {shouldUseSharedVideoElement ? ( <> diff --git a/src/components/VideoPlayer/IconButton.tsx b/src/components/VideoPlayer/IconButton.tsx index 3066cc7620ef..5e3ee1f9eb01 100644 --- a/src/components/VideoPlayer/IconButton.tsx +++ b/src/components/VideoPlayer/IconButton.tsx @@ -16,9 +16,10 @@ type IconButtonProps = { hoverStyle?: StyleProp; small?: boolean; shouldForceRenderingTooltipBelow?: boolean; + sentryLabel?: string; }; -function IconButton({src, fill = 'white', onPress, style, hoverStyle, tooltipText = '', small = false, shouldForceRenderingTooltipBelow = false}: IconButtonProps) { +function IconButton({src, fill = 'white', onPress, style, hoverStyle, tooltipText = '', small = false, shouldForceRenderingTooltipBelow = false, sentryLabel}: IconButtonProps) { const styles = useThemeStyles(); return ( )} diff --git a/src/components/VideoPlayer/VideoPlayerControls/index.tsx b/src/components/VideoPlayer/VideoPlayerControls/index.tsx index 67f5f99b055e..712ba41927cc 100644 --- a/src/components/VideoPlayer/VideoPlayerControls/index.tsx +++ b/src/components/VideoPlayer/VideoPlayerControls/index.tsx @@ -109,6 +109,7 @@ function VideoPlayerControls({ onPress={togglePlayCurrentVideo} style={styles.mr2} small={small} + sentryLabel={CONST.SENTRY_LABEL.VIDEO_PLAYER.PLAY_PAUSE_BUTTON} /> {shouldShowTime && ( @@ -126,12 +127,14 @@ function VideoPlayerControls({ onPress={enterFullScreenMode} style={iconSpacing} small={small} + sentryLabel={CONST.SENTRY_LABEL.VIDEO_PLAYER.FULLSCREEN_BUTTON} /> diff --git a/src/components/VideoPlayerPreview/VideoPlayerThumbnail.tsx b/src/components/VideoPlayerPreview/VideoPlayerThumbnail.tsx index 09f1695079ad..dff35a2d8a16 100644 --- a/src/components/VideoPlayerPreview/VideoPlayerThumbnail.tsx +++ b/src/components/VideoPlayerPreview/VideoPlayerThumbnail.tsx @@ -62,6 +62,7 @@ function VideoPlayerThumbnail({thumbnailUrl, onPress, accessibilityLabel, isDele }); }} shouldUseHapticsOnLongPress + sentryLabel={CONST.SENTRY_LABEL.VIDEO_PLAYER.THUMBNAIL} > diff --git a/src/pages/media/AttachmentModalScreen/AttachmentModalBaseContent/index.tsx b/src/pages/media/AttachmentModalScreen/AttachmentModalBaseContent/index.tsx index 226b691e514b..d2fb1cbf0dfa 100644 --- a/src/pages/media/AttachmentModalScreen/AttachmentModalBaseContent/index.tsx +++ b/src/pages/media/AttachmentModalScreen/AttachmentModalBaseContent/index.tsx @@ -341,6 +341,7 @@ function AttachmentModalBaseContent({ onPress={submitAndClose} isDisabled={isConfirmButtonDisabled || shouldDisableSendButton} pressOnEnter + sentryLabel={CONST.SENTRY_LABEL.ATTACHMENT_MODAL.SEND_BUTTON} /> )} From 4d096fcf5b049b097e7d66be95003499b20d930e Mon Sep 17 00:00:00 2001 From: Dariusz Biela Date: Tue, 16 Dec 2025 14:02:52 +0100 Subject: [PATCH 4/8] fix: replace deprecated runOnJS with scheduleOnRN in BaseVideoPlayer --- src/components/VideoPlayer/BaseVideoPlayer.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/VideoPlayer/BaseVideoPlayer.tsx b/src/components/VideoPlayer/BaseVideoPlayer.tsx index b8e5072cc66c..0f52346ea773 100644 --- a/src/components/VideoPlayer/BaseVideoPlayer.tsx +++ b/src/components/VideoPlayer/BaseVideoPlayer.tsx @@ -7,6 +7,7 @@ import React, {useCallback, useEffect, useLayoutEffect, useMemo, useRef, useStat import type {GestureResponderEvent} from 'react-native'; import {View} from 'react-native'; import {runOnJS, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; +import {scheduleOnRN} from 'react-native-worklets'; import AttachmentOfflineIndicator from '@components/AttachmentOfflineIndicator'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import Hoverable from '@components/Hoverable'; @@ -123,7 +124,7 @@ function BaseVideoPlayer({ return; } - controlsOpacity.set(withTiming(0, {duration: 500}, () => runOnJS(setControlStatusState)(CONST.VIDEO_PLAYER.CONTROLS_STATUS.HIDE))); + controlsOpacity.set(withTiming(0, {duration: 500}, () => scheduleOnRN(setControlStatusState, CONST.VIDEO_PLAYER.CONTROLS_STATUS.HIDE))); }, [controlsOpacity, isEnded]); const debouncedHideControl = useMemo(() => debounce(hideControl, 1500), [hideControl]); From 58a8dc5e0cffb70c84207698ba7ae756b1aa7d15 Mon Sep 17 00:00:00 2001 From: Dariusz Biela Date: Tue, 16 Dec 2025 15:58:37 +0100 Subject: [PATCH 5/8] fix: fix eslint error @typescript-eslint/no-unused-vars --- src/components/VideoPlayer/BaseVideoPlayer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/VideoPlayer/BaseVideoPlayer.tsx b/src/components/VideoPlayer/BaseVideoPlayer.tsx index 0f52346ea773..9bf512808897 100644 --- a/src/components/VideoPlayer/BaseVideoPlayer.tsx +++ b/src/components/VideoPlayer/BaseVideoPlayer.tsx @@ -6,7 +6,7 @@ import type {RefObject} from 'react'; import React, {useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState} from 'react'; import type {GestureResponderEvent} from 'react-native'; import {View} from 'react-native'; -import {runOnJS, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; +import {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; import {scheduleOnRN} from 'react-native-worklets'; import AttachmentOfflineIndicator from '@components/AttachmentOfflineIndicator'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; From 895b2bcc70cf06989c3914a3b4fee30fc30d2533 Mon Sep 17 00:00:00 2001 From: Dariusz Biela Date: Wed, 17 Dec 2025 12:29:31 +0100 Subject: [PATCH 6/8] feat: add Sentry labels to Receipt Modal header --- src/CONST/index.ts | 6 ++++++ src/components/HeaderWithBackButton/index.tsx | 2 ++ src/components/ThreeDotsMenu/index.tsx | 2 ++ src/components/ThreeDotsMenu/types.ts | 3 +++ .../routes/TransactionReceiptModalContent.tsx | 3 +++ 5 files changed, 16 insertions(+) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 5edf3d75f519..1e11d8c1ec46 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -7604,6 +7604,7 @@ const CONST = { BACK_BUTTON: 'Header-BackButton', DOWNLOAD_BUTTON: 'Header-DownloadButton', CLOSE_BUTTON: 'Header-CloseButton', + MORE_BUTTON: 'Header-MoreButton', }, VIDEO_PLAYER: { PLAY_PAUSE_BUTTON: 'VideoPlayer-PlayPauseButton', @@ -7620,6 +7621,11 @@ const CONST = { RECEIPT: { IMAGE: 'Receipt-Image', }, + RECEIPT_MODAL: { + REPLACE_RECEIPT: 'ReceiptModal-ReplaceReceipt', + DOWNLOAD_RECEIPT: 'ReceiptModal-DownloadReceipt', + DELETE_RECEIPT: 'ReceiptModal-DeleteReceipt', + }, HEADER_VIEW: { BACK_BUTTON: 'HeaderView-BackButton', DETAILS_BUTTON: 'HeaderView-DetailsButton', diff --git a/src/components/HeaderWithBackButton/index.tsx b/src/components/HeaderWithBackButton/index.tsx index 2a1e8d9d53f1..cca94635bfa0 100755 --- a/src/components/HeaderWithBackButton/index.tsx +++ b/src/components/HeaderWithBackButton/index.tsx @@ -148,6 +148,7 @@ function HeaderWithBackButton({ style={[styles.touchableButtonImage]} role={CONST.ROLE.BUTTON} accessibilityLabel={threeDotsMenuItems.at(0)?.text ?? ''} + sentryLabel={threeDotsMenuItems.at(0)?.sentryLabel} > } @@ -166,6 +167,7 @@ function HeaderWithBackButton({ shouldOverlay={shouldOverlayDots} anchorAlignment={threeDotsAnchorAlignment} shouldSetModalVisibility={shouldSetModalVisibility} + sentryLabel={CONST.SENTRY_LABEL.HEADER.MORE_BUTTON} /> ); } diff --git a/src/components/ThreeDotsMenu/index.tsx b/src/components/ThreeDotsMenu/index.tsx index 82cd8939ac76..85cdfecf82c3 100644 --- a/src/components/ThreeDotsMenu/index.tsx +++ b/src/components/ThreeDotsMenu/index.tsx @@ -44,6 +44,7 @@ function ThreeDotsMenu({ isNested = false, shouldSelfPosition = false, threeDotsMenuRef, + sentryLabel, }: ThreeDotsMenuProps) { const [modal] = useOnyx(ONYXKEYS.MODAL, {canBeMissing: true}); @@ -153,6 +154,7 @@ function ThreeDotsMenu({ role={getButtonRole(isNested)} isNested={isNested} accessibilityLabel={translate(iconTooltip)} + sentryLabel={sentryLabel} > void; isPopupMenuVisible: boolean} | null>; + + /** Label for Sentry INP tracking */ + sentryLabel?: string; }; type ThreeDotsMenuWithOptionalAnchorProps = diff --git a/src/pages/media/AttachmentModalScreen/routes/TransactionReceiptModalContent.tsx b/src/pages/media/AttachmentModalScreen/routes/TransactionReceiptModalContent.tsx index a4279b2eebcf..c3dc98b944ab 100644 --- a/src/pages/media/AttachmentModalScreen/routes/TransactionReceiptModalContent.tsx +++ b/src/pages/media/AttachmentModalScreen/routes/TransactionReceiptModalContent.tsx @@ -174,6 +174,7 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre ), }); }, + sentryLabel: CONST.SENTRY_LABEL.RECEIPT_MODAL.REPLACE_RECEIPT, }); } if ((!isOffline && allowDownload && !isLocalSource) || !!draftTransactionID) { @@ -181,6 +182,7 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre icon: icons.Download, text: translate('common.download'), onSelected: () => onDownloadAttachment({source: innerSource, file}), + sentryLabel: CONST.SENTRY_LABEL.RECEIPT_MODAL.DOWNLOAD_RECEIPT, }); } @@ -191,6 +193,7 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre text: translate('receipt.deleteReceipt'), onSelected: () => setIsDeleteReceiptConfirmModalVisible?.(true), shouldCallAfterModalHide: true, + sentryLabel: CONST.SENTRY_LABEL.RECEIPT_MODAL.DELETE_RECEIPT, }); } return menuItems; From cf221133958c1df509da424ccb825c9be83702c2 Mon Sep 17 00:00:00 2001 From: Dariusz Biela Date: Wed, 17 Dec 2025 15:06:42 +0100 Subject: [PATCH 7/8] refactor: extract WithSentryLabel type for consistent sentry label usage Create a reusable WithSentryLabel type in src/types/utils/SentryLabel.ts and update all component types to use it via intersection instead of defining sentryLabel?: string inline. Updated files: - GenericPressable/types.ts - Button/index.tsx - MenuItem.tsx - Checkbox.tsx - FloatingActionButton.tsx - FloatingReceiptButton.tsx - ContextMenuItem.tsx - BaseMiniContextMenuItem.tsx - ThreeDotsMenu/types.ts - ButtonWithDropdownMenu/types.ts - VideoPlayer/IconButton.tsx - ContextMenuActions.tsx --- src/components/BaseMiniContextMenuItem.tsx | 8 ++------ src/components/Button/index.tsx | 6 ++---- src/components/ButtonWithDropdownMenu/types.ts | 10 +++------- src/components/Checkbox.tsx | 6 ++---- src/components/ContextMenuItem.tsx | 6 ++---- src/components/FloatingActionButton.tsx | 6 ++---- src/components/FloatingReceiptButton.tsx | 6 ++---- src/components/MenuItem.tsx | 6 ++---- src/components/Pressable/GenericPressable/types.ts | 9 +++------ src/components/ThreeDotsMenu/types.ts | 6 ++---- src/components/VideoPlayer/IconButton.tsx | 4 ++-- .../home/report/ContextMenu/ContextMenuActions.tsx | 4 ++-- src/types/utils/SentryLabel.ts | 8 ++++++++ 13 files changed, 34 insertions(+), 51 deletions(-) create mode 100644 src/types/utils/SentryLabel.ts diff --git a/src/components/BaseMiniContextMenuItem.tsx b/src/components/BaseMiniContextMenuItem.tsx index c04f8436279c..23a4520eae8a 100644 --- a/src/components/BaseMiniContextMenuItem.tsx +++ b/src/components/BaseMiniContextMenuItem.tsx @@ -8,11 +8,12 @@ import getButtonState from '@libs/getButtonState'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; import variables from '@styles/variables'; import CONST from '@src/CONST'; +import type WithSentryLabel from '@src/types/utils/SentryLabel'; import type {PressableRef} from './Pressable/GenericPressable/types'; import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback'; import Tooltip from './Tooltip/PopoverAnchorTooltip'; -type BaseMiniContextMenuItemProps = { +type BaseMiniContextMenuItemProps = WithSentryLabel & { /** * Text to display when hovering the menu item */ @@ -41,11 +42,6 @@ type BaseMiniContextMenuItemProps = { * Reference to the outer element */ ref?: PressableRef; - - /** - * Label for Sentry tracking - */ - sentryLabel?: string; }; /** diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx index 87d0ccebc018..206f578644fd 100644 --- a/src/components/Button/index.tsx +++ b/src/components/Button/index.tsx @@ -19,10 +19,11 @@ import HapticFeedback from '@libs/HapticFeedback'; import CONST from '@src/CONST'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; import type IconAsset from '@src/types/utils/IconAsset'; +import type WithSentryLabel from '@src/types/utils/SentryLabel'; import {getButtonRole} from './utils'; import validateSubmitShortcut from './validateSubmitShortcut'; -type ButtonProps = Partial & { +type ButtonProps = Partial & WithSentryLabel & { /** Should the press event bubble across multiple instances when Enter key triggers it. */ allowBubble?: boolean; @@ -179,9 +180,6 @@ type ButtonProps = Partial & { * Whether the button should stay visually normal even when disabled. */ shouldStayNormalOnDisable?: boolean; - - /** Label for Sentry tracking. On web, this will be added as data-sentry-label attribute. */ - sentryLabel?: string; }; type KeyboardShortcutComponentProps = Pick; diff --git a/src/components/ButtonWithDropdownMenu/types.ts b/src/components/ButtonWithDropdownMenu/types.ts index 47458710d62e..ae479d2beff0 100644 --- a/src/components/ButtonWithDropdownMenu/types.ts +++ b/src/components/ButtonWithDropdownMenu/types.ts @@ -6,6 +6,7 @@ import type CONST from '@src/CONST'; import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; import type IconAsset from '@src/types/utils/IconAsset'; +import type WithSentryLabel from '@src/types/utils/SentryLabel'; type PaymentType = DeepValueOf; @@ -21,7 +22,7 @@ type ReportExportType = DeepValueOf; type OnboardingHelpType = DeepValueOf; -type DropdownOption = { +type DropdownOption = WithSentryLabel & { value: TValueType; text: string; icon?: IconAsset; @@ -49,11 +50,9 @@ type DropdownOption = { shouldShow?: boolean; /** Whether to show a loading spinner for this option */ shouldShowLoadingSpinnerIcon?: boolean; - /** Label for sentry to identify the dropdown option */ - sentryLabel?: string; }; -type ButtonWithDropdownMenuProps = { +type ButtonWithDropdownMenuProps = WithSentryLabel & { /** The custom text to display on the main button instead of selected option */ customText?: string; @@ -159,9 +158,6 @@ type ButtonWithDropdownMenuProps = { /** Reference to the outer element */ ref?: React.Ref; - - /** Label for the sentry to identify the button */ - sentryLabel?: string; }; type ButtonWithDropdownMenuRef = { diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx index 28bf3086eb1c..5be22b872409 100644 --- a/src/components/Checkbox.tsx +++ b/src/components/Checkbox.tsx @@ -7,12 +7,13 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; +import type WithSentryLabel from '@src/types/utils/SentryLabel'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; import type {PressableRef} from './Pressable/GenericPressable/types'; import PressableWithFeedback from './Pressable/PressableWithFeedback'; -type CheckboxProps = Partial & { +type CheckboxProps = Partial & WithSentryLabel & { /** Whether checkbox is checked */ isChecked?: boolean; @@ -63,9 +64,6 @@ type CheckboxProps = Partial & { /** Reference to the outer element */ ref?: ForwardedRef; - - /** Label for Sentry tracking. On web, this will be added as data-sentry-label attribute. */ - sentryLabel?: string; }; function Checkbox({ diff --git a/src/components/ContextMenuItem.tsx b/src/components/ContextMenuItem.tsx index c9da9ff6fa95..125856bfb1d1 100644 --- a/src/components/ContextMenuItem.tsx +++ b/src/components/ContextMenuItem.tsx @@ -7,11 +7,12 @@ import useThrottledButtonState from '@hooks/useThrottledButtonState'; import useWindowDimensions from '@hooks/useWindowDimensions'; import getButtonState from '@libs/getButtonState'; import type IconAsset from '@src/types/utils/IconAsset'; +import type WithSentryLabel from '@src/types/utils/SentryLabel'; import BaseMiniContextMenuItem from './BaseMiniContextMenuItem'; import FocusableMenuItem from './FocusableMenuItem'; import Icon from './Icon'; -type ContextMenuItemProps = { +type ContextMenuItemProps = WithSentryLabel & { /** Icon Component */ icon: IconAsset; @@ -64,9 +65,6 @@ type ContextMenuItemProps = { /** Reference to the outer element */ ref?: ForwardedRef; - - /** Label for Sentry tracking */ - sentryLabel?: string; }; type ContextMenuItemHandle = { diff --git a/src/components/FloatingActionButton.tsx b/src/components/FloatingActionButton.tsx index 29e9be922309..783fe383530a 100644 --- a/src/components/FloatingActionButton.tsx +++ b/src/components/FloatingActionButton.tsx @@ -12,6 +12,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {canUseTouchScreen} from '@libs/DeviceCapabilities'; import variables from '@styles/variables'; import CONST from '@src/CONST'; +import type WithSentryLabel from '@src/types/utils/SentryLabel'; import Icon from './Icon'; import {PlusCircle} from './Icon/Expensicons'; import {PressableWithFeedback, PressableWithoutFeedback} from './Pressable'; @@ -24,7 +25,7 @@ const SMALL_FAB_PATH = const AnimatedPath = Animated.createAnimatedComponent(Path); -type FloatingActionButtonProps = { +type FloatingActionButtonProps = WithSentryLabel & { /* Callback to fire on request to toggle the FloatingActionButton */ onPress: (event: GestureResponderEvent | KeyboardEvent | undefined) => void; @@ -42,9 +43,6 @@ type FloatingActionButtonProps = { /** Reference to the outer element */ ref?: ForwardedRef; - - /** Label for Sentry INP tracking */ - sentryLabel?: string; }; function FloatingActionButton({onPress, onLongPress, isActive, accessibilityLabel, role, ref, sentryLabel}: FloatingActionButtonProps) { diff --git a/src/components/FloatingReceiptButton.tsx b/src/components/FloatingReceiptButton.tsx index 1e72d9e555df..decb513f0015 100644 --- a/src/components/FloatingReceiptButton.tsx +++ b/src/components/FloatingReceiptButton.tsx @@ -7,12 +7,13 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {canUseTouchScreen} from '@libs/DeviceCapabilities'; import variables from '@styles/variables'; +import type WithSentryLabel from '@src/types/utils/SentryLabel'; import Icon from './Icon'; import {ReceiptPlus} from './Icon/Expensicons'; import {PressableWithoutFeedback} from './Pressable'; import Tooltip from './Tooltip'; -type FloatingReceiptButtonProps = { +type FloatingReceiptButtonProps = WithSentryLabel & { /* Callback to fire on request to toggle the FloatingReceiptButton */ onPress: (event: GestureResponderEvent | KeyboardEvent | undefined) => void; @@ -21,9 +22,6 @@ type FloatingReceiptButtonProps = { /* An accessibility role for the button */ role: Role; - - /** Label for Sentry INP tracking */ - sentryLabel?: string; }; function FloatingReceiptButton({onPress, accessibilityLabel, role, sentryLabel}: FloatingReceiptButtonProps) { diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 261a7cda60cc..2b50c3366df5 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -25,6 +25,7 @@ import CONST from '@src/CONST'; import type {Icon as IconType} from '@src/types/onyx/OnyxCommon'; import type {TooltipAnchorAlignment} from '@src/types/utils/AnchorAlignment'; import type IconAsset from '@src/types/utils/IconAsset'; +import type WithSentryLabel from '@src/types/utils/SentryLabel'; import ActivityIndicator from './ActivityIndicator'; import Avatar from './Avatar'; import Badge from './Badge'; @@ -65,7 +66,7 @@ type NoIcon = { icon?: undefined; }; -type MenuItemBaseProps = ForwardedFSClassProps & { +type MenuItemBaseProps = ForwardedFSClassProps & WithSentryLabel & { /** Reference to the outer element */ ref?: PressableRef | Ref; @@ -394,9 +395,6 @@ type MenuItemBaseProps = ForwardedFSClassProps & { /** Whether the screen containing the item is focused */ isFocused?: boolean; - - /** Label for Sentry tracking */ - sentryLabel?: string; }; type MenuItemProps = (IconProps | AvatarProps | NoIcon) & MenuItemBaseProps; diff --git a/src/components/Pressable/GenericPressable/types.ts b/src/components/Pressable/GenericPressable/types.ts index cdd0505d4aca..44968328e0ec 100644 --- a/src/components/Pressable/GenericPressable/types.ts +++ b/src/components/Pressable/GenericPressable/types.ts @@ -5,6 +5,7 @@ import type {ValueOf} from 'type-fest'; import type {ForwardedFSClassProps} from '@libs/Fullstory/types'; import type {Shortcut} from '@libs/KeyboardShortcut'; import type CONST from '@src/CONST'; +import type WithSentryLabel from '@src/types/utils/SentryLabel'; type StylePropWithFunction = StyleProp | ((state: PressableStateCallbackType) => StyleProp); @@ -39,7 +40,8 @@ type RequiredAccessibilityLabel = type PressableProps = RNPressableProps & RequiredAccessibilityLabel & - ForwardedFSClassProps & { + ForwardedFSClassProps & + WithSentryLabel & { /** * onPress callback */ @@ -156,11 +158,6 @@ type PressableProps = RNPressableProps & */ isNested?: boolean; - /** - * Label for Sentry tracking. On web, this will be added as data-sentry-label attribute. - */ - sentryLabel?: string; - /** * Reference to the outer element. */ diff --git a/src/components/ThreeDotsMenu/types.ts b/src/components/ThreeDotsMenu/types.ts index 61b63179990e..6617d65b4771 100644 --- a/src/components/ThreeDotsMenu/types.ts +++ b/src/components/ThreeDotsMenu/types.ts @@ -4,8 +4,9 @@ import type {TranslationPaths} from '@src/languages/types'; import type {AnchorPosition} from '@src/styles'; import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; import type IconAsset from '@src/types/utils/IconAsset'; +import type WithSentryLabel from '@src/types/utils/SentryLabel'; -type ThreeDotsMenuProps = { +type ThreeDotsMenuProps = WithSentryLabel & { /** Tooltip for the popup icon */ iconTooltip?: TranslationPaths; @@ -50,9 +51,6 @@ type ThreeDotsMenuProps = { /** Ref to the menu */ threeDotsMenuRef?: React.RefObject<{hidePopoverMenu: () => void; isPopupMenuVisible: boolean} | null>; - - /** Label for Sentry INP tracking */ - sentryLabel?: string; }; type ThreeDotsMenuWithOptionalAnchorProps = diff --git a/src/components/VideoPlayer/IconButton.tsx b/src/components/VideoPlayer/IconButton.tsx index 15856664982c..a2af11c083c6 100644 --- a/src/components/VideoPlayer/IconButton.tsx +++ b/src/components/VideoPlayer/IconButton.tsx @@ -6,8 +6,9 @@ import Tooltip from '@components/Tooltip'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; import type IconAsset from '@src/types/utils/IconAsset'; +import type WithSentryLabel from '@src/types/utils/SentryLabel'; -type IconButtonProps = { +type IconButtonProps = WithSentryLabel & { src: IconAsset; onPress?: (event?: GestureResponderEvent | KeyboardEvent) => void | Promise; fill?: string; @@ -16,7 +17,6 @@ type IconButtonProps = { hoverStyle?: StyleProp; small?: boolean; shouldForceRenderingTooltipBelow?: boolean; - sentryLabel?: string; }; function IconButton({src, fill = 'white', onPress, style, hoverStyle, tooltipText = '', small = false, shouldForceRenderingTooltipBelow = false, sentryLabel}: IconButtonProps) { diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index ab5856111899..bfd8ca5f1d85 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -150,6 +150,7 @@ import type {TranslationPaths} from '@src/languages/types'; import ROUTES from '@src/ROUTES'; import type {Beta, Card, Download as DownloadOnyx, OnyxInputOrEntry, Policy, PolicyTagLists, ReportAction, ReportActionReactions, Report as ReportType, Transaction} from '@src/types/onyx'; import type IconAsset from '@src/types/utils/IconAsset'; +import type WithSentryLabel from '@src/types/utils/SentryLabel'; import KeyboardUtils from '@src/utils/keyboard'; import type {ContextMenuAnchor} from './ReportActionContextMenu'; import {hideContextMenu, showDeleteModal} from './ReportActionContextMenu'; @@ -242,7 +243,7 @@ type ContextMenuActionWithContent = { renderContent: RenderContent; }; -type ContextMenuActionWithIcon = { +type ContextMenuActionWithIcon = WithSentryLabel & { textTranslateKey: TranslationPaths; icon: | IconAsset @@ -273,7 +274,6 @@ type ContextMenuActionWithIcon = { >; onPress: OnPress; getDescription: GetDescription; - sentryLabel?: string; }; type ContextMenuAction = (ContextMenuActionWithContent | ContextMenuActionWithIcon) & { diff --git a/src/types/utils/SentryLabel.ts b/src/types/utils/SentryLabel.ts new file mode 100644 index 000000000000..a452e3e9469f --- /dev/null +++ b/src/types/utils/SentryLabel.ts @@ -0,0 +1,8 @@ +/** + * Label for Sentry tracking. On web, this will be added as data-sentry-label attribute. + */ +type WithSentryLabel = { + sentryLabel?: string; +}; + +export default WithSentryLabel; From fc1d833dfea4dad523721e92b0a6ec308dd9b171 Mon Sep 17 00:00:00 2001 From: Dariusz Biela Date: Wed, 17 Dec 2025 16:18:22 +0100 Subject: [PATCH 8/8] refactor: fix prettier errors --- src/components/Button/index.tsx | 219 ++++++++-------- src/components/Checkbox.tsx | 73 +++--- src/components/MenuItem.tsx | 441 ++++++++++++++++---------------- 3 files changed, 368 insertions(+), 365 deletions(-) diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx index 206f578644fd..265463dcc463 100644 --- a/src/components/Button/index.tsx +++ b/src/components/Button/index.tsx @@ -23,164 +23,165 @@ import type WithSentryLabel from '@src/types/utils/SentryLabel'; import {getButtonRole} from './utils'; import validateSubmitShortcut from './validateSubmitShortcut'; -type ButtonProps = Partial & WithSentryLabel & { - /** Should the press event bubble across multiple instances when Enter key triggers it. */ - allowBubble?: boolean; +type ButtonProps = Partial & + WithSentryLabel & { + /** Should the press event bubble across multiple instances when Enter key triggers it. */ + allowBubble?: boolean; - /** The icon asset to display to the right of the text */ - iconRight?: IconAsset; + /** The icon asset to display to the right of the text */ + iconRight?: IconAsset; - /** The fill color to pass into the icon. */ - iconFill?: string; + /** The fill color to pass into the icon. */ + iconFill?: string; - /** The fill color to pass into the icon when the button is hovered. */ - iconHoverFill?: string; + /** The fill color to pass into the icon when the button is hovered. */ + iconHoverFill?: string; - /** Any additional styles to pass to the left icon container. */ - iconStyles?: StyleProp; + /** Any additional styles to pass to the left icon container. */ + iconStyles?: StyleProp; - /** Any additional styles to pass to the right icon container. */ - iconRightStyles?: StyleProp; + /** Any additional styles to pass to the right icon container. */ + iconRightStyles?: StyleProp; - /** Any additional styles to pass to the icon wrapper container. */ - iconWrapperStyles?: StyleProp; + /** Any additional styles to pass to the icon wrapper container. */ + iconWrapperStyles?: StyleProp; - /** Extra-small sized button */ - extraSmall?: boolean; + /** Extra-small sized button */ + extraSmall?: boolean; - /** Small sized button */ - small?: boolean; + /** Small sized button */ + small?: boolean; - /** Large sized button */ - large?: boolean; + /** Large sized button */ + large?: boolean; - /** Medium sized button */ - medium?: boolean; + /** Medium sized button */ + medium?: boolean; - /** Indicates whether the button should be disabled and in the loading state */ - isLoading?: boolean; + /** Indicates whether the button should be disabled and in the loading state */ + isLoading?: boolean; - /** Indicates whether the button should be disabled */ - isDisabled?: boolean; + /** Indicates whether the button should be disabled */ + isDisabled?: boolean; - /** Invoked on mount and layout changes */ - onLayout?: (event: LayoutChangeEvent) => void; + /** Invoked on mount and layout changes */ + onLayout?: (event: LayoutChangeEvent) => void; - /** A function that is called when the button is clicked on */ - onPress?: (event?: GestureResponderEvent | KeyboardEvent) => void | Promise; + /** A function that is called when the button is clicked on */ + onPress?: (event?: GestureResponderEvent | KeyboardEvent) => void | Promise; - /** A function that is called when the button is long pressed */ - onLongPress?: (event?: GestureResponderEvent) => void; + /** A function that is called when the button is long pressed */ + onLongPress?: (event?: GestureResponderEvent) => void; - /** A function that is called when the button is pressed */ - onPressIn?: (event: GestureResponderEvent) => void; + /** A function that is called when the button is pressed */ + onPressIn?: (event: GestureResponderEvent) => void; - /** A function that is called when the button is released */ - onPressOut?: (event: GestureResponderEvent) => void; + /** A function that is called when the button is released */ + onPressOut?: (event: GestureResponderEvent) => void; - /** Callback that is called when mousedown is triggered. */ - onMouseDown?: (e: React.MouseEvent) => void; + /** Callback that is called when mousedown is triggered. */ + onMouseDown?: (e: React.MouseEvent) => void; - /** Call the onPress function when Enter key is pressed */ - pressOnEnter?: boolean; + /** Call the onPress function when Enter key is pressed */ + pressOnEnter?: boolean; - /** The priority to assign the enter key event listener. 0 is the highest priority. */ - enterKeyEventListenerPriority?: number; + /** The priority to assign the enter key event listener. 0 is the highest priority. */ + enterKeyEventListenerPriority?: number; - /** Additional styles to add after local styles. Applied to Pressable portion of button */ - style?: StyleProp; + /** Additional styles to add after local styles. Applied to Pressable portion of button */ + style?: StyleProp; - /** Additional styles to add to the component when it's disabled */ - disabledStyle?: StyleProp; + /** Additional styles to add to the component when it's disabled */ + disabledStyle?: StyleProp; - /** Additional button styles. Specific to the OpacityView of the button */ - innerStyles?: StyleProp; + /** Additional button styles. Specific to the OpacityView of the button */ + innerStyles?: StyleProp; - /** Additional text styles */ - textStyles?: StyleProp; + /** Additional text styles */ + textStyles?: StyleProp; - /** Additional text styles when the button is hovered */ - textHoverStyles?: StyleProp; + /** Additional text styles when the button is hovered */ + textHoverStyles?: StyleProp; - /** The number of lines to display for the primary text */ - primaryTextNumberOfLines?: number; + /** The number of lines to display for the primary text */ + primaryTextNumberOfLines?: number; - /** Whether we should use the default hover style */ - shouldUseDefaultHover?: boolean; + /** Whether we should use the default hover style */ + shouldUseDefaultHover?: boolean; - /** Additional hover styles */ - hoverStyles?: StyleProp; + /** Additional hover styles */ + hoverStyles?: StyleProp; - /** Whether we should use the success theme color */ - success?: boolean; + /** Whether we should use the success theme color */ + success?: boolean; - /** Whether we should use the danger theme color */ - danger?: boolean; + /** Whether we should use the danger theme color */ + danger?: boolean; - /** Whether we should display the button as a link */ - link?: boolean; + /** Whether we should display the button as a link */ + link?: boolean; - /** Should we remove the right border radius top + bottom? */ - shouldRemoveRightBorderRadius?: boolean; + /** Should we remove the right border radius top + bottom? */ + shouldRemoveRightBorderRadius?: boolean; - /** Should we remove the left border radius top + bottom? */ - shouldRemoveLeftBorderRadius?: boolean; + /** Should we remove the left border radius top + bottom? */ + shouldRemoveLeftBorderRadius?: boolean; - /** Should enable the haptic feedback? */ - shouldEnableHapticFeedback?: boolean; + /** Should enable the haptic feedback? */ + shouldEnableHapticFeedback?: boolean; - /** Should disable the long press? */ - isLongPressDisabled?: boolean; + /** Should disable the long press? */ + isLongPressDisabled?: boolean; - /** Id to use for this button */ - id?: string; + /** Id to use for this button */ + id?: string; - /** Accessibility label for the component */ - accessibilityLabel?: string; + /** Accessibility label for the component */ + accessibilityLabel?: string; - /** The icon asset to display to the left of the text */ - icon?: IconAsset | null; + /** The icon asset to display to the left of the text */ + icon?: IconAsset | null; - /** The text for the button label */ - text?: string; + /** The text for the button label */ + text?: string; - /** Boolean whether to display the right icon */ - shouldShowRightIcon?: boolean; + /** Boolean whether to display the right icon */ + shouldShowRightIcon?: boolean; - /** Whether the button should use split style or not */ - isSplitButton?: boolean; + /** Whether the button should use split style or not */ + isSplitButton?: boolean; - /** Whether button's content should be centered */ - isContentCentered?: boolean; + /** Whether button's content should be centered */ + isContentCentered?: boolean; - /** Whether the Enter keyboard listening is active whether or not the screen that contains the button is focused */ - isPressOnEnterActive?: boolean; + /** Whether the Enter keyboard listening is active whether or not the screen that contains the button is focused */ + isPressOnEnterActive?: boolean; - /** The testID of the button. Used to locate this view in end-to-end tests. */ - testID?: string; + /** The testID of the button. Used to locate this view in end-to-end tests. */ + testID?: string; - /** Whether is a nested button inside other button, since nesting buttons isn't valid html */ - isNested?: boolean; + /** Whether is a nested button inside other button, since nesting buttons isn't valid html */ + isNested?: boolean; - /** The text displays under the first line */ - secondLineText?: string; + /** The text displays under the first line */ + secondLineText?: string; - /** - * Whether the button should have a background layer in the color of theme.appBG. - * This is needed for buttons that allow content to display under them. - */ - shouldBlendOpacity?: boolean; + /** + * Whether the button should have a background layer in the color of theme.appBG. + * This is needed for buttons that allow content to display under them. + */ + shouldBlendOpacity?: boolean; - /** - * Reference to the outer element. - */ - ref?: ForwardedRef; + /** + * Reference to the outer element. + */ + ref?: ForwardedRef; - /** - * Whether the button should stay visually normal even when disabled. - */ - shouldStayNormalOnDisable?: boolean; -}; + /** + * Whether the button should stay visually normal even when disabled. + */ + shouldStayNormalOnDisable?: boolean; + }; type KeyboardShortcutComponentProps = Pick; diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx index 5be22b872409..6e05f80574c2 100644 --- a/src/components/Checkbox.tsx +++ b/src/components/Checkbox.tsx @@ -13,58 +13,59 @@ import * as Expensicons from './Icon/Expensicons'; import type {PressableRef} from './Pressable/GenericPressable/types'; import PressableWithFeedback from './Pressable/PressableWithFeedback'; -type CheckboxProps = Partial & WithSentryLabel & { - /** Whether checkbox is checked */ - isChecked?: boolean; +type CheckboxProps = Partial & + WithSentryLabel & { + /** Whether checkbox is checked */ + isChecked?: boolean; - /** Whether checkbox is in the indeterminate (“mixed”) state */ - isIndeterminate?: boolean; + /** Whether checkbox is in the indeterminate (“mixed”) state */ + isIndeterminate?: boolean; - /** A function that is called when the box/label is pressed */ - onPress: () => void; + /** A function that is called when the box/label is pressed */ + onPress: () => void; - /** Should the input be styled for errors */ - hasError?: boolean; + /** Should the input be styled for errors */ + hasError?: boolean; - /** Should the input be disabled */ - disabled?: boolean; + /** Should the input be disabled */ + disabled?: boolean; - /** Additional styles to add to checkbox button */ - style?: StyleProp; + /** Additional styles to add to checkbox button */ + style?: StyleProp; - /** Additional styles to add to checkbox container */ - containerStyle?: StyleProp; + /** Additional styles to add to checkbox container */ + containerStyle?: StyleProp; - /** Callback that is called when mousedown is triggered. */ - onMouseDown?: MouseEventHandler; + /** Callback that is called when mousedown is triggered. */ + onMouseDown?: MouseEventHandler; - /** The size of the checkbox container */ - containerSize?: number; + /** The size of the checkbox container */ + containerSize?: number; - /** The border radius of the checkbox container */ - containerBorderRadius?: number; + /** The border radius of the checkbox container */ + containerBorderRadius?: number; - /** The size of the caret (checkmark) */ - caretSize?: number; + /** The size of the caret (checkmark) */ + caretSize?: number; - /** An accessibility label for the checkbox */ - accessibilityLabel: string; + /** An accessibility label for the checkbox */ + accessibilityLabel: string; - /** stop propagation of the mouse down event */ - shouldStopMouseDownPropagation?: boolean; + /** stop propagation of the mouse down event */ + shouldStopMouseDownPropagation?: boolean; - /** Whether the checkbox should be selected when pressing Enter key */ - shouldSelectOnPressEnter?: boolean; + /** Whether the checkbox should be selected when pressing Enter key */ + shouldSelectOnPressEnter?: boolean; - /** Additional styles to add to checkbox wrapper */ - wrapperStyle?: StyleProp; + /** Additional styles to add to checkbox wrapper */ + wrapperStyle?: StyleProp; - /** Used to locate this view in end-to-end tests. */ - testID?: string; + /** Used to locate this view in end-to-end tests. */ + testID?: string; - /** Reference to the outer element */ - ref?: ForwardedRef; -}; + /** Reference to the outer element */ + ref?: ForwardedRef; + }; function Checkbox({ isChecked = false, diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 2b50c3366df5..d8837d1ad898 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -66,336 +66,337 @@ type NoIcon = { icon?: undefined; }; -type MenuItemBaseProps = ForwardedFSClassProps & WithSentryLabel & { - /** Reference to the outer element */ - ref?: PressableRef | Ref; +type MenuItemBaseProps = ForwardedFSClassProps & + WithSentryLabel & { + /** Reference to the outer element */ + ref?: PressableRef | Ref; - /** Function to fire when component is pressed */ - onPress?: (event: GestureResponderEvent | KeyboardEvent) => void | Promise; + /** Function to fire when component is pressed */ + onPress?: (event: GestureResponderEvent | KeyboardEvent) => void | Promise; - /** Whether the menu item should be interactive at all */ - interactive?: boolean; + /** Whether the menu item should be interactive at all */ + interactive?: boolean; - /** Text to be shown as badge near the right end. */ - badgeText?: string; + /** Text to be shown as badge near the right end. */ + badgeText?: string; - /** Icon to display on the left side of the badge */ - badgeIcon?: IconAsset; + /** Icon to display on the left side of the badge */ + badgeIcon?: IconAsset; - /** Whether the badge should be shown as success */ - badgeSuccess?: boolean; + /** Whether the badge should be shown as success */ + badgeSuccess?: boolean; - /** Used to apply offline styles to child text components */ - style?: StyleProp; + /** Used to apply offline styles to child text components */ + style?: StyleProp; - /** Outer wrapper styles */ - outerWrapperStyle?: StyleProp; + /** Outer wrapper styles */ + outerWrapperStyle?: StyleProp; - /** Any additional styles to apply */ - wrapperStyle?: StyleProp; + /** Any additional styles to apply */ + wrapperStyle?: StyleProp; - /** Styles to apply on the title wrapper */ - titleWrapperStyle?: StyleProp; + /** Styles to apply on the title wrapper */ + titleWrapperStyle?: StyleProp; - /** Any additional styles to apply on the outer element */ - containerStyle?: StyleProp; + /** Any additional styles to apply on the outer element */ + containerStyle?: StyleProp; - /** Used to apply styles specifically to the title */ - titleStyle?: StyleProp; + /** Used to apply styles specifically to the title */ + titleStyle?: StyleProp; - /** Any additional styles to apply on the badge element */ - badgeStyle?: ViewStyle; + /** Any additional styles to apply on the badge element */ + badgeStyle?: ViewStyle; - /** Any additional styles to apply to the label */ - labelStyle?: StyleProp; + /** Any additional styles to apply to the label */ + labelStyle?: StyleProp; - /** Additional styles to style the description text below the title */ - descriptionTextStyle?: StyleProp; + /** Additional styles to style the description text below the title */ + descriptionTextStyle?: StyleProp; - /** The fill color to pass into the icon. */ - iconFill?: string | ((isHovered: boolean) => string); + /** The fill color to pass into the icon. */ + iconFill?: string | ((isHovered: boolean) => string); - /** Secondary icon to display on the left side of component, right of the icon */ - secondaryIcon?: IconAsset; + /** Secondary icon to display on the left side of component, right of the icon */ + secondaryIcon?: IconAsset; - /** The fill color to pass into the secondary icon. */ - secondaryIconFill?: string; + /** The fill color to pass into the secondary icon. */ + secondaryIconFill?: string; - /** Whether the secondary icon should have hover style */ - isSecondaryIconHoverable?: boolean; + /** Whether the secondary icon should have hover style */ + isSecondaryIconHoverable?: boolean; - /** Icon Width */ - iconWidth?: number; + /** Icon Width */ + iconWidth?: number; - /** Icon Height */ - iconHeight?: number; + /** Icon Height */ + iconHeight?: number; - /** Any additional styles to pass to the icon container. */ - iconStyles?: StyleProp; + /** Any additional styles to pass to the icon container. */ + iconStyles?: StyleProp; - /** Additional styles to pass to the icon itself */ - additionalIconStyles?: StyleProp; + /** Additional styles to pass to the icon itself */ + additionalIconStyles?: StyleProp; - /** A fallback avatar icon to display when there is an error on loading avatar from remote URL. */ - fallbackIcon?: IconAsset; + /** A fallback avatar icon to display when there is an error on loading avatar from remote URL. */ + fallbackIcon?: IconAsset; - /** An icon to display under the main item */ - furtherDetailsIcon?: IconAsset; + /** An icon to display under the main item */ + furtherDetailsIcon?: IconAsset; - /** Boolean whether to display the title right icon */ - shouldShowTitleIcon?: boolean; + /** Boolean whether to display the title right icon */ + shouldShowTitleIcon?: boolean; - /** Icon to display at right side of title */ - titleIcon?: IconAsset; + /** Icon to display at right side of title */ + titleIcon?: IconAsset; - /** Boolean whether to display the right icon */ - shouldShowRightIcon?: boolean; + /** Boolean whether to display the right icon */ + shouldShowRightIcon?: boolean; - /** Overrides the icon for shouldShowRightIcon */ - iconRight?: IconAsset; + /** Overrides the icon for shouldShowRightIcon */ + iconRight?: IconAsset; - /** Should render component on the right */ - shouldShowRightComponent?: boolean; + /** Should render component on the right */ + shouldShowRightComponent?: boolean; - /** Component to be displayed on the right */ - rightComponent?: ReactNode; + /** Component to be displayed on the right */ + rightComponent?: ReactNode; - /** A description text to show under the title */ - description?: string; + /** A description text to show under the title */ + description?: string; - /** Text to show below menu item. This text is not interactive */ - helperText?: string; + /** Text to show below menu item. This text is not interactive */ + helperText?: string; - /** Any additional styles to pass to helper text. */ - helperTextStyle?: StyleProp; + /** Any additional styles to pass to helper text. */ + helperTextStyle?: StyleProp; - /** Should the description be shown above the title (instead of the other way around) */ - shouldShowDescriptionOnTop?: boolean; + /** Should the description be shown above the title (instead of the other way around) */ + shouldShowDescriptionOnTop?: boolean; - /** Error to display at the bottom of the component */ - errorText?: string | ReactNode; + /** Error to display at the bottom of the component */ + errorText?: string | ReactNode; - /** Any additional styles to pass to error text. */ - errorTextStyle?: StyleProp; + /** Any additional styles to pass to error text. */ + errorTextStyle?: StyleProp; - /** Hint to display at the bottom of the component */ - hintText?: string | ReactNode; + /** Hint to display at the bottom of the component */ + hintText?: string | ReactNode; - /** Should the error text red dot indicator be shown */ - shouldShowRedDotIndicator?: boolean; + /** Should the error text red dot indicator be shown */ + shouldShowRedDotIndicator?: boolean; - /** A boolean flag that gives the icon a green fill if true */ - success?: boolean; + /** A boolean flag that gives the icon a green fill if true */ + success?: boolean; - /** Whether item is focused or active */ - focused?: boolean; + /** Whether item is focused or active */ + focused?: boolean; - /** Should we disable this menu item? */ - disabled?: boolean; + /** Should we disable this menu item? */ + disabled?: boolean; - /** Text that appears above the title */ - label?: string; + /** Text that appears above the title */ + label?: string; - /** Character limit after which the menu item text will be truncated */ - characterLimit?: number; + /** Character limit after which the menu item text will be truncated */ + characterLimit?: number; - isLabelHoverable?: boolean; + isLabelHoverable?: boolean; - /** Label to be displayed on the right */ - rightLabel?: string; + /** Label to be displayed on the right */ + rightLabel?: string; - /** Text to display for the item */ - title?: string; + /** Text to display for the item */ + title?: string; - /** Component to display as the title */ - titleComponent?: ReactElement; + /** Component to display as the title */ + titleComponent?: ReactElement; - /** Any additional styles to apply to the container for title components */ - titleContainerStyle?: StyleProp; + /** Any additional styles to apply to the container for title components */ + titleContainerStyle?: StyleProp; - /** A right-aligned subtitle for this menu option */ - subtitle?: string | number; + /** A right-aligned subtitle for this menu option */ + subtitle?: string | number; - /** Should the title show with normal font weight (not bold) */ - shouldShowBasicTitle?: boolean; + /** Should the title show with normal font weight (not bold) */ + shouldShowBasicTitle?: boolean; - /** Should we make this selectable with a checkbox */ - shouldShowSelectedState?: boolean; + /** Should we make this selectable with a checkbox */ + shouldShowSelectedState?: boolean; - /** Should we truncate the title */ - shouldTruncateTitle?: boolean; + /** Should we truncate the title */ + shouldTruncateTitle?: boolean; - /** Whether this item is selected */ - isSelected?: boolean; + /** Whether this item is selected */ + isSelected?: boolean; - /** Prop to identify if we should load avatars vertically instead of diagonally */ - shouldStackHorizontally?: boolean; + /** Prop to identify if we should load avatars vertically instead of diagonally */ + shouldStackHorizontally?: boolean; - /** Prop to represent the size of the avatar images to be shown */ - avatarSize?: ValueOf; + /** Prop to represent the size of the avatar images to be shown */ + avatarSize?: ValueOf; - /** Affects avatar size */ - viewMode?: ValueOf; + /** Affects avatar size */ + viewMode?: ValueOf; - /** Used to truncate the text with an ellipsis after computing the text layout */ - numberOfLinesTitle?: number; + /** Used to truncate the text with an ellipsis after computing the text layout */ + numberOfLinesTitle?: number; - /** Used to truncate the description with an ellipsis after computing the text layout */ - numberOfLinesDescription?: number; + /** Used to truncate the description with an ellipsis after computing the text layout */ + numberOfLinesDescription?: number; - /** Whether we should use small avatar subscript sizing the for menu item */ - isSmallAvatarSubscriptMenu?: boolean; + /** Whether we should use small avatar subscript sizing the for menu item */ + isSmallAvatarSubscriptMenu?: boolean; - /** The type of brick road indicator to show. */ - brickRoadIndicator?: ValueOf; + /** The type of brick road indicator to show. */ + brickRoadIndicator?: ValueOf; - /** Should render the content in HTML format */ - shouldRenderAsHTML?: boolean; + /** Should render the content in HTML format */ + shouldRenderAsHTML?: boolean; - /** Whether or not the text should be escaped */ - shouldEscapeText?: boolean; + /** Whether or not the text should be escaped */ + shouldEscapeText?: boolean; - /** Should we grey out the menu item when it is disabled? */ - shouldGreyOutWhenDisabled?: boolean; + /** Should we grey out the menu item when it is disabled? */ + shouldGreyOutWhenDisabled?: boolean; - /** Should we remove the background color of the menu item */ - shouldRemoveBackground?: boolean; + /** Should we remove the background color of the menu item */ + shouldRemoveBackground?: boolean; - /** Should we remove the hover background color of the menu item */ - shouldRemoveHoverBackground?: boolean; + /** Should we remove the hover background color of the menu item */ + shouldRemoveHoverBackground?: boolean; - rightIconAccountID?: number | string; + rightIconAccountID?: number | string; - iconAccountID?: number; + iconAccountID?: number; - /** Should we use default cursor for disabled content */ - shouldUseDefaultCursorWhenDisabled?: boolean; + /** Should we use default cursor for disabled content */ + shouldUseDefaultCursorWhenDisabled?: boolean; - /** The action accept for anonymous user or not */ - isAnonymousAction?: boolean; + /** The action accept for anonymous user or not */ + isAnonymousAction?: boolean; - /** Flag to indicate whether or not text selection should be disabled from long-pressing the menu item. */ - shouldBlockSelection?: boolean; + /** Flag to indicate whether or not text selection should be disabled from long-pressing the menu item. */ + shouldBlockSelection?: boolean; - /** Whether should render title as HTML or as Text */ - shouldParseTitle?: boolean; + /** Whether should render title as HTML or as Text */ + shouldParseTitle?: boolean; - /** Whether should render helper text as HTML or as Text */ - shouldParseHelperText?: boolean; + /** Whether should render helper text as HTML or as Text */ + shouldParseHelperText?: boolean; - /** Whether should render hint text as HTML or as Text */ - shouldRenderHintAsHTML?: boolean; + /** Whether should render hint text as HTML or as Text */ + shouldRenderHintAsHTML?: boolean; - /** Whether should render error text as HTML or as Text */ - shouldRenderErrorAsHTML?: boolean; + /** Whether should render error text as HTML or as Text */ + shouldRenderErrorAsHTML?: boolean; - /** List of markdown rules that will be ignored */ - excludedMarkdownRules?: string[]; + /** List of markdown rules that will be ignored */ + excludedMarkdownRules?: string[]; - /** Should check anonymous user in onPress function */ - shouldCheckActionAllowedOnPress?: boolean; + /** Should check anonymous user in onPress function */ + shouldCheckActionAllowedOnPress?: boolean; - /** Text to display under the main item */ - furtherDetails?: string; + /** Text to display under the main item */ + furtherDetails?: string; - /** The maximum number of lines for further details text */ - furtherDetailsNumberOfLines?: number; + /** The maximum number of lines for further details text */ + furtherDetailsNumberOfLines?: number; - /** The further details additional style */ - furtherDetailsStyle?: StyleProp; + /** The further details additional style */ + furtherDetailsStyle?: StyleProp; - /** Render custom content under the main item */ - furtherDetailsComponent?: ReactElement; + /** Render custom content under the main item */ + furtherDetailsComponent?: ReactElement; - /** The function that should be called when this component is LongPressed or right-clicked. */ - onSecondaryInteraction?: (event: GestureResponderEvent | MouseEvent) => void; + /** The function that should be called when this component is LongPressed or right-clicked. */ + onSecondaryInteraction?: (event: GestureResponderEvent | MouseEvent) => void; - /** Array of objects that map display names to their corresponding tooltip */ - titleWithTooltips?: DisplayNameWithTooltip[] | undefined; + /** Array of objects that map display names to their corresponding tooltip */ + titleWithTooltips?: DisplayNameWithTooltip[] | undefined; - /** Icon should be displayed in its own color */ - displayInDefaultIconColor?: boolean; + /** Icon should be displayed in its own color */ + displayInDefaultIconColor?: boolean; - /** Determines how the icon should be resized to fit its container */ - contentFit?: ImageContentFit; + /** Determines how the icon should be resized to fit its container */ + contentFit?: ImageContentFit; - /** Is this in the Pane */ - isPaneMenu?: boolean; + /** Is this in the Pane */ + isPaneMenu?: boolean; - /** Adds padding to the left of the text when there is no icon. */ - shouldPutLeftPaddingWhenNoIcon?: boolean; + /** Adds padding to the left of the text when there is no icon. */ + shouldPutLeftPaddingWhenNoIcon?: boolean; - /** Handles what to do when the item is focused */ - onFocus?: () => void; + /** Handles what to do when the item is focused */ + onFocus?: () => void; - /** Handles what to do when the item loose focus */ - onBlur?: () => void; + /** Handles what to do when the item loose focus */ + onBlur?: () => void; - /** Optional account id if it's user avatar or policy id if it's workspace avatar */ - avatarID?: number | string; + /** Optional account id if it's user avatar or policy id if it's workspace avatar */ + avatarID?: number | string; - /** Whether to show the tooltip */ - shouldRenderTooltip?: boolean; + /** Whether to show the tooltip */ + shouldRenderTooltip?: boolean; - /** Anchor alignment of the tooltip */ - tooltipAnchorAlignment?: TooltipAnchorAlignment; + /** Anchor alignment of the tooltip */ + tooltipAnchorAlignment?: TooltipAnchorAlignment; - /** Additional styles for tooltip wrapper */ - tooltipWrapperStyle?: StyleProp; + /** Additional styles for tooltip wrapper */ + tooltipWrapperStyle?: StyleProp; - /** Any additional amount to manually adjust the horizontal position of the tooltip */ - tooltipShiftHorizontal?: number; + /** Any additional amount to manually adjust the horizontal position of the tooltip */ + tooltipShiftHorizontal?: number; - /** Any additional amount to manually adjust the vertical position of the tooltip */ - tooltipShiftVertical?: number; + /** Any additional amount to manually adjust the vertical position of the tooltip */ + tooltipShiftVertical?: number; - /** Render custom content inside the tooltip. */ - renderTooltipContent?: () => ReactNode; + /** Render custom content inside the tooltip. */ + renderTooltipContent?: () => ReactNode; - /** Callback to fire when the education tooltip is pressed */ - onEducationTooltipPress?: () => void; + /** Callback to fire when the education tooltip is pressed */ + onEducationTooltipPress?: () => void; - /** Whether the tooltip should hide on scroll */ - shouldHideOnScroll?: boolean; + /** Whether the tooltip should hide on scroll */ + shouldHideOnScroll?: boolean; - shouldShowLoadingSpinnerIcon?: boolean; + shouldShowLoadingSpinnerIcon?: boolean; - /** Should selected item be marked with checkmark */ - shouldShowSelectedItemCheck?: boolean; + /** Should selected item be marked with checkmark */ + shouldShowSelectedItemCheck?: boolean; - /** Should use auto width for the icon container. */ - shouldIconUseAutoWidthStyle?: boolean; + /** Should use auto width for the icon container. */ + shouldIconUseAutoWidthStyle?: boolean; - /** Should break word for room title */ - shouldBreakWord?: boolean; + /** Should break word for room title */ + shouldBreakWord?: boolean; - /** Pressable component Test ID. Used to locate the component in tests. */ - pressableTestID?: string; + /** Pressable component Test ID. Used to locate the component in tests. */ + pressableTestID?: string; - /** Whether to teleport the portal to the modal layer */ - shouldTeleportPortalToModalLayer?: boolean; + /** 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 `copyable=true`. Default value is `title` prop. */ - copyValue?: string; + /** 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 */ - copyable?: boolean; + /** Should enable copy to clipboard action */ + copyable?: boolean; - /** Plaid image for the bank */ - plaidUrl?: string; + /** Plaid image for the bank */ + plaidUrl?: string; - /** Report ID for the avatar */ - iconReportID?: string; + /** Report ID for the avatar */ + iconReportID?: string; - /** Report ID for the avatar on the right */ - rightIconReportID?: string; + /** Report ID for the avatar on the right */ + rightIconReportID?: string; - /** Whether the menu item contains nested submenu items. */ - hasSubMenuItems?: boolean; + /** Whether the menu item contains nested submenu items. */ + hasSubMenuItems?: boolean; - /** Whether the screen containing the item is focused */ - isFocused?: boolean; -}; + /** Whether the screen containing the item is focused */ + isFocused?: boolean; + }; type MenuItemProps = (IconProps | AvatarProps | NoIcon) & MenuItemBaseProps;