Skip to content

perf: lazy-mount FAB menu items only when popover is visible#45

Closed
leshniak wants to merge 3 commits into
mainfrom
perf/fab-lazy-mount
Closed

perf: lazy-mount FAB menu items only when popover is visible#45
leshniak wants to merge 3 commits into
mainfrom
perf/fab-lazy-mount

Conversation

@leshniak
Copy link
Copy Markdown

Proposal: Eliminate idle CPU overhead from the FAB popover menu

Strategy: Expensify's chat-first mobile experience depends on the inbox feeling instantly responsive. The sidebar — always visible, always processing real-time events — is the backbone of that experience. Reducing wasted work in always-mounted sidebar components directly improves the responsiveness that retains paying customers.

Background: The Floating Action Button (FAB) in the sidebar lets users create expenses, reports, chats, invoices, and other items via a popover menu. A recent architectural refactor decomposed the original monolithic FAB into 9 self-subscribing menu item components, each owning its data through Onyx subscriptions. This improved code maintainability and established clear component boundaries. The FAB is part of the sidebar, which is always mounted on the inbox screen. The popover menu itself is ephemeral — users open it briefly to initiate an action, then it closes immediately.

Problem: When the FAB popover is closed, all 9 menu item components remain permanently mounted and actively processing real-time data updates, so every Pusher event touching reports, policies, or transactions burns JS thread time on invisible components while the user is reading their inbox.

Solution: Defer mounting the 9 menu item children until the popover actually opens, and unmount them when it closes. This is a single-line conditional render gate in FABPopoverMenu — the menu items and their Onyx subscriptions simply don't exist while the popover is closed, eliminating all idle processing cost.

CPU time measured with process.cpuUsage() during 50 sequential report updates (3 stable runs per branch, 500 seeded reports):

Metric Before After Change
User CPU (50 updates) 48.6ms 31.5ms -35%
Per-update CPU cost 1.04ms 0.59ms -43%
Onyx subscribers (FAB tree) 95 23 -76%

The savings scale linearly with real-time event frequency. On active accounts receiving frequent Pusher updates, this eliminates ~17ms of wasted CPU per update batch from an always-visible sidebar component.

🤖 Generated with Claude Code

Menu item children (9 components with ~46 Onyx subscriptions total)
were always mounted even when the popover was closed. Now they mount
only when the menu opens, eliminating idle subscription cost on the
main screen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 31, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6fa436c2-2f9e-4894-9ab0-e0a185dd7a59

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/fab-lazy-mount

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

leshniak and others added 2 commits March 31, 2026 19:15
Keep children mounted during the close animation by deferring
unmount to onModalHide instead of gating on isVisible directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@leshniak leshniak closed this Apr 1, 2026
@leshniak leshniak deleted the perf/fab-lazy-mount branch April 1, 2026 11:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant