Skip to content

[$250] mweb-cards-Minor visual glitch on navigating back from concierge to cards page #61668

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
1 of 8 tasks
mitarachim opened this issue May 8, 2025 · 15 comments
Open
1 of 8 tasks
Assignees
Labels
Daily KSv2 External Added to denote the issue can be worked on by a contributor Help Wanted Apply this label when an issue is open to proposals by contributors Overdue

Comments

@mitarachim
Copy link

mitarachim commented May 8, 2025

If you haven’t already, check out our contributing guidelines for onboarding and email [email protected] to request to join our Slack channel!


Version Number: V9.1.42-0
Reproducible in staging?: Yes
Reproducible in production?: No
If this was caught during regression testing, add the test name, ID and link from TestRail: https://expensify.testrail.io/index.php?/tests/view/6068249
Email or phone of affected tester (no customers): Slottwo1 [email protected]
Issue reported by: Applause Internal Team
Device used: Redminote note 10s android 13
App Component: Workspace Settings

Action Performed:

  1. Go to https://staging.new.expensify.com/home
  2. Go to workspace settings
  3. Tap company card - add card - american express - american express corporate card
  4. Complete the flow
  5. Tap concierge link
  6. Tap device back button

Expected Result:

Tapping device back button from concierge page, minor visual glitches (green) must not be seen in cards page briefly.

Actual Result:

Tapping device back button from concierge page, minor visual glitches (green) can be seen in cards page briefly. In production behaviour no green minor glitches.

Workaround:

Unknown

Platforms:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Bug6825294_1746689289225.Screenrecorder-2025-05-08-12-52-38-762.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021920420725439306402
  • Upwork Job ID: 1920420725439306402
  • Last Price Increase: 2025-05-15
Issue OwnerCurrent Issue Owner: @parasharrajat
@mitarachim mitarachim added DeployBlockerCash This issue or pull request should block deployment Daily KSv2 Bug Something is broken. Auto assigns a BugZero manager. DeployBlocker Indicates it should block deploying the API labels May 8, 2025
Copy link

melvin-bot bot commented May 8, 2025

Triggered auto assignment to @Gonals (DeployBlockerCash), see https://stackoverflowteams.com/c/expensify/questions/9980/ for more details.

Copy link

melvin-bot bot commented May 8, 2025

Triggered auto assignment to @dylanexpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

Copy link

melvin-bot bot commented May 8, 2025

💬 A slack conversation has been started in #expensify-open-source

@github-actions github-actions bot added Engineering Hourly KSv2 and removed Daily KSv2 labels May 8, 2025
Copy link
Contributor

github-actions bot commented May 8, 2025

👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:

  1. Identify the pull request that introduced this issue and revert it.
  2. Find someone who can quickly fix the issue.
  3. Fix the issue yourself.

@Gonals Gonals added Daily KSv2 External Added to denote the issue can be worked on by a contributor and removed DeployBlockerCash This issue or pull request should block deployment DeployBlocker Indicates it should block deploying the API Hourly KSv2 Engineering Daily KSv2 Bug Something is broken. Auto assigns a BugZero manager. labels May 8, 2025
@melvin-bot melvin-bot bot changed the title mweb-cards-Minor visual glitch on navigating back from concierge to cards page [$250] mweb-cards-Minor visual glitch on navigating back from concierge to cards page May 8, 2025
Copy link

melvin-bot bot commented May 8, 2025

Job added to Upwork: https://www.upwork.com/jobs/~021920420725439306402

@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label May 8, 2025
Copy link

melvin-bot bot commented May 8, 2025

Triggered auto assignment to Contributor-plus team member for initial proposal review - @parasharrajat (External)

@melvin-bot melvin-bot bot added the Daily KSv2 label May 8, 2025
@Gonals
Copy link
Contributor

Gonals commented May 8, 2025

Very, very minor Mobile-Chrome visual bug. Not blocking deploy on it

@bradyrose
Copy link

bradyrose commented May 8, 2025

Problem

When tapping the back button on the Concierge screen, the Workspace Company Cards page briefly flashes a bright‑green skeleton loader (from CardsSkeleton) before the real content and theme load. This glitch is visible in staging (mWeb Chrome on Android), but does not occur in production.


