Skip to content

Fix edit composer height to match the main composer - #99193

Open
MelvinBot wants to merge 2 commits into
mainfrom
claude-editComposerHeight
Open

Fix edit composer height to match the main composer#99193
MelvinBot wants to merge 2 commits into
mainfrom
claude-editComposerHeight

Conversation

@MelvinBot

@MelvinBot MelvinBot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

Deploy blocker: the message edit composer renders slightly taller than the main composer (introduced in 9.4.58, staging-only).

Root cause: PR #98781 grew the shared composerSizeButton from 32×32 to 40×40. The edit composer's cancel (X) button — unlike the main composer's + button, which is absolutely positioned and contributes no height — sits in normal flow and additionally adds marginVertical: composerSizeButton.marginHorizontal (3px). Its vertical footprint therefore became 40 + 3 + 3 = 46px, which exactly equals the compose box's content area (minHeight componentSizeMedium = 48, minus the 2px border). With zero slack, sub-pixel rounding pushes the edit compose box just past 48px, while the main composer stays pinned at 48px. At the old 32px size there was 8px of slack, so production is unaffected.

Fix: drop the extra marginVertical on the cancel button so its footprint (40px) sits well inside the 46px content area. composerSizeButton already has alignSelf: 'center', so the button stays vertically centered, and minHeight: 48 still floors the box — so the edit composer can't become shorter than the main composer either. This is the minimal change that removes the asymmetry the offending PR introduced.

Fixed Issues

$ #99143
PROPOSAL:

Tests

  1. Open a chat and send a single-line message.
  2. Note the height of the main composer.
  3. Open the edit composer on that message (press the keyboard Up arrow on web/desktop, or long-press the message → Edit comment on mobile).
  4. Verify the edit composer is the same height as the main composer (no longer slightly taller).
  • Verify that no errors appear in the JS console

Offline tests

N/A — this is a purely presentational (layout/sizing) change with no network dependency.

QA Steps

Same as tests.

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
Main composer Edit composer

Pixel-level comparison confirmed the composer border box is identical (same top/bottom coordinates, ~125px tall) in both the main and edit composer.

Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
Main composer Edit composer

Edit composer renders at single-line height, matching the main composer.

Co-authored-by: Shawn Borton <shawnborton@users.noreply.github.com>
@MelvinBot
MelvinBot requested a review from a team August 21, 2026 15:14
@melvin-bot melvin-bot Bot added Melvin-Test-Android Melvin-Test-Web Triggers Melvin to run the testing steps of the PR on web labels Aug 21, 2026
@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ Changes either increased or maintained existing code coverage, great job!

Files with missing lines Coverage Δ
...rt/ReportActionCompose/MessageEditCancelButton.tsx 100.00% <100.00%> (ø)
...pages/inbox/report/ReportActionItemMessageEdit.tsx 58.33% <ø> (ø)
src/styles/index.ts 63.00% <ø> (ø)
... and 111 files with indirect coverage changes

@MelvinBot

Copy link
Copy Markdown
Contributor Author

✅ Android test passed

Ran the testing steps on standalone Android NewDot. The edit composer now renders the same height as the main composer — no visible extra tallness in edit mode.

Steps performed:

  1. Sent a single-line message in a chat.
  2. Captured the main composer at rest.
  3. Long-pressed the message → Edit comment to open the inline edit composer.
  4. Captured the edit composer and compared heights.

Verification (pixel-level, not eyeballed): Sampling the composer's green border column at screen center in both screenshots, the pill's top border sat at y≈2146–2148 and bottom border at y≈2269–2271 in both images — a pixel-identical bounding box (~125px tall) in the same absolute position. No height discrepancy, and no JS console errors.

Evidence

Main composer at rest after sending a single-line message

Main composer at rest after sending a single-line message

Edit composer opened via long-press > Edit comment, showing same height as main composer

Edit composer opened via long-press > Edit comment, showing same height as main composer


view run

@github-actions

Copy link
Copy Markdown
Contributor

🚧 shawnborton has triggered a test Expensify/App build. You can view the workflow run here.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

⚠️ Web test blocked by tooling — could not open the edit composer

I signed in, opened a chat, and sent a single-line message on dev NewDot web, but I could not complete the actual verification (comparing the edit composer height to the main composer). The blocker is a limitation of the web automation harness, not an app bug.

