diff --git a/src/components/Tooltip/BaseGenericTooltip/index.native.tsx b/src/components/Tooltip/BaseGenericTooltip/index.native.tsx index 3c758a66c4fa..3d948efb262d 100644 --- a/src/components/Tooltip/BaseGenericTooltip/index.native.tsx +++ b/src/components/Tooltip/BaseGenericTooltip/index.native.tsx @@ -37,6 +37,7 @@ function BaseGenericTooltip({ shouldUseOverlay = false, onHideTooltip = () => {}, shouldTeleportPortalToModalLayer = false, + isEducationTooltip = false, }: BaseGenericTooltipProps) { // The width of tooltip's inner content. Has to be undefined in the beginning // as a width of 0 will cause the content to be rendered of a width of 0, @@ -69,6 +70,7 @@ function BaseGenericTooltip({ anchorAlignment, wrapperStyle, shouldAddHorizontalPadding: false, + isEducationTooltip, }), [ StyleUtils, @@ -85,6 +87,7 @@ function BaseGenericTooltip({ shouldForceRenderingBelow, anchorAlignment, wrapperStyle, + isEducationTooltip, ], ); diff --git a/src/components/Tooltip/BaseGenericTooltip/index.tsx b/src/components/Tooltip/BaseGenericTooltip/index.tsx index 72f7085b8177..678bcf0c35b0 100644 --- a/src/components/Tooltip/BaseGenericTooltip/index.tsx +++ b/src/components/Tooltip/BaseGenericTooltip/index.tsx @@ -38,6 +38,7 @@ function BaseGenericTooltip({ }, shouldUseOverlay = false, onHideTooltip = () => {}, + isEducationTooltip = false, }: BaseGenericTooltipProps) { // The width of tooltip's inner content. Has to be undefined in the beginning // as a width of 0 will cause the content to be rendered of a width of 0, @@ -83,6 +84,7 @@ function BaseGenericTooltip({ shouldForceRenderingBelow, anchorAlignment, wrapperStyle, + isEducationTooltip, }), [ StyleUtils, @@ -99,6 +101,7 @@ function BaseGenericTooltip({ shouldForceRenderingBelow, anchorAlignment, wrapperStyle, + isEducationTooltip, ], ); diff --git a/src/components/Tooltip/BaseGenericTooltip/types.ts b/src/components/Tooltip/BaseGenericTooltip/types.ts index 8800d0629b0e..e96371734d80 100644 --- a/src/components/Tooltip/BaseGenericTooltip/types.ts +++ b/src/components/Tooltip/BaseGenericTooltip/types.ts @@ -33,6 +33,9 @@ type BaseGenericTooltipProps = { /** Whether the tooltip should teleport to the modal layer */ shouldTeleportPortalToModalLayer?: boolean; + + /** Whether it is education tooltip */ + isEducationTooltip?: boolean; } & Pick; // eslint-disable-next-line import/prefer-default-export diff --git a/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx b/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx index a51275de9870..5033cf977e58 100644 --- a/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx +++ b/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx @@ -59,6 +59,7 @@ function BaseEducationalTooltip({children, shouldRender = false, shouldHideOnNav diff --git a/src/components/Tooltip/GenericTooltip.tsx b/src/components/Tooltip/GenericTooltip.tsx index e31eda25293d..46025b504051 100644 --- a/src/components/Tooltip/GenericTooltip.tsx +++ b/src/components/Tooltip/GenericTooltip.tsx @@ -36,6 +36,7 @@ function GenericTooltip({ shouldUseOverlay: shouldUseOverlayProp = false, shouldTeleportPortalToModalLayer, shouldRender = true, + isEducationTooltip = false, }: GenericTooltipProps) { const {preferredLocale} = useLocalize(); const {windowWidth} = useWindowDimensions(); @@ -163,6 +164,7 @@ function GenericTooltip({ <> {shouldRender && isRendered && ( ReportUtils.canShowReportRecipientLocalTime(personalDetails, report, currentUserPersonalDetails.accountID) && !isComposerFullSize, + () => canShowReportRecipientLocalTime(personalDetails, report, currentUserPersonalDetails.accountID) && !isComposerFullSize, [personalDetails, report, currentUserPersonalDetails.accountID, isComposerFullSize], ); - const includesConcierge = useMemo(() => ReportUtils.chatIncludesConcierge({participants: report?.participants}), [report?.participants]); - const userBlockedFromConcierge = useMemo(() => User.isBlockedFromConcierge(blockedFromConcierge), [blockedFromConcierge]); + const includesConcierge = useMemo(() => chatIncludesConcierge({participants: report?.participants}), [report?.participants]); + const userBlockedFromConcierge = useMemo(() => isBlockedFromConciergeUserAction(blockedFromConcierge), [blockedFromConcierge]); const isBlockedFromConcierge = useMemo(() => includesConcierge && userBlockedFromConcierge, [includesConcierge, userBlockedFromConcierge]); // Placeholder to display in the chat input. @@ -288,7 +288,7 @@ function ReportActionCompose({ const newCommentTrimmed = newComment.trim(); if (attachmentFileRef.current) { - Report.addAttachment(reportID, attachmentFileRef.current, newCommentTrimmed); + addAttachmentReportActions(reportID, attachmentFileRef.current, newCommentTrimmed); attachmentFileRef.current = null; } else { Performance.markStart(CONST.TIMING.SEND_MESSAGE, {message: newCommentTrimmed}); @@ -337,10 +337,10 @@ function ReportActionCompose({ // We are returning a callback here as we want to incoke the method on unmount only useEffect( () => () => { - if (!EmojiPickerActions.isActive(report?.reportID)) { + if (!isActiveEmojiPickerAction(report?.reportID)) { return; } - EmojiPickerActions.hideEmojiPicker(); + hideEmojiPicker(); }, // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps [], @@ -348,7 +348,7 @@ function ReportActionCompose({ // When we invite someone to a room they don't have the policy object, but we still want them to be able to mention other reports they are members of, so we only check if the policyID in the report is from a workspace const isGroupPolicyReport = useMemo(() => !!report?.policyID && report.policyID !== CONST.POLICY.ID_FAKE, [report]); - const reportRecipientAcountIDs = ReportUtils.getReportRecipientAccountIDs(report, currentUserPersonalDetails.accountID); + const reportRecipientAcountIDs = getReportRecipientAccountIDs(report, currentUserPersonalDetails.accountID); const reportRecipient = personalDetails?.[reportRecipientAcountIDs[0]]; const shouldUseFocusedColor = !isBlockedFromConcierge && !disabled && isFocused; @@ -407,7 +407,7 @@ function ReportActionCompose({ const onValueChange = useCallback( (value: string) => { if (value.length === 0 && isComposerFullSize) { - Report.setIsComposerFullSize(reportID, false); + setIsComposerFullSize(reportID, false); } debouncedValidate(value); }, @@ -433,7 +433,7 @@ function ReportActionCompose({ horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM, }} - wrapperStyle={styles.reportActionComposeTooltipWrapper} + wrapperStyle={[styles.productTrainingTooltipWrapper, styles.pv2]} shiftHorizontal={variables.composerTooltipShiftHorizontal} shiftVertical={variables.composerTooltipShiftVertical + offsetTop} > @@ -492,7 +492,7 @@ function ReportActionCompose({ raiseIsScrollLikelyLayoutTriggered={raiseIsScrollLikelyLayoutTriggered} reportID={reportID} policyID={report?.policyID} - includeChronos={ReportUtils.chatIncludesChronos(report)} + includeChronos={chatIncludesChronos(report)} isGroupPolicyReport={isGroupPolicyReport} lastReportAction={lastReportAction} isMenuVisible={isMenuVisible} @@ -528,7 +528,7 @@ function ReportActionCompose({ )} - {DeviceCapabilities.canUseTouchScreen() && isMediumScreenWidth ? null : ( + {canUseTouchScreen() && isMediumScreenWidth ? null : ( { diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx index 5c082e3d50f7..2e7dc93a116f 100644 --- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx @@ -22,25 +22,25 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; -import * as QuickActionNavigation from '@libs/actions/QuickActionNavigation'; +import {createWorkspaceWithPolicyDraftAndNavigateToIt} from '@libs/actions/App'; +import {startMoneyRequest} from '@libs/actions/IOU'; +import {openExternalLink, openOldDotLink} from '@libs/actions/Link'; +import {navigateToQuickAction} from '@libs/actions/QuickActionNavigation'; +import {startNewChat} from '@libs/actions/Report'; +import {isAnonymousUser} from '@libs/actions/Session'; +import {canActionTask as canActionTaskUtils, canModifyTask as canModifyTaskUtils, completeTask} from '@libs/actions/Task'; +import {setSelfTourViewed} from '@libs/actions/Welcome'; import getIconForAction from '@libs/getIconForAction'; import interceptAnonymousUser from '@libs/interceptAnonymousUser'; import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute'; import Navigation from '@libs/Navigation/Navigation'; import type {CentralPaneName, NavigationPartialRoute, RootStackParamList} from '@libs/Navigation/types'; import {hasSeenTourSelector} from '@libs/onboardingSelectors'; -import * as PolicyUtils from '@libs/PolicyUtils'; -import * as ReportUtils from '@libs/ReportUtils'; -import * as SubscriptionUtils from '@libs/SubscriptionUtils'; +import {areAllGroupPoliciesExpenseChatDisabled, canSendInvoice as canSendInvoicePolicyUtils, shouldShowPolicy} from '@libs/PolicyUtils'; +import {canCreateRequest, generateReportID, getDisplayNameForParticipant, getIcons, getReportName, getWorkspaceChats, isArchivedReport, isPolicyExpenseChat} from '@libs/ReportUtils'; +import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import {getNavatticURL} from '@libs/TourUtils'; import variables from '@styles/variables'; -import * as App from '@userActions/App'; -import * as IOU from '@userActions/IOU'; -import * as Link from '@userActions/Link'; -import * as Report from '@userActions/Report'; -import * as Session from '@userActions/Session'; -import * as Task from '@userActions/Task'; -import * as Welcome from '@userActions/Welcome'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -184,7 +184,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl if (isEmptyObject(activePolicy) || !activePolicy?.isPolicyExpenseChatEnabled) { return {} as OnyxTypes.Report; } - const policyChatsForActivePolicy = ReportUtils.getWorkspaceChats(`${activePolicyID ?? CONST.DEFAULT_NUMBER_ID}`, [session?.accountID ?? CONST.DEFAULT_NUMBER_ID], allReports); + const policyChatsForActivePolicy = getWorkspaceChats(`${activePolicyID ?? CONST.DEFAULT_NUMBER_ID}`, [session?.accountID ?? CONST.DEFAULT_NUMBER_ID], allReports); return policyChatsForActivePolicy.length > 0 ? policyChatsForActivePolicy.at(0) : ({} as OnyxTypes.Report); }, [activePolicy, activePolicyID, session?.accountID, allReports]); const [quickActionPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${quickActionReport?.policyID}`); @@ -200,8 +200,8 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl const {isOffline} = useNetwork(); const {canUseSpotnanaTravel} = usePermissions(); - const canSendInvoice = useMemo(() => PolicyUtils.canSendInvoice(allPolicies as OnyxCollection, session?.email), [allPolicies, session?.email]); - const isValidReport = !(isEmptyObject(quickActionReport) || ReportUtils.isArchivedReport(quickActionReport, reportNameValuePairs)); + const canSendInvoice = useMemo(() => canSendInvoicePolicyUtils(allPolicies as OnyxCollection, session?.email), [allPolicies, session?.email]); + const isValidReport = !(isEmptyObject(quickActionReport) || isArchivedReport(quickActionReport, reportNameValuePairs)); const {environment} = useEnvironment(); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); const navatticURL = getNavatticURL(environment, introSelected?.choice); @@ -220,20 +220,18 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl * 2. none of the group policies they are a member of have isPolicyExpenseChatEnabled=true */ const shouldRedirectToExpensifyClassic = useMemo(() => { - return PolicyUtils.areAllGroupPoliciesExpenseChatDisabled((allPolicies as OnyxCollection) ?? {}); + return areAllGroupPoliciesExpenseChatDisabled((allPolicies as OnyxCollection) ?? {}); }, [allPolicies]); - const shouldShowNewWorkspaceButton = Object.values(allPolicies ?? {}).every( - (policy) => !PolicyUtils.shouldShowPolicy(policy as OnyxEntry, !!isOffline, session?.email), - ); + const shouldShowNewWorkspaceButton = Object.values(allPolicies ?? {}).every((policy) => !shouldShowPolicy(policy as OnyxEntry, !!isOffline, session?.email)); const quickActionAvatars = useMemo(() => { if (isValidReport) { - const avatars = ReportUtils.getIcons(quickActionReport, personalDetails); - return avatars.length <= 1 || ReportUtils.isPolicyExpenseChat(quickActionReport) ? avatars : avatars.filter((avatar) => avatar.id !== session?.accountID); + const avatars = getIcons(quickActionReport, personalDetails); + return avatars.length <= 1 || isPolicyExpenseChat(quickActionReport) ? avatars : avatars.filter((avatar) => avatar.id !== session?.accountID); } if (!isEmptyObject(policyChatForActivePolicy)) { - return ReportUtils.getIcons(policyChatForActivePolicy, personalDetails); + return getIcons(policyChatForActivePolicy, personalDetails); } return []; // Policy is needed as a dependency in order to update the shortcut details when the workspace changes @@ -245,7 +243,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl return ''; } if (quickAction?.action === CONST.QUICK_ACTIONS.SEND_MONEY && quickActionAvatars.length > 0) { - const name: string = ReportUtils.getDisplayNameForParticipant(+(quickActionAvatars.at(0)?.id ?? CONST.DEFAULT_NUMBER_ID), true) ?? ''; + const name: string = getDisplayNameForParticipant(+(quickActionAvatars.at(0)?.id ?? CONST.DEFAULT_NUMBER_ID), true) ?? ''; return translate('quickAction.paySomeone', {name}); } const titleKey = getQuickActionTitle(quickAction?.action ?? ('' as QuickActionName)); @@ -265,7 +263,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl const selectOption = useCallback( (onSelected: () => void, shouldRestrictAction: boolean) => { - if (shouldRestrictAction && quickActionReport?.policyID && SubscriptionUtils.shouldRestrictUserBillableActions(quickActionReport.policyID)) { + if (shouldRestrictAction && quickActionReport?.policyID && shouldRestrictUserBillableActions(quickActionReport.policyID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(quickActionReport.policyID)); return; } @@ -352,11 +350,11 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl setModalVisible(true); return; } - IOU.startMoneyRequest( + startMoneyRequest( CONST.IOU.TYPE.CREATE, // When starting to create an expense from the global FAB, there is not an existing report yet. A random optimistic reportID is generated and used // for all of the routes in the creation flow. - ReportUtils.generateReportID(), + generateReportID(), ); }), }, @@ -376,7 +374,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM, horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, }, - tooltipShiftHorizontal: styles.popoverMenuItem.paddingHorizontal, + tooltipShiftHorizontal: variables.quickActionTooltipShiftHorizontal, tooltipShiftVertical: styles.popoverMenuItem.paddingVertical / 2, renderTooltipContent: renderProductTrainingTooltip, tooltipWrapperStyle: styles.productTrainingTooltipWrapper, @@ -386,7 +384,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl if (quickAction?.action) { const iouType = getIouType(quickAction?.action); - if (!!iouType && !ReportUtils.canCreateRequest(quickActionReport, quickActionPolicy, iouType)) { + if (!!iouType && !canCreateRequest(quickActionReport, quickActionPolicy, iouType)) { return []; } return [ @@ -394,13 +392,13 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl ...baseQuickAction, icon: getQuickActionIcon(quickAction?.action), text: quickActionTitle, - description: !hideQABSubtitle ? ReportUtils.getReportName(quickActionReport) ?? translate('quickAction.updateDestination') : '', + description: !hideQABSubtitle ? getReportName(quickActionReport) ?? translate('quickAction.updateDestination') : '', onSelected: () => interceptAnonymousUser(() => { hideProductTrainingTooltip(); - QuickActionNavigation.navigateToQuickAction(isValidReport, `${quickActionReport?.reportID ?? CONST.DEFAULT_NUMBER_ID}`, quickAction, selectOption); + navigateToQuickAction(isValidReport, `${quickActionReport?.reportID ?? CONST.DEFAULT_NUMBER_ID}`, quickAction, selectOption); }), - shouldShowSubscriptRightAvatar: ReportUtils.isPolicyExpenseChat(quickActionReport), + shouldShowSubscriptRightAvatar: isPolicyExpenseChat(quickActionReport), }, ]; } @@ -410,13 +408,13 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl ...baseQuickAction, icon: Expensicons.ReceiptScan, text: translate('quickAction.scanReceipt'), - description: ReportUtils.getReportName(policyChatForActivePolicy), + description: getReportName(policyChatForActivePolicy), onSelected: () => interceptAnonymousUser(() => { selectOption(() => { hideProductTrainingTooltip(); - const quickActionReportID = policyChatForActivePolicy?.reportID || ReportUtils.generateReportID(); - IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.SCAN, true); + const quickActionReportID = policyChatForActivePolicy?.reportID || generateReportID(); + startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.SCAN, true); }, true); }), shouldShowSubscriptRightAvatar: true, @@ -429,7 +427,6 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl translate, quickActionAvatars, isValidReport, - styles.popoverMenuItem.paddingHorizontal, styles.popoverMenuItem.paddingVertical, styles.pt3, styles.pb2, @@ -449,8 +446,8 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl const viewTourTaskReportID = introSelected?.viewTour; const [viewTourTaskReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${viewTourTaskReportID}`); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - const canModifyTask = Task.canModifyTask(viewTourTaskReport, currentUserPersonalDetails.accountID); - const canActionTask = Task.canActionTask(viewTourTaskReport, currentUserPersonalDetails.accountID); + const canModifyTask = canModifyTaskUtils(viewTourTaskReport, currentUserPersonalDetails.accountID); + const canActionTask = canActionTaskUtils(viewTourTaskReport, currentUserPersonalDetails.accountID); return ( @@ -465,7 +462,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl { icon: Expensicons.ChatBubble, text: translate('sidebarScreen.fabNewChat'), - onSelected: () => interceptAnonymousUser(Report.startNewChat), + onSelected: () => interceptAnonymousUser(startNewChat), }, ...(canSendInvoice ? [ @@ -480,11 +477,11 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl return; } - IOU.startMoneyRequest( + startMoneyRequest( CONST.IOU.TYPE.INVOICE, // When starting to create an invoice from the global FAB, there is not an existing report yet. A random optimistic reportID is generated and used // for all of the routes in the creation flow. - ReportUtils.generateReportID(), + generateReportID(), ); }), }, @@ -508,10 +505,10 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl text: translate('tour.takeATwoMinuteTour'), description: translate('tour.exploreExpensify'), onSelected: () => { - Link.openExternalLink(navatticURL); - Welcome.setSelfTourViewed(Session.isAnonymousUser()); + openExternalLink(navatticURL); + setSelfTourViewed(isAnonymousUser()); if (viewTourTaskReport && canModifyTask && canActionTask) { - Task.completeTask(viewTourTaskReport); + completeTask(viewTourTaskReport); } }, }, @@ -527,7 +524,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl iconHeight: variables.h40, text: translate('workspace.new.newWorkspace'), description: translate('workspace.new.getTheExpensifyCardAndMore'), - onSelected: () => interceptAnonymousUser(() => App.createWorkspaceWithPolicyDraftAndNavigateToIt()), + onSelected: () => interceptAnonymousUser(() => createWorkspaceWithPolicyDraftAndNavigateToIt()), }, ] : []), @@ -541,7 +538,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu}: Fl isVisible={modalVisible} onConfirm={() => { setModalVisible(false); - Link.openOldDotLink(CONST.OLDDOT_URLS.INBOX); + openOldDotLink(CONST.OLDDOT_URLS.INBOX); }} onCancel={() => setModalVisible(false)} title={translate('sidebarScreen.redirectToExpensifyClassicModal.title')} diff --git a/src/styles/index.ts b/src/styles/index.ts index 06feb42b3fe2..dbae34f440af 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -3996,12 +3996,6 @@ const styles = (theme: ThemeColors) => ...wordBreak.breakWord, }, - reportActionComposeTooltipWrapper: { - backgroundColor: theme.tooltipHighlightBG, - paddingVertical: 8, - borderRadius: variables.componentBorderRadiusMedium, - }, - productTrainingTooltipWrapper: { backgroundColor: theme.tooltipHighlightBG, borderRadius: variables.componentBorderRadiusNormal, @@ -4009,7 +4003,7 @@ const styles = (theme: ThemeColors) => productTrainingTooltipText: { fontSize: variables.fontSizeLabel, - color: theme.textDark, + color: theme.textReversed, lineHeight: variables.lineHeightLarge, }, diff --git a/src/styles/theme/themes/light.ts b/src/styles/theme/themes/light.ts index 7be69e5461d1..e4939c750bd8 100644 --- a/src/styles/theme/themes/light.ts +++ b/src/styles/theme/themes/light.ts @@ -80,7 +80,7 @@ const lightTheme = { mentionBG: colors.blue100, ourMentionText: colors.green600, ourMentionBG: colors.green100, - tooltipHighlightBG: colors.green100, + tooltipHighlightBG: colors.green700, tooltipHighlightText: colors.green400, tooltipSupportingText: colors.productDark800, tooltipPrimaryText: colors.productDark900, diff --git a/src/styles/utils/generators/TooltipStyleUtils/index.ts b/src/styles/utils/generators/TooltipStyleUtils/index.ts index dbaf0a7fe5a6..d169b0da0f25 100644 --- a/src/styles/utils/generators/TooltipStyleUtils/index.ts +++ b/src/styles/utils/generators/TooltipStyleUtils/index.ts @@ -21,6 +21,12 @@ const POINTER_HEIGHT = 4; /** The width of a tooltip pointer */ const POINTER_WIDTH = 12; +/** The height of a education tooltip pointer */ +const EDUCATION_POINTER_HEIGHT = 8; + +/** The width of a education tooltip pointer */ +const EDUCATION_POINTER_WIDTH = 16; + type TooltipStyles = { rootWrapperStyle: ViewStyle; textStyle: TextStyle; @@ -44,6 +50,7 @@ type TooltipParams = { wrapperStyle: StyleProp; anchorAlignment?: TooltipAnchorAlignment; shouldAddHorizontalPadding?: boolean; + isEducationTooltip?: boolean; }; type TooltipAnimationProps = { @@ -98,7 +105,10 @@ const createTooltipStyleUtils: StyleUtilGenerator = ( vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM, }, wrapperStyle = {}, + isEducationTooltip = false, }) => { + const pointerWidth = isEducationTooltip ? EDUCATION_POINTER_WIDTH : POINTER_WIDTH; + const pointerHeight = isEducationTooltip ? EDUCATION_POINTER_HEIGHT : POINTER_HEIGHT; const customWrapperStyle = StyleSheet.flatten(wrapperStyle); const tooltipVerticalPadding = spacing.pv1; const tooltipHorizontalPadding = shouldAddHorizontalPadding ? spacing.ph2.paddingHorizontal * 2 : 0; @@ -128,7 +138,7 @@ const createTooltipStyleUtils: StyleUtilGenerator = ( // we'll display it beneath its wrapped component rather than above it as usual. shouldShowBelow = shouldForceRenderingBelow || - yOffset - tooltipHeight - POINTER_HEIGHT < GUTTER_WIDTH + titleBarHeight || + yOffset - tooltipHeight - pointerHeight < GUTTER_WIDTH + titleBarHeight || !!(tooltip && isOverlappingAtTop(tooltip, xOffset, yOffset, tooltipTargetWidth, tooltipTargetHeight)) || anchorAlignment.vertical === CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP; @@ -141,8 +151,8 @@ const createTooltipStyleUtils: StyleUtilGenerator = ( // and shift it to left a bit if the tooltip is positioned on the extreme right. horizontalShiftPointer = horizontalShift > 0 - ? Math.max(-horizontalShift, -(tooltipWidth / 2) + POINTER_WIDTH / 2 + variables.componentBorderRadiusSmall) - : Math.min(-horizontalShift, tooltipWidth / 2 - POINTER_WIDTH / 2 - variables.componentBorderRadiusSmall); + ? Math.max(-horizontalShift, -(tooltipWidth / 2) + pointerWidth / 2 + variables.componentBorderRadiusSmall) + : Math.min(-horizontalShift, tooltipWidth / 2 - pointerWidth / 2 - variables.componentBorderRadiusSmall); // Because it uses fixed positioning, the top-left corner of the tooltip is aligned // with the top-left corner of the window by default. @@ -154,9 +164,9 @@ const createTooltipStyleUtils: StyleUtilGenerator = ( // To shift the tooltip up, we'll give `top` a negative value. rootWrapperTop = shouldShowBelow ? // We need to shift the tooltip down below the component. So shift the tooltip down (+) by... - yOffset + tooltipTargetHeight + POINTER_HEIGHT + manualShiftVertical + yOffset + tooltipTargetHeight + pointerHeight + manualShiftVertical : // We need to shift the tooltip up above the component. So shift the tooltip up (-) by... - yOffset - (tooltipHeight + POINTER_HEIGHT) + manualShiftVertical; + yOffset - (tooltipHeight + pointerHeight) + manualShiftVertical; // By default, the pointer's top-left will align with the top-left of the tooltip wrapper. // @@ -166,7 +176,7 @@ const createTooltipStyleUtils: StyleUtilGenerator = ( // // OR if the pointer should be above the tooltip wrapper, then the pointer up (-) by the pointer's height // so that the bottom of the pointer lines up with the top of the tooltip - pointerWrapperTop = shouldShowBelow ? -POINTER_HEIGHT : tooltipHeight; + pointerWrapperTop = shouldShowBelow ? -pointerHeight : tooltipHeight; // Horizontal tooltip position: // we will use xOffset to position the tooltip relative to the Wrapped Component @@ -196,15 +206,15 @@ const createTooltipStyleUtils: StyleUtilGenerator = ( rootWrapperLeft = xOffset + horizontalShift + manualShiftHorizontal; switch (anchorAlignment.horizontal) { case CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT: - pointerWrapperLeft = POINTER_WIDTH / 2; + pointerWrapperLeft = pointerWidth / 2; break; case CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT: - pointerWrapperLeft = horizontalShiftPointer + (tooltipWidth - POINTER_WIDTH * 1.5); + pointerWrapperLeft = horizontalShiftPointer + (tooltipWidth - pointerWidth * 1.5); rootWrapperLeft += tooltipTargetWidth - tooltipWidth; break; case CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.CENTER: default: - pointerWrapperLeft = horizontalShiftPointer + (tooltipWidth / 2 - POINTER_WIDTH / 2); + pointerWrapperLeft = horizontalShiftPointer + (tooltipWidth / 2 - pointerWidth / 2); rootWrapperLeft += tooltipTargetWidth / 2 - tooltipWidth / 2; } @@ -252,9 +262,9 @@ const createTooltipStyleUtils: StyleUtilGenerator = ( height: 0, backgroundColor: theme.transparent, borderStyle: 'solid', - borderLeftWidth: POINTER_WIDTH / 2, - borderRightWidth: POINTER_WIDTH / 2, - borderTopWidth: POINTER_HEIGHT, + borderLeftWidth: pointerWidth / 2, + borderRightWidth: pointerWidth / 2, + borderTopWidth: pointerHeight, borderLeftColor: theme.transparent, borderRightColor: theme.transparent, borderTopColor: customWrapperStyle.backgroundColor ?? theme.heading, diff --git a/src/styles/variables.ts b/src/styles/variables.ts index 5379b631a73d..0dd0736d0369 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -258,12 +258,15 @@ export default { searchTypeColumnWidth: 52, - composerTooltipShiftHorizontal: 10, + composerTooltipShiftHorizontal: 4, composerTooltipShiftVertical: -10, - gbrTooltipShiftHorizontal: -20, - fabTooltipShiftHorizontal: -15, - workspaceLHNtooltipShiftHorizontal: 26, - searchFiltersTooltipShiftHorizontal: -20, + gbrTooltipShiftHorizontal: -15, + fabTooltipShiftHorizontal: -11, + workspaceLHNtooltipShiftHorizontal: 23, + searchFiltersTooltipShiftHorizontal: -25, + quickActionTooltipShiftHorizontal: 24, + savedSearchShiftHorizontal: -26, + savedSearchShiftVertical: 15, searchFiltersTooltipShiftHorizontalNarrow: -10, searchFiltersTooltipShiftVerticalNarrow: 5, bottomTabInboxTooltipShiftHorizontal: 36,