Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
8e1aed8
Add layout spacing tokens and useLayoutSpacing
grgia Sep 10, 2026
41520ac
Read card padding from useLayoutSpacing in card rows and sections
grgia Sep 10, 2026
c0c287b
Lint: ban horizontal inset conditionals on layout flags
grgia Sep 10, 2026
519c9c6
Name the replacement in the layout spacing lint message
grgia Sep 10, 2026
e534392
Add the remaining card inset styles to useLayoutSpacing
grgia Sep 10, 2026
27f1f4a
Document the type and layout spacing tokens for contributors and agents
grgia Sep 10, 2026
0e5021d
Read the page gutter token in Spend rows, Table rows and the search i…
grgia Sep 10, 2026
523ab42
Tighten mobile page gutters to 12px and card padding to 24px
grgia Sep 10, 2026
5a3c223
Use a 12px gap between stacked Home cards on mobile
grgia Sep 11, 2026
4bcc8d7
Use the 12px card gap between stacked Section cards on mobile
grgia Sep 11, 2026
9688a4e
Fix lint shorthand in the spacing rule and drop two unused exported t…
grgia Sep 11, 2026
cb41d5e
Inset workspace page header button rows at the page gutter on mobile
grgia Sep 11, 2026
c3012f2
Start tab pills and the Workspaces tab header at the page gutter
grgia Sep 11, 2026
99e1923
Flag only hand-spelled card insets in the layout spacing rule
grgia Sep 11, 2026
65eb2ce
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Sep 16, 2026
4e48bce
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Sep 16, 2026
81a51dd
Restore the proposalPoliceComment action bundle from main
grgia Sep 16, 2026
997a932
Start the table filter bar at the page gutter on mobile
grgia Sep 16, 2026
4677db5
Let Section cards in Rules and bank account flows use the page gutter
grgia Sep 16, 2026
c2044af
Keep the 12px tab bar to page-level tab bars
grgia Sep 17, 2026
549d26c
Move the remaining Spend, Domain and expense report insets onto the p…
grgia Sep 17, 2026
45fafcf
Keep two right-hand-panel screens on the plain 20px inset
grgia Sep 17, 2026
5a32648
Name cardPaddingLeft and cardMarginHorizontal in the lint message
grgia Sep 17, 2026
8c3eff5
Update the Chats row highlight test for the page gutter token
grgia Sep 17, 2026
695b8c4
Resolve the expense report list gutter from the same flag as its tabl…
grgia Sep 17, 2026
d00cba5
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Sep 17, 2026
abb40cf
Resolve the search skeleton gutter from its effective layout flag
grgia Sep 18, 2026
6483b91
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Sep 18, 2026
ed0aa39
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Sep 24, 2026
fca43bf
Move two insets added on main onto the card padding token
grgia Sep 24, 2026
dd12f23
Use the slim gutter for report header buttons and the totals row on m…
grgia Sep 24, 2026
8dd856a
Drop cardMarginHorizontal now its only consumer is gone
grgia Sep 24, 2026
70f774e
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Sep 28, 2026
bdcc3f8
Bring the Insights tab and two skeletons onto the spacing tokens
grgia Sep 29, 2026
3c13c45
Line Section menu rows up with the 24px card padding
grgia Sep 29, 2026
5af0c5e
Say where the menu item padding constant comes from
grgia Sep 29, 2026
59052d2
Fix the last insets a fresh review found on the merged head
grgia Sep 29, 2026
7bd7c8a
Catch padding reads like styles.ph5.paddingHorizontal in the spacing …
grgia Sep 29, 2026
c48a095
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Sep 29, 2026
b95c0fe
Read the menu item padding from one constant in both places
grgia Sep 30, 2026
4faf690
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Sep 30, 2026
77edb7b
Restore the GitHub Action bundles from main
grgia Sep 30, 2026
b55b304
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Oct 2, 2026
c86e8c1
Pin the column width test to the wide layout
grgia Oct 2, 2026
eba3048
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Oct 2, 2026
c001fff
Move the early renewal offer card rows onto the card padding token
grgia Oct 2, 2026
0e7fd83
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Oct 5, 2026
86b1e96
Move the Insights dashboard card gap and chart card bottom padding on…
grgia Oct 5, 2026
94fd85c
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Oct 5, 2026
6e54099
Move the invoicing details card top padding onto the card padding token
grgia Oct 5, 2026
e252dc9
Cover cardPaddingTop in the layout spacing test and token lists
grgia Oct 5, 2026
18d0cc0
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Oct 6, 2026
a225011
Point the spacing docs at the hook instead of listing its tokens
grgia Oct 6, 2026
41d7adb
Merge remote-tracking branch 'origin/main' into georgia-spacing-system
grgia Oct 7, 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
1 change: 1 addition & 0 deletions .claude/skills/app-coding-standards/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Coding standards for the Expensify App. Each standard is a standalone file in `r
- [UI-1](rules/ui-1-correct-loading-indicator.md) — Use the correct loading indicator based on navigation context
- [UI-2](rules/ui-2-new-page-scrollview.md) — New pages must be scrollable
- [UI-3](rules/ui-3-no-inline-styles.md) — Do not use inline style objects
- [UI-4](rules/ui-4-layout-spacing-tokens.md) — Type and responsive insets come from tokens

## Usage

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
ruleId: UI-4
title: Type and responsive insets come from tokens
---

## [UI-4] Type and responsive insets come from tokens

### Reasoning

Per `STYLING.md`, font sizes come from `<Text variant="...">` and paddings or margins that differ between narrow and wide layouts come from `useLayoutSpacing()`. Writing `shouldUseNarrowLayout ? styles.ph5 : styles.ph8` decides the card inset at the call site, so every card row has to agree by hand and a design change means editing dozens of files. `rulesdir/no-raw-typography` and `rulesdir/no-layout-spacing-conditional` enforce both.

### Incorrect

```tsx
function CardRow() {
const {shouldUseNarrowLayout} = useResponsiveLayout();
return (
<View style={[styles.flexRow, shouldUseNarrowLayout ? styles.ph5 : styles.ph8]}>
<Text style={{fontSize: 15}}>Title</Text>
</View>
);
}
```

### Correct

```tsx
function CardRow() {
const {cardPaddingHorizontal} = useLayoutSpacing();
return (
<View style={[styles.flexRow, cardPaddingHorizontal]}>
<Text variant="textStrong">Title</Text>
</View>
);
}
```

See `useLayoutSpacing`'s implementation for available options. Tokens live in `src/styles/layoutSpacing.ts`; add a new one there rather than writing a ternary.

---

### Review Metadata

Flag ONLY when ALL of these are true:

- The changed code picks a horizontal inset helper by layout flag where the pair spells the card padding values (the `5` step narrow, the `8` step wide, e.g. `styles.ph5 : styles.ph8`, `styles.mhn5 : styles.mhn8`), or sets a raw `fontSize` / `lineHeight`
- A matching token exists (`cardPadding*`, `pageGutter*`, or a `Text` variant)

**DO NOT flag if:**

- The conditional picks vertical spacing only (`pt`, `pb`, `pv`, `mt`, `mb`, `mv`, `gap`)
- The values are not a card inset or page gutter and no token exists yet (suggest adding one instead)
- The code is inside `src/styles/`

**Search Patterns** (hints for reviewers):
- `shouldUseNarrowLayout ? styles.p`
- `shouldUseNarrowLayout ? styles.m`
- `isSmallScreenWidth ? styles.p`
- `fontSize:`
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Do not use `useMemo`, `useCallback`, or `React.memo` in components or hooks that
### Code Quality

- **ESLint**: Linter. Pre-existing violations are grandfathered via the seatbelt ratchet in `scripts/lint/`.
- **Design tokens**: font sizes come from `<Text variant="...">`, and paddings or margins that differ between narrow and wide layouts come from `useLayoutSpacing()` (`cardPaddingHorizontal`, `pageGutter`, ...). Never write `shouldUseNarrowLayout ? styles.ph5 : styles.ph8` or a raw `fontSize`. See `contributingGuides/STYLING.md`.

### Post-Edit Checklist (IMPORTANT)

Expand Down
1 change: 1 addition & 0 deletions config/eslint/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ const config = defineConfig([
'rulesdir/require-a11y-disable-justification': 'error',
'rulesdir/no-direct-pre-insert-fullscreen-under-rhp': 'error',
'rulesdir/no-raw-typography': 'error',
'rulesdir/no-layout-spacing-conditional': 'error',
'rulesdir/no-direct-personal-details-list': 'error',
'rulesdir/require-locale-for-localized-date-format': 'error',
'rulesdir/prefer-narrow-hook-dependencies': [
Expand Down
19 changes: 19 additions & 0 deletions contributingGuides/STYLING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,25 @@ These helper styles are loosely based on the [Bootstrap system of CSS utility he

**Note:** Not all helpers from Bootstrap exist, so it may be necessary to create the helper style we need.

## Type and Responsive Spacing Come From Tokens

Two kinds of values must never be written by hand in a component: font sizes and the paddings or margins that change between narrow and wide layouts.

- **Type**: use `<Text variant="...">` (see `src/styles/typography.ts`). Raw `fontSize` / `lineHeight` are blocked by `rulesdir/no-raw-typography`.
- **Responsive insets**: use `useLayoutSpacing()` (see `src/styles/layoutSpacing.ts`). It resolves `cardPadding` and `pageGutter` for the current layout and returns ready styles (`cardGap`, the space between stacked cards, is also read directly by the style sheet for the Home layout). Writing the card inset by hand, `shouldUseNarrowLayout ? styles.ph5 : styles.ph8` or any other `5`/`8` inset pair, is blocked by `rulesdir/no-layout-spacing-conditional`.

```tsx
// Bad - the card inset is decided here, so every card row has to agree by hand
const {shouldUseNarrowLayout} = useResponsiveLayout();
<View style={[styles.flexRow, shouldUseNarrowLayout ? styles.ph5 : styles.ph8]} />

