Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions src/components/ReportActionItem/ActionableItemButtons.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import {View} from 'react-native';
import type {StyleProp, TextStyle} from 'react-native';
import type {StyleProp, TextStyle, ViewStyle} from 'react-native';
import Button from '@components/Button';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
Expand All @@ -19,24 +19,31 @@ type ActionableItemButtonsProps = {
layout?: 'horizontal' | 'vertical';
shouldUseLocalization?: boolean;
primaryTextNumberOfLines?: number;
textStyles?: StyleProp<TextStyle>;
styles?: {
text?: StyleProp<TextStyle>;
button?: StyleProp<ViewStyle>;
buttonHover?: StyleProp<ViewStyle>;
container?: StyleProp<ViewStyle>;
};
};

function ActionableItemButtons(props: ActionableItemButtonsProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();

return (
<View style={[props.layout === 'horizontal' ? styles.flexRow : [styles.flexColumn, styles.alignItemsStart], styles.gap2, styles.mt2]}>
<View style={[styles.gap2, styles.mt2, props.layout === 'horizontal' ? styles.flexRow : [styles.flexColumn, styles.alignItemsStart, props.styles?.container]]}>
{props.items?.map((item) => (
<Button
key={item.key}
onPress={item.onPress}
text={props.shouldUseLocalization ? translate(item.text as TranslationPaths) : item.text}
medium
success={item.isPrimary}
innerStyles={props.styles?.button}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR introduced a bug where suggested response button text gets clipped instead of wrapping to the next line, because styles.breakWord was not applied to the button text styles. Fixed in #82113 / #83048

hoverStyles={props.styles?.buttonHover}
primaryTextNumberOfLines={props.primaryTextNumberOfLines}
textStyles={props.textStyles}
textStyles={props.styles?.text}
/>
))}
</View>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {DomUtils, parseDocument} from 'htmlparser2';
import type {Followup} from '@libs/ReportActionsUtils';
import {getReportActionMessage, isActionOfType} from '@libs/ReportActionsUtils';
import CONST from '@src/CONST';
import type {OnyxInputOrEntry, ReportAction} from '@src/types/onyx';
import type {Followup} from './ReportActionsUtils';
import {getReportActionMessage, isActionOfType} from './ReportActionsUtils';

/**
* Checks if a report action contains actionable (unresolved) followup suggestions.
Expand All @@ -22,36 +23,28 @@ function containsActionableFollowUps(reportAction: OnyxInputOrEntry<ReportAction
return !!followups && followups.length > 0;
}

// Matches a <followup-list> HTML element and its entire contents. (<followup-list><followup><followup-text>Question?</followup-text></followup></followup-list>)
const followUpListRegex = /<followup-list(\s[^>]*)?>[\s\S]*?<\/followup-list>/i;
/**
* Parses followup data from a <followup-list> HTML element.
* @param html - The HTML string to parse for <followup-list> elements
* @returns null if no <followup-list> exists, empty array [] if the followup-list has the 'selected' attribute (resolved state), or an array of followup objects if unresolved
*/
function parseFollowupsFromHtml(html: string): Followup[] | null {
const followupListMatch = html.match(followUpListRegex);
if (!followupListMatch) {
const doc = parseDocument(html);
const followupListElements = DomUtils.getElementsByTagName('followup-list', doc, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this work on native too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looked good when I was testing

if (followupListElements.length === 0) {
return null;
}

// There will be only one follow up list
const followupListHtml = followupListMatch[0];
// Matches a <followup-list> element that has the "selected" attribute (<followup-list selected>...</followup-list>).
const followUpSelectedListRegex = /<followup-list[^>]*\sselected[\s>]/i;
const hasSelectedAttribute = followUpSelectedListRegex.test(followupListHtml);
if (hasSelectedAttribute) {
const followupList = followupListElements.at(0);
if (!followupList) {
return null;
}
if (DomUtils.hasAttrib(followupList, 'selected')) {
return [];
}

const followups: Followup[] = [];
// Matches individual <followup><followup-text>...</followup-text></followup> elements
const followUpTextRegex = /<followup><followup-text>([^<]*)<\/followup-text><\/followup>/gi;
let match = followUpTextRegex.exec(followupListHtml);
while (match !== null) {
followups.push({text: match[1]});
match = followUpTextRegex.exec(followupListHtml);
}
return followups;
const followupTextElements = DomUtils.getElementsByTagName('followup-text', followupList, true);
return followupTextElements.map((el) => ({text: DomUtils.textContent(el)}));
}
export {containsActionableFollowUps, parseFollowupsFromHtml};
16 changes: 16 additions & 0 deletions src/libs/ReportActionFollowupUtils/stripFollowupListFromHtml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Used for generating preview text in LHN and other places where followups should not be displayed.
* Implemented here instead of ReportActionFollowupUtils due to circular ref
* @param html message.html from the report COMMENT actions
* @returns html with the <followup-list> element and its contents stripped out or undefined if html is undefined
*/
function stripFollowupListFromHtml(html?: string): string | undefined {
if (!html) {
return;
}
// Matches a <followup-list> HTML element and its entire contents. (<followup-list><followup><followup-text>Question?</followup-text></followup></followup-list>)
const followUpListRegex = /<followup-list(\s[^>]*)?>[\s\S]*?<\/followup-list>/i;
return html.replace(followUpListRegex, '').trim();
}

export default stripFollowupListFromHtml;
16 changes: 1 addition & 15 deletions src/libs/ReportActionsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import Parser from './Parser';
import {arePersonalDetailsMissing, getEffectiveDisplayName, getPersonalDetailByEmail, getPersonalDetailsByIDs} from './PersonalDetailsUtils';
import {getPolicy, isPolicyAdmin as isPolicyAdminPolicyUtils} from './PolicyUtils';
import stripFollowupListFromHtml from './ReportActionFollowupUtils/stripFollowupListFromHtml';
import type {getReportName, OptimisticIOUReportAction, PartialReportAction} from './ReportUtils';
import StringUtils from './StringUtils';
import {getReportFieldTypeTranslationKey} from './WorkspaceReportFieldUtils';
Expand Down Expand Up @@ -80,7 +81,7 @@
let allReportActions: OnyxCollection<ReportActions>;
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,

Check warning on line 84 in src/libs/ReportActionsUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
callback: (actions) => {
if (!actions) {
return;
Expand All @@ -92,7 +93,7 @@
let allReports: OnyxCollection<Report>;
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,

Check warning on line 96 in src/libs/ReportActionsUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
callback: (value) => {
allReports = value;
},
Expand All @@ -101,13 +102,13 @@
let isNetworkOffline = false;
Onyx.connect({
key: ONYXKEYS.NETWORK,
callback: (val) => (isNetworkOffline = val?.isOffline ?? false),

Check warning on line 105 in src/libs/ReportActionsUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
});

let deprecatedCurrentUserAccountID: number | undefined;
Onyx.connect({
key: ONYXKEYS.SESSION,
callback: (value) => {

Check warning on line 111 in src/libs/ReportActionsUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
// When signed out, value is undefined
if (!value) {
return;
Expand Down Expand Up @@ -1734,21 +1735,6 @@
];
}

/**
* Used for generating preview text in LHN and other places where followups should not be displayed.
* Implemented here instead of ReportActionFollowupUtils due to circular ref
* @param html message.html from the report COMMENT actions
* @returns html with the <followup-list> element and its contents stripped out or undefined if html is undefined
*/
function stripFollowupListFromHtml(html?: string): string | undefined {
if (!html) {
return;
}
// Matches a <followup-list> HTML element and its entire contents. (<followup-list><followup><followup-text>Question?</followup-text></followup></followup-list>)
const followUpListRegex = /<followup-list(\s[^>]*)?>[\s\S]*?<\/followup-list>/i;
return html.replace(followUpListRegex, '').trim();
}

function getReportActionHtml(reportAction: PartialReportAction): string {
return getReportActionMessage(reportAction)?.html ?? '';
}
Expand Down
49 changes: 49 additions & 0 deletions src/libs/actions/Report/SuggestedFollowup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import type {OnyxEntry} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import type {Ancestor} from '@libs/ReportUtils';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Report, ReportAction} from '@src/types/onyx';
import type {Timezone} from '@src/types/onyx/PersonalDetails';
import {addComment, buildOptimisticResolvedFollowups} from '.';

/**
* Resolves a suggested followup by posting the selected question as a comment
* and optimistically updating the HTML to mark the followup-list as resolved.
* @param report - The report where the action exists
* @param notifyReportID - The report ID to notify for new actions
* @param reportAction - The report action containing the followup-list
* @param selectedFollowup - The followup question selected by the user
* @param timezoneParam - The user's timezone
* @param ancestors - Array of ancestor reports for proper threading
*/
function resolveSuggestedFollowup(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that this is moved to seprate file, can we fully deprecate this in actions/Report.ts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oooops... done 😄

report: OnyxEntry<Report>,
notifyReportID: string | undefined,
reportAction: OnyxEntry<ReportAction>,
selectedFollowup: string,
timezoneParam: Timezone,
ancestors: Ancestor[] = [],
) {
const reportID = report?.reportID;
const reportActionID = reportAction?.reportActionID;

if (!reportID || !reportActionID) {
return;
}

const resolvedAction = buildOptimisticResolvedFollowups(reportAction);

if (!resolvedAction) {
return;
}

// Optimistically update the HTML to mark followup-list as resolved
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {
[reportActionID]: resolvedAction,
});

// Post the selected followup question as a comment
addComment(report, notifyReportID ?? reportID, ancestors, selectedFollowup, timezoneParam);
}

export default resolveSuggestedFollowup;
83 changes: 21 additions & 62 deletions src/libs/actions/Report.ts → src/libs/actions/Report/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,8 @@
import processReportIDDeeplink from '@libs/processReportIDDeeplink';
import Pusher from '@libs/Pusher';
import type {UserIsLeavingRoomEvent, UserIsTypingEvent} from '@libs/Pusher/types';
import * as ReportActionsFollowupUtils from '@libs/ReportActionsFollowupUtils';
import * as ReportActionsFollowupUtils from '@libs/ReportActionFollowupUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import {getLastVisibleAction} from '@libs/ReportActionsUtils';
import {updateTitleFieldToMatchPolicy} from '@libs/ReportTitleUtils';
import type {Ancestor, OptimisticAddCommentReportAction, OptimisticChatReport, SelfDMParameters} from '@libs/ReportUtils';
import {
Expand Down Expand Up @@ -177,6 +176,24 @@
import {getAmount, getCurrency, hasValidModifiedAmount, isOnHold, shouldClearConvertedAmount} from '@libs/TransactionUtils';
import addTrailingForwardSlash from '@libs/UrlUtils';
import Visibility from '@libs/Visibility';
import {clearByKey} from '@userActions/CachedPDFPaths';
import {setDownload} from '@userActions/Download';
import {close} from '@userActions/Modal';
import navigateFromNotification from '@userActions/navigateFromNotification';
import {getAll} from '@userActions/PersistedRequests';
import {buildAddMembersToWorkspaceOnyxData, buildRoomMembersOnyxData} from '@userActions/Policy/Member';
import {createPolicyExpenseChats} from '@userActions/Policy/Policy';
import {
createUpdateCommentMatcher,
resolveCommentDeletionConflicts,
resolveDuplicationConflictAction,
resolveEditCommentWithNewAddCommentRequest,
resolveOpenReportDuplicationConflictAction,
} from '@userActions/RequestConflictUtils';
import {isAnonymousUser} from '@userActions/Session';
import {onServerDataReady} from '@userActions/Welcome';
import {getOnboardingMessages} from '@userActions/Welcome/OnboardingFlow';
import type {OnboardingCompanySize, OnboardingMessage} from '@userActions/Welcome/OnboardingFlow';
import CONFIG from '@src/CONFIG';
import type {OnboardingAccounting} from '@src/CONST';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -212,24 +229,6 @@
import type {FileObject} from '@src/types/utils/Attachment';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import type {Dimensions} from '@src/types/utils/Layout';
import {clearByKey} from './CachedPDFPaths';
import {setDownload} from './Download';
import {close} from './Modal';
import navigateFromNotification from './navigateFromNotification';
import {getAll} from './PersistedRequests';
import {buildAddMembersToWorkspaceOnyxData, buildRoomMembersOnyxData} from './Policy/Member';
import {createPolicyExpenseChats} from './Policy/Policy';
import {
createUpdateCommentMatcher,
resolveCommentDeletionConflicts,
resolveDuplicationConflictAction,
resolveEditCommentWithNewAddCommentRequest,
resolveOpenReportDuplicationConflictAction,
} from './RequestConflictUtils';
import {isAnonymousUser} from './Session';
import {onServerDataReady} from './Welcome';
import {getOnboardingMessages} from './Welcome/OnboardingFlow';
import type {OnboardingCompanySize, OnboardingMessage} from './Welcome/OnboardingFlow';

type SubscriberCallback = (isFromCurrentUser: boolean, reportAction: ReportAction | undefined) => void;

Expand Down Expand Up @@ -282,7 +281,7 @@
/** @deprecated This value is deprecated and will be removed soon after migration. Use the email from useCurrentUserPersonalDetails hook instead. */
let deprecatedCurrentUserLogin: string | undefined;

Onyx.connect({

Check warning on line 284 in src/libs/actions/Report/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
// When signed out, val is undefined
Expand All @@ -296,7 +295,7 @@
},
});

Onyx.connect({

Check warning on line 298 in src/libs/actions/Report/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.CONCIERGE_REPORT_ID,
callback: (value) => (conciergeReportIDOnyxConnect = value),
});
Expand All @@ -304,7 +303,7 @@
// map of reportID to all reportActions for that report
const allReportActions: OnyxCollection<ReportActions> = {};

Onyx.connect({

Check warning on line 306 in src/libs/actions/Report/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
callback: (actions, key) => {
if (!key || !actions) {
Expand All @@ -316,7 +315,7 @@
});

let allReports: OnyxCollection<Report>;
Onyx.connect({

Check warning on line 318 in src/libs/actions/Report/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -325,7 +324,7 @@
});

let allPersonalDetails: OnyxEntry<PersonalDetailsList> = {};
Onyx.connect({

Check warning on line 327 in src/libs/actions/Report/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
allPersonalDetails = value ?? {};
Expand All @@ -340,7 +339,7 @@
});

let onboarding: OnyxEntry<Onboarding>;
Onyx.connect({

Check warning on line 342 in src/libs/actions/Report/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NVP_ONBOARDING,
callback: (val) => {
if (Array.isArray(val)) {
Expand Down Expand Up @@ -555,6 +554,7 @@
return null;
}

// Mark followup-list as selected after a comment has been posted below the follow up list comment
const updatedHtml = html.replace(/<followup-list(\s[^>]*)?>/, '<followup-list selected>');
return {
...reportAction,
Expand Down Expand Up @@ -644,7 +644,7 @@

// Check if the last visible action is from Concierge with unresolved followups
// If so, optimistically resolve them by adding the updated action to optimisticReportActions
const lastVisibleAction = getLastVisibleAction(reportID);
const lastVisibleAction = ReportActionsUtils.getLastVisibleAction(reportID);
const lastActorAccountID = lastVisibleAction?.actorAccountID;
const lastActionReportActionID = lastVisibleAction?.reportActionID;
const resolvedAction = buildOptimisticResolvedFollowups(lastVisibleAction);
Expand Down Expand Up @@ -6549,46 +6549,6 @@
resolveConciergeOptions(report, notifyReportID, reportActionID, selectedDescription, timezoneParam, 'selectedDescription', ancestors);
}

/**
* Resolves a suggested followup by posting the selected question as a comment
* and optimistically updating the HTML to mark the followup-list as resolved.
* @param report - The report where the action exists
* @param notifyReportID - The report ID to notify for new actions
* @param reportAction - The report action containing the followup-list
* @param selectedFollowup - The followup question selected by the user
* @param timezoneParam - The user's timezone
* @param ancestors - Array of ancestor reports for proper threading
*/
function resolveSuggestedFollowup(
report: OnyxEntry<Report>,
notifyReportID: string | undefined,
reportAction: OnyxEntry<ReportAction>,
selectedFollowup: string,
timezoneParam: Timezone,
ancestors: Ancestor[] = [],
) {
const reportID = report?.reportID;
const reportActionID = reportAction?.reportActionID;

if (!reportID || !reportActionID) {
return;
}

const resolvedAction = buildOptimisticResolvedFollowups(reportAction);

if (!resolvedAction) {
return;
}

// Optimistically update the HTML to mark followup-list as resolved
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {
[reportActionID]: resolvedAction,
});

// Post the selected followup question as a comment
addComment(report, notifyReportID ?? reportID, ancestors, selectedFollowup, timezoneParam);
}

/**
* Enhances existing transaction thread reports with additional context for navigation
*
Expand Down Expand Up @@ -6689,7 +6649,6 @@
resolveActionableReportMentionWhisper,
resolveConciergeCategoryOptions,
resolveConciergeDescriptionOptions,
resolveSuggestedFollowup,
savePrivateNotesDraft,
saveReportActionDraft,
saveReportDraftComment,
Expand Down
11 changes: 8 additions & 3 deletions src/pages/inbox/report/PureReportActionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import resolveSuggestedFollowup from '@libs/actions/Report/SuggestedFollowup';
import ControlSelection from '@libs/ControlSelection';
import {convertToDisplayString} from '@libs/CurrencyUtils';
import {canUseTouchScreen} from '@libs/DeviceCapabilities';
Expand All @@ -63,7 +64,7 @@ import Parser from '@libs/Parser';
import Permissions from '@libs/Permissions';
import {getDisplayNameOrDefault} from '@libs/PersonalDetailsUtils';
import {getCleanedTagName, hasDynamicExternalWorkflow, isPolicyAdmin, isPolicyMember, isPolicyOwner} from '@libs/PolicyUtils';
import {containsActionableFollowUps, parseFollowupsFromHtml} from '@libs/ReportActionsFollowupUtils';
import {containsActionableFollowUps, parseFollowupsFromHtml} from '@libs/ReportActionFollowupUtils';
import {
extractLinksFromMessageHtml,
getActionableCardFraudAlertMessage,
Expand Down Expand Up @@ -204,7 +205,6 @@ import {
resolveActionableMentionConfirmWhisper,
resolveConciergeCategoryOptions,
resolveConciergeDescriptionOptions,
resolveSuggestedFollowup,
} from '@userActions/Report';
import type {IgnoreDirection} from '@userActions/ReportActions';
import {isAnonymousUser, signOutAndRedirectToSignIn} from '@userActions/Session';
Expand Down Expand Up @@ -1722,7 +1722,12 @@ function PureReportActionItem({
}
shouldUseLocalization={!isConciergeOptions && !actionContainsFollowUps}
primaryTextNumberOfLines={actionableButtonsNoLines}
textStyles={isConciergeOptions || actionContainsFollowUps ? styles.textAlignLeft : undefined}
styles={{
text: [isConciergeOptions || actionContainsFollowUps ? styles.textAlignLeft : undefined, actionContainsFollowUps && styles.fontWeightNormal],
button: actionContainsFollowUps ? [styles.actionableItemButton, hovered && styles.actionableItemButtonBackgroundHovered] : undefined,
buttonHover: actionContainsFollowUps ? styles.actionableItemButtonHovered : undefined,
container: actionContainsFollowUps && shouldUseNarrowLayout ? [styles.alignItemsStretch] : undefined,
}}
/>
)}
</View>
Expand Down
18 changes: 18 additions & 0 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,24 @@ const staticStyles = (theme: ThemeColors) =>
overflow: 'hidden',
},

actionableItemButton: {
paddingTop: 8,
paddingBottom: 8,
backgroundColor: 'transparent',
borderWidth: 1,
borderColor: theme.border,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when we're hovering the message change this to button press

Same as on the expense

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated look cc @dubielzyk-expensify

Screen.Recording.2026-01-28.at.13.59.05.mov

alignItems: 'flex-start',
borderRadius: variables.componentBorderRadiusMedium,
},

actionableItemButtonBackgroundHovered: {
borderColor: theme.buttonPressedBG,
},

actionableItemButtonHovered: {
borderWidth: 1,
},

hoveredComponentBG: {
backgroundColor: theme.hoverComponentBG,
},
Expand Down
Loading
Loading