What I verified:

  • ✅ Opened a chat and sent a single-line message.
  • ✅ Captured the main composer at rest.

Why the edit composer couldn't be opened: every entry point into the inline edit composer requires an input primitive that agent-device --platform web doesn't expose in this environment:

  • Keyboard Up arrow — no raw key-dispatch verb exists on web (type only inserts literal characters).
  • Hover → "Edit comment" — the message hover toolbar (the ... menu) only mounts on a real hover state, which the web harness can't simulate; it never appeared in the DOM/accessibility tree after clicking.
  • Right-click context menuclick --button secondary returns a hard UNSUPPORTED_OPERATION on this web session (coordinate- and ref-independent), and longpress is unsupported on web.

Since the composer-height fix can only be seen once the edit composer is open, I can't produce web screenshots proving the test case here. This needs a manual QA pass on web (or Playwright), where the Up-arrow / hover / right-click entry points work.

For reference, the same test passed on Android — the edit composer rendered pixel-identical in height to the main composer.

Evidence (web, partial)

Main composer with unsent single-line text

Main composer with unsent single-line text

Main composer after sending the message in the chat

Main composer after sending the message in the chat


view run

@shawnborton

Copy link
Copy Markdown
Contributor

Testing well on my end:
CleanShot 2026-08-21 at 11 48 28@2x

@MelvinBot please mark the PR as ready for review, fill out PR author checklist as best you can and add screenshots

@MelvinBot
MelvinBot marked this pull request as ready for review August 21, 2026 16:00
@MelvinBot
MelvinBot requested a review from a team as a code owner August 21, 2026 16:00
@melvin-bot
melvin-bot Bot requested a review from Eskalifer1 August 21, 2026 16:00
@melvin-bot

melvin-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown

@Eskalifer1 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot
melvin-bot Bot requested review from JmillsExpensify and removed request for a team August 21, 2026 16:00
@MelvinBot

Copy link
Copy Markdown
Contributor Author

Done, shawnborton 🎉

  • Marked the PR ready for review (out of draft).
  • Filled out the PR Author Checklist as best I could, and added concrete Tests / QA Steps.
  • Added screenshots to the Screenshots/Videos section:
    • Android: Native — main vs. edit composer (pixel-verified identical height in my earlier test).
    • MacOS: Chrome / Safari — main composer + the edit-composer screenshot you posted.

A few checklist items I left unchecked because they need a human or weren't covered:

  • Offline / failure-scenario / High Traffic account steps (this is a purely presentational sizing change, so I marked offline as N/A).
  • Platform coverage beyond Android: Native and MacOS: Chrome/Safari — iOS Native, iOS mWeb Safari, and Android mWeb Chrome haven't been tested, so those boxes and screenshot sections are still empty.
  • The Design label / @Expensify/design tag — since this is a UI sizing change, you may want to add that.

Note: I couldn't automate the edit composer interaction on web (the web driver has no hover / Up-arrow primitive), so the web edit-composer evidence relies on your screenshot rather than an automated capture. The Android path was fully automated and pixel-verified.


view run

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8003cfdd65

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// button within the compose box (minHeight componentSizeMedium) instead of adding vertical margin.
// The extra marginVertical left zero slack once composerSizeButton grew to 40px, which let the edit
// compose box round up past the main composer's height. See https://github.com/Expensify/App/issues/99143
const closeButtonStyles = [styles.composerSizeButton];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep the inline cancel button vertically centered

When editing an inline message, the button's wrapper uses justifyContent: 'flex-end' (ReportActionItemMessageEdit.tsx:419), so composerSizeButton.alignSelf only centers the button horizontally within that column and does not center it vertically. Removing the 3px vertical margins leaves the 40px button against the bottom of the 46px content area, placing it 3px below the main composer's action button; preserve equivalent inner spacing without contributing to the compose box's outer height.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yep, we should choose another approach

Image

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@MelvinBot can you please review this feedback?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The feedback is correct — this needs a different approach. Removing marginVertical fixes the height, but it drops the cancel (X) button to the bottom of the compose box so it's no longer vertically centered (~3px low), which is what Eskalifer1's screenshot shows.

