diff --git a/src/components/AnimatedSubmitButton/index.tsx b/src/components/AnimatedSubmitButton/index.tsx index 73f141cab74b..7e7f86714c41 100644 --- a/src/components/AnimatedSubmitButton/index.tsx +++ b/src/components/AnimatedSubmitButton/index.tsx @@ -1,4 +1,4 @@ -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; @@ -22,28 +22,28 @@ import Animated, {Keyframe, useAnimatedStyle, useSharedValue, withTiming} from ' import {scheduleOnRN} from 'react-native-worklets'; type AnimatedSubmitButtonProps = WithSentryLabel & { - // Whether to show the success state - success: boolean | undefined; + /** Submit buttons support the default and success styles; danger is not a valid submit state. */ + variant?: typeof CONST.BUTTON_VARIANT.SUCCESS; - // Text to show on the button + /** Text to show on the button */ text: string; - // Function to call when the button is pressed + /** Function to call when the button is pressed */ onPress: () => void; - // Whether the animation is running + /** Whether the animation is running */ isSubmittingAnimationRunning: boolean; - // Function to call when the animation finishes + /** Function to call when the animation finishes */ onAnimationFinish: () => void; - // Whether the button should be disabled + /** Whether the button should be disabled */ isDisabled?: boolean; - // Whether this is a DEW submission that needs backend validation before showing "Submitted" + /** Whether this is a DEW submission that needs backend validation before showing "Submitted" */ isDEWSubmission?: boolean; - // The report id for which the button is displayed + /** The report id for which the button is displayed */ reportID?: string; /** Whether to show "Mark as done" copy instead of "Submit" copy for track-intent users */ @@ -53,7 +53,7 @@ type AnimatedSubmitButtonProps = WithSentryLabel & { const pendingExpenseActionSelector = (reportMetadata: OnyxEntry) => reportMetadata?.pendingExpenseAction; function AnimatedSubmitButton({ - success, + variant, text, onPress, isSubmittingAnimationRunning, @@ -110,7 +110,6 @@ function AnimatedSubmitButton({ [buttonDuration, stretchOutY], ); const icons = useMemoizedLazyExpensifyIcons(['Send']); - const icon = isAnimationRunning ? icons.Send : null; useEffect(() => { if (!isAnimationRunning) { @@ -159,6 +158,7 @@ function AnimatedSubmitButton({ // eslint-disable-next-line react-hooks/refs const showLoading = isShowingLoading || (isAnimationRunning && (!viewRef.current || (isDEWSubmission && !isDEWSubmissionComplete))); + const shouldShowIcon = isAnimationRunning && !showLoading; return ( @@ -170,24 +170,25 @@ function AnimatedSubmitButton({ exiting={buttonAnimation} > )} {!isAnimationRunning && ( )} ); diff --git a/src/components/Attachments/AttachmentCarousel/CarouselButtons.tsx b/src/components/Attachments/AttachmentCarousel/CarouselButtons.tsx index 39f19ec78db0..84ef71f518e2 100644 --- a/src/components/Attachments/AttachmentCarousel/CarouselButtons.tsx +++ b/src/components/Attachments/AttachmentCarousel/CarouselButtons.tsx @@ -1,5 +1,5 @@ import type {Attachment} from '@components/Attachments/types'; -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import Tooltip from '@components/Tooltip'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; @@ -51,15 +51,19 @@ function CarouselButtons({page, attachments, shouldShowArrows, onBack, onForward )} @@ -67,15 +71,19 @@ function CarouselButtons({page, attachments, shouldShowArrows, onBack, onForward )} diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.tsx b/src/components/Attachments/AttachmentCarousel/CarouselItem.tsx index b453f7c8cfff..cdc1162700fb 100644 --- a/src/components/Attachments/AttachmentCarousel/CarouselItem.tsx +++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.tsx @@ -1,6 +1,6 @@ import AttachmentView from '@components/Attachments/AttachmentView'; import type {Attachment} from '@components/Attachments/types'; -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; import SafeAreaConsumer from '@components/SafeAreaConsumer'; import Text from '@components/Text'; @@ -48,8 +48,10 @@ function CarouselItem({item, onPress, isFocused, isModalHovered, reportID}: Caro const renderButton = (style: StyleProp) => ( ); } diff --git a/src/components/Domain/CopyableTextField.tsx b/src/components/Domain/CopyableTextField.tsx index b3795cc01489..069d1505936f 100644 --- a/src/components/Domain/CopyableTextField.tsx +++ b/src/components/Domain/CopyableTextField.tsx @@ -1,5 +1,5 @@ import ActivityIndicator from '@components/ActivityIndicator'; -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import CopyTextToClipboard from '@components/CopyTextToClipboard'; import Text from '@components/Text'; @@ -10,6 +10,8 @@ import useThemeStyles from '@hooks/useThemeStyles'; import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan'; +import CONST from '@src/CONST'; + import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; import React, {useState} from 'react'; @@ -71,12 +73,12 @@ function CopyableTextField({value, isLoading = false, style, textStyle, shouldDi {shouldDisplayShowMoreButton && ( )} )} diff --git a/src/components/MapView/GPSMapView.tsx b/src/components/MapView/GPSMapView.tsx index 950bf3932161..c4c7094a286e 100644 --- a/src/components/MapView/GPSMapView.tsx +++ b/src/components/MapView/GPSMapView.tsx @@ -1,4 +1,4 @@ -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import ImageSVG from '@components/ImageSVG'; import useAppFocusEvent from '@hooks/useAppFocusEvent'; @@ -319,10 +319,14 @@ function GPSMapView({accessToken, style, mapPadding, styleURL, pitchEnabled, way ) : ( diff --git a/src/components/MapView/MapView.tsx b/src/components/MapView/MapView.tsx index c4e1be1d8096..3ddb3179a248 100644 --- a/src/components/MapView/MapView.tsx +++ b/src/components/MapView/MapView.tsx @@ -1,4 +1,4 @@ -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import ImageSVG from '@components/ImageSVG'; import Text from '@components/Text'; @@ -374,10 +374,14 @@ function MapView({ )} diff --git a/src/components/MapView/MapViewImpl.web.tsx b/src/components/MapView/MapViewImpl.web.tsx index 09d3ed49038d..323f6e5700ed 100644 --- a/src/components/MapView/MapViewImpl.web.tsx +++ b/src/components/MapView/MapViewImpl.web.tsx @@ -1,4 +1,4 @@ -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import 'mapbox-gl/dist/mapbox-gl.css'; import ImageSVG from '@components/ImageSVG'; @@ -335,10 +335,14 @@ function MapViewImpl({ )} diff --git a/src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx b/src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx index 8138f82278c2..ed1574f1e486 100644 --- a/src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx +++ b/src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx @@ -257,7 +257,7 @@ function SubmitPrimaryActionContent({reportID}: SubmitPrimaryActionProps) { return ( handleSubmit()} diff --git a/src/components/ReportActionItem/ChronosOOOListActions.tsx b/src/components/ReportActionItem/ChronosOOOListActions.tsx index eea23f59381f..d69e0d809bb9 100644 --- a/src/components/ReportActionItem/ChronosOOOListActions.tsx +++ b/src/components/ReportActionItem/ChronosOOOListActions.tsx @@ -1,4 +1,4 @@ -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import Text from '@components/Text'; @@ -10,7 +10,7 @@ import {getOriginalMessage} from '@libs/ReportActionsUtils'; import {removeEvent} from '@userActions/Chronos'; -import type CONST from '@src/CONST'; +import CONST from '@src/CONST'; import type ReportAction from '@src/types/onyx/ReportAction'; import React from 'react'; @@ -61,8 +61,10 @@ function ChronosOOOListActions({reportID, action}: ChronosOOOListActionsProps) { )} ); } diff --git a/src/components/SettlementButton/AnimatedSettlementButton.tsx b/src/components/SettlementButton/AnimatedSettlementButton.tsx index 6401ae99a621..2474c60ac8e0 100644 --- a/src/components/SettlementButton/AnimatedSettlementButton.tsx +++ b/src/components/SettlementButton/AnimatedSettlementButton.tsx @@ -1,4 +1,4 @@ -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; @@ -173,11 +173,12 @@ function AnimatedSettlementButton({ exiting={buttonAnimation} > )} {!isAnimationRunning && ( diff --git a/src/pages/Debug/DebugJSON.tsx b/src/pages/Debug/DebugJSON.tsx index 29814e8e2855..67ad85765de8 100644 --- a/src/pages/Debug/DebugJSON.tsx +++ b/src/pages/Debug/DebugJSON.tsx @@ -1,4 +1,4 @@ -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import ScrollView from '@components/ScrollView'; import SwipeInterceptPanResponder from '@components/SwipeInterceptPanResponder'; import Text from '@components/Text'; @@ -34,13 +34,14 @@ function DebugJSON({data}: DebugJSONProps) { > {json} diff --git a/src/pages/Debug/Report/DebugReportPage.tsx b/src/pages/Debug/Report/DebugReportPage.tsx index 5fcf434f013b..5c34f0b46706 100644 --- a/src/pages/Debug/Report/DebugReportPage.tsx +++ b/src/pages/Debug/Report/DebugReportPage.tsx @@ -1,4 +1,4 @@ -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; @@ -225,27 +225,28 @@ function DebugReportPage({ {!!message && {message}} {!!action && ( - )} ))} {!!transactionID && ( )} diff --git a/src/pages/MissingPersonalDetails/subPages/PIN.tsx b/src/pages/MissingPersonalDetails/subPages/PIN.tsx index de1f06b5ffc9..1f5caa4e596c 100644 --- a/src/pages/MissingPersonalDetails/subPages/PIN.tsx +++ b/src/pages/MissingPersonalDetails/subPages/PIN.tsx @@ -1,4 +1,4 @@ -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import FormProvider from '@components/Form/FormProvider'; import Text from '@components/Text'; import ValidateCodeInput from '@components/ValidateCodeInput'; @@ -114,12 +114,10 @@ function PIN({onNext}: CustomSubPageProps) { - diff --git a/src/pages/TransactionMerge/TransactionMergeReceipts.tsx b/src/pages/TransactionMerge/TransactionMergeReceipts.tsx index cee8c2a20521..27376e9d31bc 100644 --- a/src/pages/TransactionMerge/TransactionMergeReceipts.tsx +++ b/src/pages/TransactionMerge/TransactionMergeReceipts.tsx @@ -1,4 +1,4 @@ -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import RadioButton from '@components/RadioButton'; import ReportActionItemImage from '@components/ReportActionItem/ReportActionItemImage'; @@ -74,7 +74,6 @@ function TransactionMergeReceipts({transactions, selectedReceiptID, onSelect}: T diff --git a/src/pages/domain/DomainsListPage.tsx b/src/pages/domain/DomainsListPage.tsx index 4d7eab5ccbea..b7ac0300784c 100644 --- a/src/pages/domain/DomainsListPage.tsx +++ b/src/pages/domain/DomainsListPage.tsx @@ -1,5 +1,5 @@ import ActivityIndicator from '@components/ActivityIndicator'; -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import type {DomainRowData} from '@components/Tables/DomainListTable'; import DomainListTable from '@components/Tables/DomainListTable'; import WorkspaceListLayout from '@components/WorkspaceListLayout'; @@ -83,13 +83,14 @@ function DomainsListPage() { const headerButton = !!domainRows.length && ( ); return ( diff --git a/src/pages/inbox/report/FloatingMessageCounter.tsx b/src/pages/inbox/report/FloatingMessageCounter.tsx index 98d9989b3f74..f19df402b9dc 100644 --- a/src/pages/inbox/report/FloatingMessageCounter.tsx +++ b/src/pages/inbox/report/FloatingMessageCounter.tsx @@ -1,4 +1,4 @@ -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import Icon from '@components/Icon'; import Text from '@components/Text'; import getActionBadgeText from '@components/utils/getActionBadgeText'; @@ -8,6 +8,8 @@ import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import type {ButtonVariant} from '@styles/utils/types'; + import CONST from '@src/CONST'; import type IconAsset from '@src/types/utils/IconAsset'; @@ -19,11 +21,8 @@ import {View} from 'react-native'; import Animated, {useAnimatedStyle, useSharedValue, withSpring} from 'react-native-reanimated'; type FloatingPillButtonProps = { - /** Whether the button uses the success style */ - success: boolean; - - /** Whether the button uses the danger style */ - danger?: boolean; + /** Inner button variant */ + variant?: ButtonVariant; /** Callback when the button is pressed */ onPress?: () => void; @@ -41,16 +40,17 @@ type FloatingPillButtonProps = { textStyle?: StyleProp; }; -function FloatingPillButton({success, danger, onPress, icon, iconFill, label, textStyle}: FloatingPillButtonProps) { +function FloatingPillButton({variant, onPress, icon, iconFill, label, textStyle}: FloatingPillButtonProps) { const styles = useThemeStyles(); return ( diff --git a/src/pages/inbox/report/actionContents/ChatMessageContent.tsx b/src/pages/inbox/report/actionContents/ChatMessageContent.tsx index a2f69b60cb67..72a02fc3eea7 100644 --- a/src/pages/inbox/report/actionContents/ChatMessageContent.tsx +++ b/src/pages/inbox/report/actionContents/ChatMessageContent.tsx @@ -1,5 +1,5 @@ import {AttachmentContext} from '@components/AttachmentContext'; -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import MentionReportContext from '@components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/MentionReportContext'; import Text from '@components/Text'; @@ -88,8 +88,10 @@ function ChatMessageContent({action, policyID, reportID, originalReportID, displ /> {hasBeenFlagged && ( diff --git a/src/pages/settings/Agents/Fields/EditAgentAvatarPage.tsx b/src/pages/settings/Agents/Fields/EditAgentAvatarPage.tsx index 9166a7b33053..8490fc61d38a 100644 --- a/src/pages/settings/Agents/Fields/EditAgentAvatarPage.tsx +++ b/src/pages/settings/Agents/Fields/EditAgentAvatarPage.tsx @@ -1,7 +1,7 @@ import AttachmentPicker from '@components/AttachmentPicker'; import Avatar from '@components/Avatar'; import AvatarPageFooter from '@components/AvatarPageFooter'; -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {PressableWithFeedback} from '@components/Pressable'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -172,15 +172,16 @@ function EditAgentAvatarContent({accountID, fallbackRoute, onSave, initialPreset > {({openPicker}) => ( )} diff --git a/src/pages/settings/Profile/Avatar/AvatarPreview.tsx b/src/pages/settings/Profile/Avatar/AvatarPreview.tsx index 440defd8b5a7..840e2e47aa29 100644 --- a/src/pages/settings/Profile/Avatar/AvatarPreview.tsx +++ b/src/pages/settings/Profile/Avatar/AvatarPreview.tsx @@ -1,6 +1,6 @@ import AttachmentPicker from '@components/AttachmentPicker'; import Avatar from '@components/Avatar'; -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; import UserInitialsAvatar from '@components/UserInitialsAvatar'; @@ -149,15 +149,16 @@ function AvatarPreview({selected, isRemoved, onImageRemoved, imageData, setError if (menuItems?.length <= 1) { return ( ); } diff --git a/src/pages/settings/Subscription/CardSection/CardSection.tsx b/src/pages/settings/Subscription/CardSection/CardSection.tsx index c729b6dfab57..745f64ac5abb 100644 --- a/src/pages/settings/Subscription/CardSection/CardSection.tsx +++ b/src/pages/settings/Subscription/CardSection/CardSection.tsx @@ -249,25 +249,27 @@ function CardSection() { {isEmptyObject(defaultCard?.accountData) && } {billingStatus?.isRetryAvailable !== undefined && ( + > + {translate('subscription.cardSection.retryPaymentButton')} + )} {hasCardAuthenticatedError(privateStripeCustomerID, amountOwed) && ( + > + {translate('subscription.cardSection.authenticatePayment')} + )} {!!account?.hasPurchases && ( diff --git a/src/pages/settings/Subscription/CardSection/CardSectionButton/index.native.tsx b/src/pages/settings/Subscription/CardSection/CardSectionButton/index.native.tsx index d17d9dd8832b..da971e8ec51c 100644 --- a/src/pages/settings/Subscription/CardSection/CardSectionButton/index.native.tsx +++ b/src/pages/settings/Subscription/CardSection/CardSectionButton/index.native.tsx @@ -1,8 +1,17 @@ -import type {ButtonProps} from '@components/Button'; +import type {ButtonProps} from '@components/ButtonComposed'; +import ButtonIcon from '@components/ButtonComposed/primitives/ButtonIcon'; +import ButtonKeyboardShortcut from '@components/ButtonComposed/primitives/ButtonKeyboardShortcut'; +import ButtonText from '@components/ButtonComposed/primitives/ButtonText'; // eslint-disable-next-line @typescript-eslint/no-unused-vars -function CardSectionButton(_props: ButtonProps) { +function CardSectionButtonBase(_props: ButtonProps) { return null; } +const CardSectionButton = Object.assign(CardSectionButtonBase, { + Icon: ButtonIcon, + Text: ButtonText, + KeyboardShortcut: ButtonKeyboardShortcut, +}); + export default CardSectionButton; diff --git a/src/pages/settings/Subscription/CardSection/CardSectionButton/index.tsx b/src/pages/settings/Subscription/CardSection/CardSectionButton/index.tsx index 20d21258ac88..90835ac23c0f 100644 --- a/src/pages/settings/Subscription/CardSection/CardSectionButton/index.tsx +++ b/src/pages/settings/Subscription/CardSection/CardSectionButton/index.tsx @@ -1,10 +1,17 @@ -import type {ButtonProps} from '@components/Button'; -import Button from '@components/Button'; +import Button from '@components/ButtonComposed'; +import type {ButtonProps} from '@components/ButtonComposed'; +import ButtonIcon from '@components/ButtonComposed/primitives/ButtonIcon'; +import ButtonKeyboardShortcut from '@components/ButtonComposed/primitives/ButtonKeyboardShortcut'; +import ButtonText from '@components/ButtonComposed/primitives/ButtonText'; -import React from 'react'; - -function CardSectionButton(props: ButtonProps) { +function CardSectionButtonBase(props: ButtonProps) { return ); const onBackButtonPress = () => { diff --git a/src/pages/workspace/companyCards/DynamicWorkspaceCompanyCardDetailsPage.tsx b/src/pages/workspace/companyCards/DynamicWorkspaceCompanyCardDetailsPage.tsx index 6e9b20717e8e..95aa615c551b 100644 --- a/src/pages/workspace/companyCards/DynamicWorkspaceCompanyCardDetailsPage.tsx +++ b/src/pages/workspace/companyCards/DynamicWorkspaceCompanyCardDetailsPage.tsx @@ -216,20 +216,22 @@ function DynamicWorkspaceCompanyCardDetailsPage({route}: DynamicWorkspaceCompany {canWriteCompanyCards && ( + > + + {translate('workspace.moreFeatures.companyCards.updateCard')} + )} + > + + {translate('workspace.common.viewTransactions')} + {}} > + > + + {translate('workspace.common.viewTransactions')} + ) : ( {workspaceCardImage} @@ -371,17 +371,17 @@ function DynamicWorkspaceExpensifyCardDetailsPage({route}: DynamicWorkspaceExpen {canManageCardFreeze && isCardOpen && !isCardFrozen(card) && ( + > + + {translate('cardPage.freezeCard')} + )} - + + + {translate('workspace.common.viewTransactions')} + )}