Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f33c8bb
Update report details view to use compact desktop table styles
Krishna2323 Apr 19, 2026
8c67c84
Merge remote-tracking branch 'upstream/main' into krishna2323/issue/8…
Krishna2323 Apr 25, 2026
95282fe
Fix row boundary computation to use all rendered transactions instead…
Krishna2323 Apr 25, 2026
38884a8
Fix bottom border radius on last transaction item by applying overflo…
Krishna2323 Apr 25, 2026
425a58b
Skip last-item border radius when pending expense skeleton is visible
Krishna2323 Apr 26, 2026
3ff5d5f
Remove redundant isFirstItem top radius and duplicate bottom radius f…
Krishna2323 Apr 26, 2026
7dc7685
Fix checkbox alignment by removing default 2px margin on header and g…
Krishna2323 Apr 26, 2026
4eb214c
Fix desktop checkbox alignment and remove bottom margin from table on…
Krishna2323 Apr 26, 2026
0c14816
Replace inline style values with style utilities and consolidate desk…
Krishna2323 Apr 26, 2026
eab4f8a
Apply compact table styles from 800px instead of 1024px to match tabl…
Krishna2323 Apr 26, 2026
2e46d50
Update group header to match Figma: 36px height, 8px vertical padding…
Krishna2323 Apr 27, 2026
d19f2f6
Merge remote-tracking branch 'origin/main' into krishna2323/issue/86203
Krishna2323 Apr 29, 2026
83be019
Merge upstream/main and resolve conflicts
Krishna2323 Apr 29, 2026
9c68706
Resolve merge conflicts in MoneyRequestReportView components
Krishna2323 Apr 29, 2026
5fe4fff
Fix merge conflict resolution to preserve upstream narrow layout styles
Krishna2323 Apr 29, 2026
cc2d160
Match Select All row styling with group header at tweener sizes
Krishna2323 Apr 29, 2026
c7149dd
Fix table header column alignment with transaction rows on desktop
Krishna2323 Apr 29, 2026
5972e41
Fix table header column alignment on desktop by adjusting right padding
Krishna2323 Apr 29, 2026
6d301e6
fix: prevent amount columns from stretching on report details page
Krishna2323 Apr 30, 2026
f624009
refactor: remove unnecessary useMemo from MoneyRequestReportGroupHeader
Krishna2323 Apr 30, 2026
44af0e5
fix: prevent bottom border radius on last transaction when skeleton i…
Krishna2323 Apr 30, 2026
131a0dc
Merge branch 'Expensify:main' into krishna2323/issue/86203
Krishna2323 Apr 30, 2026
dd0789d
fix: account for offline pending-delete rows when determining last tr…
Krishna2323 Apr 30, 2026
b9c6e98
Remove useCallback and isDesktopTableLayout per review feedback
Krishna2323 May 1, 2026
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
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import React, {useCallback, useMemo} from 'react';
import React from 'react';
import {View} from 'react-native';
import Checkbox from '@components/Checkbox';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import Text from '@components/Text';
import {useCurrencyListActions} from '@hooks/useCurrencyList';
import useLocalize from '@hooks/useLocalize';
import useResponsiveLayoutOnWideRHP from '@hooks/useResponsiveLayoutOnWideRHP';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {getCommaSeparatedTagNameWithSanitizedColons} from '@libs/PolicyUtils';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import type {GroupedTransactions} from '@src/types/onyx';
import type {PendingAction} from '@src/types/onyx/OnyxCommon';

const DESKTOP_HEIGHT = 28;