Root Cause

  • Unconditionally rendered skeleton: CardsSkeleton appears whenever isLoading === true, regardless of how the page was reached.
  • Premature remount: Navigation.goBack() causes Concierge to unmount and Cards to remount before theme/context hydration, leading to a flash of unstyled content.
  • Dev-only styling leakage: .placeholder { background-color: #0f0 } is not gated behind a development-only condition, so it leaks into staging CSS bundles.

Solution

1. Suppress Skeleton Loader on Back Navigation

Pass a flag (suppressPlaceholder) through navigation when leaving the Concierge screen:

// ConciergePage.tsx
<ReportHeaderSkeletonView
  onBackButtonPress={() => Navigation.goBack('WorkspaceCompanyCardsPage', { suppressPlaceholder: true })}
/>

// WorkspaceCompanyCardsPage.tsx
const { suppressPlaceholder } = useNavigationParams<{ suppressPlaceholder?: boolean }>();
if (isLoading && !suppressPlaceholder) {
  return <CardsSkeleton />;
}

2. Protect Dev-Only Green CSS

Update the skeleton styles to avoid bundling development-only styling in staging/production:

/* CardsSkeleton.module.css */
.placeholder {
  background-color: transparent;
}

@media all and (env(DEVELOPMENT)) {
  .placeholder {
    background-color: #0f0;
  }
}

3. Fade in Cards Page Content

Smooth the visual transition when content loads:

const fadeAnim = useRef(new Animated.Value(0)).current;

useEffect(() => {
  Animated.timing(fadeAnim, {
    toValue: 1,
    duration: 200,
    useNativeDriver: true,
  }).start();
}, []);

return (
  <Animated.View style={[styles.container, { opacity: fadeAnim }]}>
    {/* Card list and content */}
  </Animated.View>
);

4. Wait for Theme Hydration Before Render

Block rendering of UI until theming is ready:

const { isHydrated } = useTheme();
if (!isHydrated) {
  return <NeutralSpinner />;
}

Tests

  • Back-nav skeleton suppression: Simulate Concierge → Cards with suppressPlaceholder, assert no .placeholder appears in the DOM.
  • Skeleton snapshot: Validate rendering of CardsSkeleton with and without the param.
  • CSS validation: Ensure .placeholder { background-color: #0f0 } does not appear in production CSS bundles.
  • Hydration gate test: Confirm NeutralSpinner appears during unhydrated state and fades into real content.

Alternatives Considered

  • Delay navigation until hydration: Introduced noticeable UX lag and complexity.
  • Remove skeleton entirely: Degraded user feedback during loading.
  • Persist old route DOM: Risked stale rendering and mismatched context.

Supporting Info: goBack() Param Support

To implement the suppression param, we verified that Expensify's goBack function supports an optional route and param object:

// src/libs/Navigation/Navigation.ts
export function goBack(route?: string, options?: { compareParams: boolean }) {
  try {
    if (!navigationRef.current?.canGoBack()) return;
    navigationRef.current.goBack(route, options);
  } catch (err) {
    Log.warn('[Navigation] goBack error:', err);
  }
}

This param is already used in places like useSafeBackHandler:

// src/hooks/useSafeBackHandler.js
export default function useSafeBackHandler(navigation, customRoute) {
  // ...
  navigation.goBack(customRoute);
  // ...
}

And in components like CategorySettings.js, you can pass it like this:

const backTo = route.params?.backTo ?? 'Settings';
useSafeBackHandler(navigation, backTo);

So it’s safe and idiomatic to forward a param like { suppressPlaceholder: true } during navigation.


Next Steps

Happy to submit a PR implementing this solution with full test coverage within 24 hours.

Copy link

melvin-bot bot commented May 12, 2025

@parasharrajat Whoops! This issue is 2 days overdue. Let's get this updated quick!

@melvin-bot melvin-bot bot added the Overdue label May 12, 2025
@parasharrajat
Copy link
Member

@bradyrose Did you check whether our goBack method supports custom param?

@melvin-bot melvin-bot bot removed the Overdue label May 12, 2025
@bradyrose
Copy link

bradyrose commented May 12, 2025

Hey @parasharrajat, goBack utility does support an optional route/param. In src/libs/Navigation/Navigation.ts, you'll see:

export function goBack(route?: string, options?: { compareParams: boolean }) {
    try {
        if (!navigationRef.current?.canGoBack()) return;
        navigationRef.current.goBack(route, options);
    } catch (err) {
        Log.warn('[Navigation] goBack error:', err);
    }
}

So in our useSafeBackHandler hook we can simply forward whatever param you pass in:

// src/hooks/useSafeBackHandler.js
export default function useSafeBackHandler(navigation, customRoute) {
    // …
    navigation.goBack(customRoute);
    // …
}

And then in a screen that needs a custom back target:

// e.g. CategorySettings.js
const backTo = route.params?.backTo ?? 'Settings';
useSafeBackHandler(navigation, backTo);

That way, you preserve any custom route while still debouncing rapid back‑presses.

@parasharrajat
Copy link
Member

@bradyrose Please use ``` for formatting the code snippet. It is easy to read that way.

@bradyrose
Copy link

@parasharrajat Updated and folded details into proposal. Thanks.

Copy link

melvin-bot bot commented May 15, 2025

📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸

Copy link

melvin-bot bot commented May 20, 2025

@parasharrajat Eep! 4 days overdue now. Issues have feelings too...

@melvin-bot melvin-bot bot added the Overdue label May 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Daily KSv2 External Added to denote the issue can be worked on by a contributor Help Wanted Apply this label when an issue is open to proposals by contributors Overdue
Projects
None yet
Development

No branches or pull requests

5 participants