Why alignSelf doesn't save us here: the cancel button is wrapped in <View style={styles.justifyContentEnd}>. A React Native View defaults to flexDirection: 'column', so on that wrapper justifyContent: 'flex-end' controls the vertical (main) axis and pins the button to the bottom. composerSizeButton's alignSelf: 'center' (styles/index.ts:2558) only affects the horizontal (cross) axis in a column — it never vertically centers. So the code comment I added at MessageEditCancelButton.tsx:33-36 is mistaken on that point. The old marginVertical: 3 was exactly what produced the 3px bottom gap that made the button look centered.

Recommended fix: keep the height win (button footprint drops from 46px → 40px, restoring slack), but move the 3px of vertical spacing off the button and onto the wrapper, where it won't feed the compose box's intrinsic min-height:

  • Add paddingBottom: 3 (i.e. composerSizeButton.marginHorizontal) to the cancel wrapper while keeping justifyContent: 'flex-end'. The wrapper is already height-stretched by the row (alignItems: stretch), so padding doesn't grow the box — its intrinsic content becomes 40 + 3 = 43px, still comfortably under the 46px content area. This restores the 3px gap (centered at single line) and keeps the button bottom-pinned for multiline, consistent with the Submit button's alignSelfEnd wrapper.

That preserves the height fix from #99143 without the vertical-centering regression.

For the record: my earlier Android pass verified the compose box height was pixel-identical, but it didn't measure the X button's position within the box — which is why this slipped through.

Want me to implement the paddingBottom change? Reply @MelvinBot implement the paddingBottom fix and I'll push it to this branch.


view run

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@Eskalifer1 can you advise how you would like Melvin to fix this one?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@MelvinBot implement the paddingBottom fix

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done — pushed the paddingBottom fix in 359ca54.

What changed:

  • Added a dedicated wrapper style messageEditCancelButtonWrapper (justifyContent: 'flex-end' + paddingBottom: 3) and applied it to the cancel button wrapper at ReportActionItemMessageEdit.tsx:419.
  • The button keeps its marginVertical removed (height fix intact), and the 3px now lives on the wrapper as padding. Since the wrapper is height-stretched by the row, padding doesn't grow the compose box — intrinsic content is 40 + 3 = 43px, still under the 46px content area — so it restores the 3px gap that centers the X on a single line and stays bottom-pinned for multiline.
  • Also corrected the now-inaccurate code comment in MessageEditCancelButton.tsx (it wrongly claimed alignSelf handled vertical centering).

Checks: ESLint (0 new errors), typecheck (no src errors), oxfmt, and unused-styles all pass. React Compiler introduces no new errors — the pristine base fails with the identical 6 pre-existing ref-access errors, so my change adds none. The Jest suite couldn't bootstrap in this environment (a jest/setup.ts module-resolution failure that hits every test), and the web runtime check was blocked by a stuck/blank browser session — both infra issues, not related to this CSS change.

A reviewer should still eyeball the edit composer on web to confirm the X button now sits centered.


view run

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi @shawnborton i will take a look at Monday, maybe i will find better fix, since i think this approach is more like a workaround

@MelvinBot

Copy link
Copy Markdown
Contributor Author

The two failing checks aren't code issues — they're process gates that only a human reviewer can clear, so there's nothing for me to push a fix for. Every code, build, lint, type, and test check is passing. ✅

Failing check Why it's failing
PR Reviewer Checklist / checklist Fails until a reviewer opens the PR and completes the reviewer checklist.
Check independent approval Fails until an independent reviewer approves the PR.

Next step: get a reviewer to complete the checklist and approve — both checks will flip green on their own. No branch changes needed.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Same situation as before — the only two failing checks aren't code issues, so there's still nothing to push a fix for. All code, build, lint, type, and test checks are green. ✅

Failing check Why it's failing
PR Reviewer Checklist / checklist Fails until a reviewer opens the PR and completes the reviewer checklist.
Check independent approval Fails until an independent reviewer approves the PR.

Next step: these clear only through review — a reviewer needs to complete the checklist and approve. Re-running me won't change anything since there's no code fix involved.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Still the same two — and neither is something I can push a fix for. All code, build, lint, type, and test checks are green. ✅

  • PR Reviewer Checklist / checklist — fails until a reviewer opens the PR and completes the reviewer checklist.
  • Check independent approval — fails until an independent reviewer approves.