type MoneyRequestReportGroupHeaderProps = {
/** The grouped transaction data */
group: GroupedTransactions;
Expand Down Expand Up @@ -65,6 +64,7 @@ function MoneyRequestReportGroupHeader({
}: MoneyRequestReportGroupHeaderProps) {
const {convertToDisplayString} = useCurrencyListActions();
const styles = useThemeStyles();
const theme = useTheme();
const {translate} = useLocalize();
const {shouldUseNarrowLayout: shouldUseNarrowLayoutHook} = useResponsiveLayoutOnWideRHP();
const shouldUseNarrowLayout = shouldUseNarrowLayoutProp ?? shouldUseNarrowLayoutHook;
Expand All @@ -75,18 +75,27 @@ function MoneyRequestReportGroupHeader({

const shouldShowCheckbox = isSelectionModeEnabled || !shouldUseNarrowLayout;

const textStyle = useMemo(
() => (shouldUseNarrowLayout ? {fontSize: variables.fontSizeLabel, lineHeight: 16} : {fontSize: variables.fontSizeNormal, lineHeight: DESKTOP_HEIGHT}),
[shouldUseNarrowLayout],
);
const textStyle = shouldUseNarrowLayout ? {fontSize: variables.fontSizeLabel, lineHeight: 16} : [styles.labelStrong];

const handleToggleSelection = useCallback(() => {
const handleToggleSelection = () => {
onToggleSelection?.(groupKey);
}, [onToggleSelection, groupKey]);
};

const groupHeaderStyle = !shouldUseNarrowLayout
? [
{minHeight: variables.tableGroupRowHeight},
styles.justifyContentCenter,
styles.highlightBG,
styles.pv2,
styles.ph3,
styles.borderBottom,
isSelected && {borderColor: theme.buttonHoveredBG},
]
: [styles.ph4, styles.pv3, styles.borderBottom];

return (
<OfflineWithFeedback pendingAction={pendingAction}>
<View style={[shouldUseNarrowLayout ? [styles.ph4, styles.pv3, styles.borderBottom] : [styles.reportLayoutGroupHeader, {height: DESKTOP_HEIGHT, minHeight: DESKTOP_HEIGHT}]]}>
<View style={groupHeaderStyle}>
<View style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]}>
{shouldShowCheckbox && (
<Checkbox
Expand All @@ -95,11 +104,12 @@ function MoneyRequestReportGroupHeader({
disabled={isDisabled}
onPress={handleToggleSelection}
accessibilityLabel={translate('reportLayout.selectGroup', {groupName: displayName})}
style={styles.mr2}
containerStyle={!shouldUseNarrowLayout && styles.m0}
style={!shouldUseNarrowLayout ? styles.mr3 : styles.mr2}
/>
)}
<Text
style={[styles.textBold, textStyle, styles.flexShrink1, shouldShowCheckbox && styles.ml2]}
style={[styles.textBold, textStyle, styles.flexShrink1, shouldShowCheckbox && shouldUseNarrowLayout && styles.ml2]}
numberOfLines={1}
>
{displayName}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,19 @@ type SearchTableHeaderProps = {
taxAmountColumnSize: TableColumnSize;
shouldShowSorting: boolean;
columns: SearchColumnType[];
shouldRemoveTotalColumnFlex?: boolean;
};
function MoneyRequestReportTableHeader({sortBy, sortOrder, onSortPress, dateColumnSize, shouldShowSorting, columns, amountColumnSize, taxAmountColumnSize}: SearchTableHeaderProps) {
function MoneyRequestReportTableHeader({
sortBy,
sortOrder,
onSortPress,
dateColumnSize,
shouldShowSorting,
columns,
amountColumnSize,
taxAmountColumnSize,
shouldRemoveTotalColumnFlex,
}: SearchTableHeaderProps) {
const styles = useThemeStyles();

const columnConfig = useMemo(
Expand Down Expand Up @@ -77,6 +88,7 @@ function MoneyRequestReportTableHeader({sortBy, sortOrder, onSortPress, dateColu
sortBy={sortBy}
sortOrder={sortOrder}
onSortPress={onSortPress}
shouldRemoveTotalColumnFlex={shouldRemoveTotalColumnFlex}
/>
</View>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useResponsiveLayoutOnWideRHP from '@hooks/useResponsiveLayoutOnWideRHP';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import useTransactionViolations from '@hooks/useTransactionViolations';
Expand Down Expand Up @@ -70,7 +71,7 @@ type MoneyRequestReportTransactionItemProps = {
/** List of cards for the user */
nonPersonalAndWorkspaceCards: CardList;

/** Whether this is the last item in the list (used to skip border-bottom on narrow) */
/** Whether this is the last item in the list */
isLastItem?: boolean;
};

Expand All @@ -95,6 +96,7 @@ function MoneyRequestReportTransactionItem({
}: MoneyRequestReportTransactionItemProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
// eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
const {isSmallScreenWidth, isMediumScreenWidth} = useResponsiveLayout();
const {shouldUseNarrowLayout} = useResponsiveLayoutOnWideRHP();
Expand All @@ -117,15 +119,18 @@ function MoneyRequestReportTransactionItem({
}, [scrollToNewTransaction, shouldBeHighlighted]);

const animatedHighlightStyle = useAnimatedHighlightStyle({
borderRadius: shouldUseNarrowLayout ? 0 : variables.componentBorderRadius,
borderRadius: shouldUseNarrowLayout ? variables.componentBorderRadius : 0,
shouldHighlight: shouldBeHighlighted,
highlightColor: theme.messageHighlightBG,
backgroundColor: theme.highlightBG,
shouldApplyOtherStyles: !shouldUseNarrowLayout,
});

return (
<OfflineWithFeedback pendingAction={pendingAction}>
<OfflineWithFeedback
pendingAction={pendingAction}
style={!shouldUseNarrowLayout && isLastItem && [styles.searchTableBottomRadius, styles.overflowHidden]}
>
<PressableWithFeedback
key={transaction.transactionID}
onPress={() => {
Expand All @@ -136,7 +141,7 @@ function MoneyRequestReportTransactionItem({
role={getButtonRole(true)}
isNested
id={transaction.transactionID}
style={[styles.transactionListItemStyle, shouldUseNarrowLayout && styles.noBorderRadius]}
style={[styles.transactionListItemStyle, !shouldUseNarrowLayout ? StyleUtils.getSearchTableRowPressableStyle(isLastItem, isSelected) : styles.noBorderRadius]}
hoverStyle={[!isPendingDelete && styles.hoveredComponentBG, isSelected && styles.activeComponentBG]}
dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}}
onPressIn={() => canUseTouchScreen() && ControlSelection.block()}
Expand Down Expand Up @@ -164,13 +169,14 @@ function MoneyRequestReportTransactionItem({
onCheckboxPress={toggleTransaction}
columns={columns}
isDisabled={isPendingDelete}
style={shouldUseNarrowLayout ? [styles.p4, styles.noBorderRadius] : [styles.p3]}
style={!shouldUseNarrowLayout ? [styles.p3, styles.pv2, styles.noBorderRadius] : [styles.p4, styles.noBorderRadius]}
onButtonPress={() => {
handleOnPress(transaction.transactionID);
}}
onArrowRightPress={() => onArrowRightPress?.(transaction.transactionID)}
isHover={hovered}
nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
shouldRemoveTotalColumnFlex
/>
)}
</PressableWithFeedback>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import useHandleSelectionMode from '@hooks/useHandleSelectionMode';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
import useNetwork from '@hooks/useNetwork';
import useOnyx from '@hooks/useOnyx';
import useReportIsArchived from '@hooks/useReportIsArchived';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
Expand Down Expand Up @@ -151,6 +152,7 @@ function MoneyRequestReportTransactionList({
const [isModalVisible, setIsModalVisible] = useState(false);
const [selectedTransactionID, setSelectedTransactionID] = useState<string>('');
const {reportPendingAction} = getReportOfflinePendingActionAndErrors(report);
const {isOffline} = useNetwork();

const isTaxEnabled = isPolicyTaxEnabled(policy);
const {totalDisplaySpend, nonReimbursableSpend, reimbursableSpend} = getMoneyRequestSpendBreakdown(report);
Expand Down Expand Up @@ -554,11 +556,36 @@ function MoneyRequestReportTransactionList({
[groupByOptions, reportLayoutGroupBy, styles, windowHeight, isInLandscapeMode],
);

const isDesktopTableLayout = !shouldUseNarrowLayout;
Comment thread
Krishna2323 marked this conversation as resolved.

const lastTransactionID = useMemo(() => {
const allTransactions = shouldShowGroupedTransactions ? groupedTransactions.flatMap((group) => group.transactions) : resolvedTransactions;
const nonDeletedTransactions = allTransactions.filter((t) => !isTransactionPendingDelete(t));
return nonDeletedTransactions.at(-1)?.transactionID;
}, [shouldShowGroupedTransactions, groupedTransactions, resolvedTransactions]);
const visibleTransactions = allTransactions.filter((t) => isOffline || !isTransactionPendingDelete(t));
return visibleTransactions.at(-1)?.transactionID;
}, [shouldShowGroupedTransactions, groupedTransactions, resolvedTransactions, isOffline]);

const renderTransactionItem = (transaction: TransactionWithOptionalHighlight) => (
<MoneyRequestReportTransactionItem
key={transaction.transactionID}
transaction={transaction}
shouldBeHighlighted={highlightedTransactionIDs.has(transaction.transactionID)}
columns={columnsToShow}
report={report}
policy={policy}
isSelectionModeEnabled={isMobileSelectionModeEnabled}
toggleTransaction={toggleTransaction}
isSelected={isTransactionSelected(transaction.transactionID)}
handleOnPress={handleOnPress}
handleLongPress={handleLongPress}
dateColumnSize={dateColumnSize}
amountColumnSize={amountColumnSize}
taxAmountColumnSize={taxAmountColumnSize}
scrollToNewTransaction={transaction.transactionID === newTransactions?.at(0)?.transactionID ? scrollToNewTransaction : undefined}
onArrowRightPress={handleArrowRightPress}
nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards ?? {}}
isLastItem={!showPendingExpensePlaceholder && transaction.transactionID === lastTransactionID}
/>
);

const transactionItems = shouldShowGroupedTransactions
? groupedTransactions.map((group) => {
Expand All @@ -568,12 +595,8 @@ function MoneyRequestReportTransactionList({
isDisabled: false,
pendingAction: undefined,
};

return (
<View
key={group.groupKey}
style={!shouldUseNarrowLayout && styles.gap2}
>
<View key={group.groupKey}>
<MoneyRequestReportGroupHeader
group={group}
groupKey={group.groupKey}
Expand All @@ -587,65 +610,17 @@ function MoneyRequestReportTransactionList({
pendingAction={selectionState.pendingAction}
shouldUseNarrowLayout={shouldUseNarrowLayout}
/>
{group.transactions.map((transaction) => {
const isLastItem = transaction.transactionID === lastTransactionID;
return (
<MoneyRequestReportTransactionItem
key={transaction.transactionID}
transaction={transaction}
shouldBeHighlighted={highlightedTransactionIDs.has(transaction.transactionID)}
columns={columnsToShow}
report={report}
policy={policy}
isSelectionModeEnabled={isMobileSelectionModeEnabled}
toggleTransaction={toggleTransaction}
isSelected={isTransactionSelected(transaction.transactionID)}
handleOnPress={handleOnPress}
handleLongPress={handleLongPress}
dateColumnSize={dateColumnSize}
amountColumnSize={amountColumnSize}
taxAmountColumnSize={taxAmountColumnSize}
scrollToNewTransaction={transaction.transactionID === newTransactions?.at(0)?.transactionID ? scrollToNewTransaction : undefined}
onArrowRightPress={handleArrowRightPress}
nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards ?? {}}
isLastItem={isLastItem}
/>
);
})}
{group.transactions.map((transaction) => renderTransactionItem(transaction))}
</View>
);
})
: resolvedTransactions.map((transaction) => {
const isLastItem = transaction.transactionID === lastTransactionID;
return (
<MoneyRequestReportTransactionItem
key={transaction.transactionID}
transaction={transaction}
shouldBeHighlighted={highlightedTransactionIDs.has(transaction.transactionID)}
columns={columnsToShow}
report={report}
policy={policy}
isSelectionModeEnabled={isMobileSelectionModeEnabled}
toggleTransaction={toggleTransaction}
isSelected={isTransactionSelected(transaction.transactionID)}
handleOnPress={handleOnPress}
handleLongPress={handleLongPress}
dateColumnSize={dateColumnSize}
amountColumnSize={amountColumnSize}
taxAmountColumnSize={taxAmountColumnSize}
scrollToNewTransaction={transaction.transactionID === newTransactions?.at(0)?.transactionID ? scrollToNewTransaction : undefined}
onArrowRightPress={handleArrowRightPress}
nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards ?? {}}
isLastItem={isLastItem}
/>
);
});
: resolvedTransactions.map((transaction) => renderTransactionItem(transaction));

const narrowListWrapper = shouldUseNarrowLayout ? [styles.highlightBG, styles.searchTableTopRadius, styles.searchTableBottomRadius, styles.overflowHidden] : undefined;

const transactionListContent = (
<View
style={[listHorizontalPadding, !shouldUseNarrowLayout && styles.gap2, shouldUseNarrowLayout ? styles.pb2 : styles.pb4, !shouldUseNarrowLayout && styles.mb2]}
style={[listHorizontalPadding, shouldUseNarrowLayout ? styles.pb2 : styles.pb4]}
onLayout={onLayout}
>
{narrowListWrapper ? <View style={narrowListWrapper}>{transactionItems}</View> : transactionItems}
Expand All @@ -664,8 +639,27 @@ function MoneyRequestReportTransactionList({

const tableHeaderContent = (
<OfflineWithFeedback pendingAction={reportPendingAction}>
<View style={[styles.dFlex, styles.flexRow, styles.pl5, styles.pr16, styles.alignItemsCenter]}>
<View style={[styles.dFlex, styles.flexRow, styles.pv2, styles.pr4, StyleUtils.getPaddingLeft(variables.w12)]}>
<View
style={[
styles.dFlex,
styles.flexRow,
!isDesktopTableLayout && styles.pl5,
isDesktopTableLayout ? styles.pr11 : styles.pr16,
styles.alignItemsCenter,
isDesktopTableLayout && [styles.highlightBG, styles.searchTableTopRadius, styles.mh5, styles.borderBottom],
]}
>
<View
style={[
styles.dFlex,
styles.flexRow,
styles.alignItemsCenter,
styles.pv2,
!isDesktopTableLayout && styles.pr4,
StyleUtils.getPaddingLeft(variables.w12),
isDesktopTableLayout && {minHeight: variables.tableGroupRowHeight},
]}
>
<Checkbox
onPress={() => {
if (selectedTransactionIDs.length !== 0) {
Expand All @@ -677,8 +671,10 @@ function MoneyRequestReportTransactionList({
accessibilityLabel={translate('accessibilityHints.selectAllTransactions')}
isIndeterminate={selectedTransactionIDs.length > 0 && selectedTransactionIDs.length !== transactionsWithoutPendingDelete.length}
isChecked={selectedTransactionIDs.length > 0 && selectedTransactionIDs.length === transactionsWithoutPendingDelete.length}
containerStyle={isDesktopTableLayout && styles.m0}
style={isDesktopTableLayout && styles.mr3}
/>
{isMediumScreenWidth && !shouldScrollHorizontally && <Text style={[styles.textStrong, styles.ph3]}>{translate('workspace.people.selectAll')}</Text>}
{isMediumScreenWidth && !shouldScrollHorizontally && <Text style={[styles.labelStrong]}>{translate('workspace.people.selectAll')}</Text>}
</View>
{(!isMediumScreenWidth || shouldScrollHorizontally) && (
<MoneyRequestReportTableHeader
Expand All @@ -689,6 +685,7 @@ function MoneyRequestReportTransactionList({
dateColumnSize={dateColumnSize}
amountColumnSize={amountColumnSize}
taxAmountColumnSize={taxAmountColumnSize}
shouldRemoveTotalColumnFlex
onSortPress={(selectedSortBy, selectedSortOrder) => {
if (!isSortableColumnName(selectedSortBy)) {
return;
Expand Down
Loading
Loading