// Good - the inset is a token, resolved once for the current layout
const {cardPaddingHorizontal} = useLayoutSpacing();
<View style={[styles.flexRow, cardPaddingHorizontal]} />
```

Spacing that is not a card inset or page gutter (for example a `pb2` vs `pb5` rhythm tweak) is still written with the helper styles. If you need a new responsive inset, add it to `layoutSpacing.ts` rather than writing the ternary.

## When to Create a New Style

If we need some minimal set of styling rules applied to a single-use component, then it's almost always better to use an array of helper styles rather than create an entirely new style if it will only be used once. Resist the urge to create a new style for every new element added to a screen. There is a very good chance the style we are adding is a "single-use" style.
Expand Down
113 changes: 113 additions & 0 deletions eslint-plugin-local-rules/no-layout-spacing-conditional.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
const name = 'no-layout-spacing-conditional';

const meta = {
type: 'problem',
docs: {
description:
'Disallow spelling the card inset by hand as a narrow/wide ternary over spacing helpers. Card padding must come from useLayoutSpacing() so every screen agrees on the same values.',
recommended: 'error',
},
schema: [],
messages: {
layoutSpacingConditional:
'`{{test}} ? styles.{{first}} : styles.{{second}}` spells the card inset by hand. Use the matching style from `useLayoutSpacing()` (src/styles/layoutSpacing.ts) so the value stays in one place.',
layoutSpacingConditionalKnown: 'Replace `{{test}} ? styles.{{first}} : styles.{{second}}` with `{{replacement}}` from `useLayoutSpacing()` (src/styles/layoutSpacing.ts).',
},
};

const NARROW_FLAGS = new Set(['shouldUseNarrowLayout', 'isSmallScreenWidth', 'isExtraSmallScreenWidth']);
const WIDE_FLAGS = new Set(['isLargeScreenWidth', 'isExtraLargeScreenWidth']);
const KNOWN_REPLACEMENTS = {
'ph5:ph8': 'cardPaddingHorizontal',
'p5:p8': 'cardPadding',
'mhn5:mhn8': 'cardEdgeToEdge',
'pl5:pl8': 'cardPaddingLeft',
};
Comment thread
arosiclair marked this conversation as resolved.
const SPACING_CLASS_PATTERN = /^([pm](?:h|l|r|hn|ln|rn)?)(\d+)$/;
const CARD_PADDING_STEPS = {narrow: '5', wide: '8'};
const TS_WRAPPER_TYPES = new Set(['TSAsExpression', 'TSSatisfiesExpression', 'TSNonNullExpression', 'TSTypeAssertion']);

function unwrap(node) {
if (TS_WRAPPER_TYPES.has(node.type)) {
return unwrap(node.expression);
}
return node;
}

function getSpacingClassName(node) {
let unwrapped = unwrap(node);
if (unwrapped.type === 'MemberExpression' && !unwrapped.computed && unwrapped.property.type === 'Identifier' && /^(padding|margin)/.test(unwrapped.property.name)) {
unwrapped = unwrap(unwrapped.object);
}
if (unwrapped.type !== 'MemberExpression' || unwrapped.computed || unwrapped.property.type !== 'Identifier') {
return undefined;
}
return SPACING_CLASS_PATTERN.test(unwrapped.property.name) ? unwrapped.property.name : undefined;
}

function findSpacingClassName(node) {
const unwrapped = unwrap(node);
if (unwrapped.type === 'ArrayExpression') {
for (const element of unwrapped.elements) {
const className = element ? findSpacingClassName(element) : undefined;
if (className) {
return className;
}
}
return undefined;
}
return getSpacingClassName(unwrapped);
}

function getLayoutFlag(test) {
const unwrapped = unwrap(test);
if (unwrapped.type === 'UnaryExpression' && unwrapped.operator === '!') {
const inner = getLayoutFlag(unwrapped.argument);
return inner ? {name: `!${inner.name}`, isNarrowWhenTrue: !inner.isNarrowWhenTrue} : undefined;
}
let flagName;
if (unwrapped.type === 'Identifier') {
flagName = unwrapped.name;
} else if (unwrapped.type === 'MemberExpression' && !unwrapped.computed && unwrapped.property.type === 'Identifier') {
flagName = unwrapped.property.name;
}
if (NARROW_FLAGS.has(flagName)) {
return {name: flagName, isNarrowWhenTrue: true};
}
if (WIDE_FLAGS.has(flagName)) {
return {name: flagName, isNarrowWhenTrue: false};
}
return undefined;
}

function create(context) {
return {
ConditionalExpression(node) {
const flag = getLayoutFlag(node.test);
if (!flag) {
return;
}
const first = findSpacingClassName(node.consequent);
const second = findSpacingClassName(node.alternate);
if (!first || !second) {
return;
}
const narrow = flag.isNarrowWhenTrue ? first : second;
const wide = flag.isNarrowWhenTrue ? second : first;
const [, narrowPrefix, narrowStep] = SPACING_CLASS_PATTERN.exec(narrow);
const [, widePrefix, wideStep] = SPACING_CLASS_PATTERN.exec(wide);
if (narrowPrefix !== widePrefix || narrowStep !== CARD_PADDING_STEPS.narrow || wideStep !== CARD_PADDING_STEPS.wide) {
return;
}
const replacement = KNOWN_REPLACEMENTS[`${narrow}:${wide}`];
const data = {test: flag.name, first, second};
if (replacement) {
context.report({node, messageId: 'layoutSpacingConditionalKnown', data: {...data, replacement}});
return;
}
context.report({node, messageId: 'layoutSpacingConditional', data});
},
};
}

export {name, meta, create};
6 changes: 3 additions & 3 deletions src/components/BaseWidgetItem.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useLayoutSpacing from '@hooks/useLayoutSpacing';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';

Expand Down Expand Up @@ -39,7 +39,7 @@ type BaseWidgetItemProps = {
function BaseWidgetItem({icon, title, subtitle, ctaText, onCtaPress, buttonVariant}: BaseWidgetItemProps) {
const styles = useThemeStyles();
const theme = useTheme();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const {cardPaddingHorizontal} = useLayoutSpacing();

return (
<PressableWithoutFeedback
Expand All @@ -49,7 +49,7 @@ function BaseWidgetItem({icon, title, subtitle, ctaText, onCtaPress, buttonVaria
sentryLabel={CONST.SENTRY_LABEL.HOME_PAGE.WIDGET_ITEM}
>
{({hovered}) => (
<View style={[styles.flexRow, styles.alignItemsCenter, styles.gap3, styles.pv3, shouldUseNarrowLayout ? styles.ph5 : styles.ph8, hovered && styles.hoveredComponentBG]}>
<View style={[styles.flexRow, styles.alignItemsCenter, styles.gap3, styles.pv3, cardPaddingHorizontal, hovered && styles.hoveredComponentBG]}>
<View style={styles.widgetItemIconContainer}>
<Icon
src={icon}
Expand Down
6 changes: 3 additions & 3 deletions src/components/ConnectionStatusMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import useLayoutSpacing from '@hooks/useLayoutSpacing';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';

Expand Down Expand Up @@ -36,15 +36,15 @@ function ConnectionStatusMessage({
const icons = useMemoizedLazyExpensifyIcons(['DotIndicator']);
const theme = useTheme();
const styles = useThemeStyles();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const {cardPaddingHorizontal} = useLayoutSpacing();

if (!message && !actionText) {
return null;
}

let statusMessageRowPadding;
if (shouldIncludeHorizontalPadding) {
statusMessageRowPadding = shouldUseNarrowLayout ? styles.ph5 : styles.ph8;
statusMessageRowPadding = cardPaddingHorizontal;
}
const shouldShowActionButton = !!actionText && !!onActionPress;
const isDangerStatus = statusTone === 'danger';
Expand Down
10 changes: 4 additions & 6 deletions src/components/MenuItem/presets/MenuItemSectionRoot.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import MenuItemRoot from '@components/MenuItem/layout/MenuItemRoot';
import type {MenuItemRootProps} from '@components/MenuItem/layout/MenuItemRoot';

import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import useLayoutSpacing from '@hooks/useLayoutSpacing';

import type {RefObject} from 'react';

Expand All @@ -16,13 +15,12 @@ type MenuItemSectionRootProps = MenuItemRootProps & {

/** A `MenuItem.Root` that spans the full width of a `Section`, ignoring the section's own horizontal padding */
function MenuItemSectionRoot({children, onPress, isDisabled = false, sentryLabel, testID, accessibilityLabel, ref}: MenuItemSectionRootProps) {
const styles = useThemeStyles();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const {cardEdgeToEdge, cardMenuItemInset} = useLayoutSpacing();

return (
<View
ref={ref}
style={shouldUseNarrowLayout ? styles.mhn5 : styles.mhn8}
style={cardEdgeToEdge}
>
<MenuItemRoot
onPress={onPress}
Expand All @@ -31,7 +29,7 @@ function MenuItemSectionRoot({children, onPress, isDisabled = false, sentryLabel
testID={testID}
accessibilityLabel={accessibilityLabel}
>
<View style={!shouldUseNarrowLayout && styles.ph3}>{children}</View>
<View style={cardMenuItemInset}>{children}</View>
</MenuItemRoot>
</View>
);
Expand Down
6 changes: 4 additions & 2 deletions src/components/MoneyReportHeaderActions/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {useMoneyReportTransactionThread} from '@components/MoneyReportTransactio
import {useSearchSelectionActions, useSearchSelectionContext} from '@components/Search/SearchContext';

import useExportAgainModal from '@hooks/useExportAgainModal';
import useLayoutSpacing from '@hooks/useLayoutSpacing';
import useOnyx from '@hooks/useOnyx';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useResponsiveLayoutOnWideRHP from '@hooks/useResponsiveLayoutOnWideRHP';
Expand Down Expand Up @@ -37,6 +38,7 @@ function narrowPrimaryAction(primaryAction: MoneyReportHeaderActionsProps['prima

function MoneyReportHeaderActions({reportID, primaryAction, isReportInSearch, backTo}: MoneyReportHeaderActionsProps) {
const styles = useThemeStyles();
const {pageGutter} = useLayoutSpacing();
const dropdownMenuRef = useRef<ButtonWithDropdownMenuRef>(null) as React.RefObject<ButtonWithDropdownMenuRef>;

const {shouldUseNarrowLayout, isMediumScreenWidth, isInLandscapeMode} = useResponsiveLayout();
Expand Down Expand Up @@ -73,7 +75,7 @@ function MoneyReportHeaderActions({reportID, primaryAction, isReportInSearch, ba
// actions stay in the header but are disabled while a selection is being built up.
if (shouldDisableReportActions && shouldUseNarrowLayoutOnWideRHP) {
return (
<View style={shouldDisplayNarrowMoreButton ? undefined : [styles.dFlex, styles.w100, styles.ph5, styles.pb3]}>
<View style={shouldDisplayNarrowMoreButton ? undefined : [styles.dFlex, styles.w100, pageGutter, styles.pb3]}>
<MoneyReportHeaderSelectionDropdown
reportID={reportID}
primaryAction={narrowedPrimaryAction}
Expand All @@ -85,7 +87,7 @@ function MoneyReportHeaderActions({reportID, primaryAction, isReportInSearch, ba
}

return (
<View style={[styles.flexRow, styles.gap2, ...(!shouldDisplayNarrowMoreButton ? [styles.pb3, styles.ph5, styles.w100, styles.alignItemsCenter, styles.justifyContentCenter] : [])]}>
<View style={[styles.flexRow, styles.gap2, ...(!shouldDisplayNarrowMoreButton ? [styles.pb3, pageGutter, styles.w100, styles.alignItemsCenter, styles.justifyContentCenter] : [])]}>
{!!primaryAction && (
<View style={!shouldDisplayNarrowMoreButton ? [styles.flex1] : undefined}>
<MoneyReportHeaderPrimaryAction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {isPolicyTaxEnabled} from '@libs/PolicyUtils';
import {canAddTransaction, getBillableAndTaxTotal, getMoneyRequestSpendBreakdown, getReportOfflinePendingActionAndErrors, isCurrentUserSubmitter} from '@libs/ReportUtils';
import {hasNonReimbursableTransactions} from '@libs/TransactionUtils';

import {resolveLayoutSpacing} from '@styles/layoutSpacing';

import {getAddExpenseDropdownOptions} from '@userActions/IOU/StartExpenseFlows';

import CONST from '@src/CONST';
Expand Down Expand Up @@ -58,6 +60,7 @@ function MoneyRequestReportListFooter({report, policy, transactions, hasPendingA
const {translate} = useLocalize();
const {convertToDisplayString} = useCurrencyListActions();
const {shouldUseNarrowLayout} = useResponsiveLayoutOnWideRHP();
const {pageGutter} = resolveLayoutSpacing(shouldUseNarrowLayout);
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Location', 'ReceiptPlus', 'Plus']);
const currentUserDetails = useCurrentUserPersonalDetails();
const isReportArchived = useReportIsArchived(report?.reportID);
Expand Down Expand Up @@ -109,7 +112,7 @@ function MoneyRequestReportListFooter({report, policy, transactions, hasPendingA
return (
<View style={[shouldUseNarrowLayout ? styles.pb2 : styles.pb4]}>
{showPendingExpensePlaceholder && (
<View style={styles.ph5}>
<View style={pageGutter}>
<SearchRowSkeleton
shouldAnimate
fixedNumItems={1}
Expand All @@ -125,7 +128,7 @@ function MoneyRequestReportListFooter({report, policy, transactions, hasPendingA
styles.flexRow,
shouldShowAddExpenseButton ? styles.justifyContentBetween : styles.justifyContentEnd,
styles.gap6,
styles.ph5,
pageGutter,
styles.mv2,
styles.alignItemsStart,
styles.minHeight7,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import useLocalize from '@hooks/useLocalize';
import useResponsiveLayoutOnWideRHP from '@hooks/useResponsiveLayoutOnWideRHP';
import useThemeStyles from '@hooks/useThemeStyles';

import {resolveLayoutSpacing} from '@styles/layoutSpacing';

import type * as OnyxTypes from '@src/types/onyx';

import type {StyleProp, ViewStyle} from 'react-native';
Expand Down Expand Up @@ -45,7 +47,8 @@ function MoneyRequestReportTotalSpend({
const isFocused = useIsFocused();
const shouldShowComments = hasComments || isLoadingReportActions;

const commentContainerStyle = [styles.ph5, styles.justifyContentBetween, styles.mb2];
const {pageGutter} = resolveLayoutSpacing(shouldUseNarrowLayout);
const commentContainerStyle = [pageGutter, styles.justifyContentBetween, styles.mb2];

return (
<View style={[styles.dFlex, styles.flexRow, styles.justifyContentEnd, shouldShowComments && commentContainerStyle]}>
Expand Down
Loading
Loading