These are human-review gates, not code failures. Get a reviewer to complete the checklist and approve, and both will turn green on their own — no branch changes needed.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Same as my earlier comment — nothing has changed, and there's still no code fix to push. The only two failing checks are human process gates:

  • PR Reviewer Checklist / checklist — waiting on a reviewer to complete the reviewer checklist
  • Check independent approval — waiting on an independent reviewer's approval

Every code, build, lint, type, and test check is passing. ✅ These two will go green once a reviewer completes the checklist and approves — re-running me won't move them.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Nothing to fix here — the only two failing checks are human-review gates, and every code, build, lint, type, and test check is passing. ✅

Failing check Why it's failing
PR Reviewer Checklist / checklist Fails until a reviewer opens the PR and completes the reviewer checklist.
Check independent approval Fails until an independent reviewer approves the PR.

There's no branch change I can push to clear these. Next step: get a reviewer to complete the checklist and approve — both checks flip green on their own.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Still the same two checks, and they're unchanged since my previous comment — both are human-only process gates, not code-fixable, so there's nothing for me to push:

  • PR Reviewer Checklist / checklist — clears once a reviewer completes the reviewer checklist.
  • Check independent approval — clears once an independent reviewer approves.

Every code, build, lint, type, and test check is passing. ✅ The only way to turn these two green is a reviewer completing the checklist and approving — no branch changes will move them.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Same result as before — there's no code fix to push. The only two failing checks are process gates that require a human, and every code, build, lint, type, and test check is passing. ✅

Failing check Why it's failing
PR Reviewer Checklist / checklist Fails until a reviewer opens the PR and completes the reviewer checklist.
Check independent approval Fails until an independent reviewer approves the PR.

Next step: have a reviewer complete the checklist and approve — both checks flip green automatically. Nothing needs to change on the branch.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Re-checked — same result as before. The only two failing checks are process gates that a human reviewer has to clear, not anything I can fix by pushing code. Every code, build, lint, type, and test check is green. ✅

Failing check Why it's failing
PR Reviewer Checklist / checklist Fails until a reviewer opens the PR and completes the reviewer checklist.
Check independent approval Fails until an independent reviewer approves the PR.

Next step: have a reviewer complete the checklist and approve — both checks flip green on their own. There's no branch change to push.


view run

Co-authored-by: Shawn Borton <shawnborton@users.noreply.github.com>
@MelvinBot
MelvinBot requested review from a team as code owners August 22, 2026 13:49
@melvin-bot
melvin-bot Bot requested review from mollfpr and removed request for a team August 22, 2026 13:49
@melvin-bot

melvin-bot Bot commented Aug 22, 2026

Copy link
Copy Markdown

@mollfpr Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@MelvinBot

Copy link
Copy Markdown
Contributor Author

The only failing check now is Check independent approval, which isn't code-fixable — it stays red until an independent reviewer approves the PR. Every code, build, lint, type, and test check is passing. ✅

There's nothing for me to push here — the check will flip green on its own once the PR gets an independent approval. No branch changes needed.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Still the same two checks, and neither is code-fixable — there's nothing for me to push. All code, build, lint, type, and test checks are passing. ✅

Failing check Why it's failing
PR Reviewer Checklist / checklist Fails until a reviewer opens the PR and completes the reviewer checklist.
Check independent approval Fails until an independent reviewer approves the PR.

Next step: these are human review gates. Once a reviewer completes the checklist and gives an independent approval, both flip green on their own. No branch changes needed from me.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Same situation as before — the only two failing checks are process gates, not anything I can fix by pushing code. Every code, build, lint, type, and test check is passing. ✅

Failing check Why it's failing
PR Reviewer Checklist / checklist Fails until a reviewer opens the PR and completes the reviewer checklist.
Check independent approval Fails until an independent reviewer approves the PR.

There's no code fix to push here — these clear only when a human reviewer completes the checklist and approves. Once that happens, both flip green on their own.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Still nothing code-fixable here — the only two failing checks are human-review gates, and every code, build, lint, type, and test check is passing. ✅

Failing check Why it's failing Who clears it
PR Reviewer Checklist / checklist The reviewer checklist hasn't been completed yet. A reviewer completes the checklist.
Check independent approval No independent reviewer approval yet. An independent reviewer approves.

Neither is resolved by pushing to the branch, so there's no fix for me to commit. Once a reviewer completes the checklist and approves, both will turn green on their own.


view run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Melvin-Test-Android Melvin-Test-Web Triggers Melvin to run the testing steps of the PR on web

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants