Skip to content

[$175] Web-Home- The empty center of Home Insights pie chart is clickable #104771

Open

Description

@applause-bot

If you haven’t already, check out our contributing guidelines for onboarding. To join our Slack channel, fill out this form.


Version Number: v9.5.16-1
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from BrowserStack: #103457
Email or phone of affected tester (no customers): gd868gd+30@gmail.com
Issue reported by: Applause Internal Team
Bug source: Pull Request QA execution
Device used: Desktop / Windows 11
App Component: Left Hand Navigation (LHN)

Action Performed:

Precondition: Have a workspace with several expenses.

  1. Open the Expensify Web App and log in
  2. Scroll to the Insights card on the Home screen
  3. Click on the dropdown menu and switch to "Top categories"
  4. Click on the empty center of the pie chart

Expected Result:

Nothing should happen.

Actual Result:

The empty center of the pie chart is clickable in the Insights card on the Home screen.
The user is redirected to the Insights tab.

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

Bug7293442_1792683462618.Expensify_PR103457_Pie_Chart_Web.mp4

View all open jobs on GitHub

Applause Internal Information
Exported by: Julia Ponikarchuk
Bug ID: 7293442

Upwork Automation - Do Not Edit

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Oct 22, 2026
  2. applause-bot commented on Oct 22, 2026

    @applause-bot
    Author

    While Applause doesn't embed attachments for this bug, here are the links for quick view:
    https://platform.applause.com/services/links/v1/external/e32eb671849771810e802d0f3e219e74c8e93a2b85178ce9df0383b80d4bc657

  3. MelvinBot commented on Oct 22, 2026

    @MelvinBot
    Contributor

    Issue Analysis

    Root Cause: This is expected behavior with the insightsPage beta on, not a bug in the pie chart. InsightsSectionContent.tsx:112-124 wraps the whole Home Insights card in a pressable that opens the Insights page. The donut hole is part of the card, so clicking it navigates.

    [NoQA] [Insights] Clicking anywhere on the Insight slot on Home should take you to the Insights page added this on purpose for [Insights] [R1] Clicking anywhere on the Insight slot on Home should take you to the Insights page.

    Recommended Fix: Don't change code. Close this issue as expected behavior. The QA step in Migrate chart gestures to Gesture Handler 3 hooks ("click the empty center, nothing happens") only holds with the beta off. The tester's account most likely had the insightsPage beta on.

    Investigation details
    • The pie ignores the hole correctly. Charts/utils/index.ts:228-230 returns -1 (no slice) for clicks inside the inner radius. PieChartContent.tsx:187-192 only handles a press when a slice is hit.
    • The card handles the click instead. With the beta on, the chart gets shouldDrillDownOnPress={false} (InsightsSectionContent.tsx:105), so the chart has no press handler. The click reaches the card's PressableWithoutFeedback, which calls navigateToInsights (lines 61-64).
    • Every area of the card behaves the same. Slices, the legend, blank padding and the hole all open Insights. PR [NoQA] [Insights] Clicking anywhere on the Insight slot on Home should take you to the Insights page #103592's tests explicitly check "click an empty area of the chart, verify the Insights page opens."
    • Why it reproduces on production: the wrapper predates the gesture migration PR, which didn't change this logic.
    • Touch devices are excluded. The wrapper is skipped when canUseTouchScreen() is true, so this only shows on desktop web.
    • With the beta off: the card isn't pressable, slice clicks open filtered Search, and clicking the hole does nothing, which matches the issue's expected result.

    If product wants the hole to do nothing even with the beta on: remove the card-level wrapper from the chart body. Then pass a navigate-to-Insights press handler into the chart from SearchChartView.tsx:138 instead of undefined. The pie's hit-test would then skip the hole on its own. Bar and line charts would need the same change. This reverses part of PR #103592, so it needs a product decision first.


    Next Steps: Reply with @MelvinBot <your feedback> to refine this analysis. If product wants the hole to do nothing even with the beta on, reply with @MelvinBot implement this to create a draft PR for the alternative above.


    view run

  4. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Oct 22, 2026
  5. melvin-bot commented on Oct 22, 2026

    @melvin-bot

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

  6. Abdallah-1551 commented on Oct 22, 2026

    @Abdallah-1551

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    On the Home page Insights card, the "Top categories" view shows a donut-style pie chart with an empty center. Clicking that empty center redirects the user to the Insights tab. Only the colored slices should respond to clicks and hover, so clicking the hole should do nothing.

    What is the root cause of that problem?

    I could not inspect the code, and the discussion has no analysis, so this is an inference. It matches the symptom (the click is treated as a slice press, not as a miss).

    The chart's press handling does not check the radial distance of the pointer. It most likely maps the pointer position to a slice using only the angle from the chart center (atan2(y - cy, x - cx)) and then calls the slice's onPress, which navigates to Insights (the Search page grouped by category). It never checks that the point lies between the donut's innerRadius and its outer radius. Every point inside the chart's bounding box therefore resolves to some slice, including the hole in the middle.

    Whichever component owns the handler, the underlying fault is the same: the hit test is angle-only and has no ring-bounds check.

    What changes do you think we should make in order to solve the problem?

    1. Add a radial bounds check to the slice hit-test. This is in the Charts pie component, likely src/components/Charts/PieChart/PieChartContent.tsx or its util file. Return "no slice" when the pointer is inside the hole or outside the outer radius:
    function getSliceIndexAtPoint(
        x: number,
        y: number,
        cx: number,
        cy: number,
        innerRadius: number,
        outerRadius: number,
        slices: Array<{startAngle: number; endAngle: number}>,
    ): number {
        const dx = x - cx;
        const dy = y - cy;
        const distance = Math.hypot(dx, dy);
    
        // Ignore clicks in the empty center or outside the ring
        if (distance < innerRadius || distance > outerRadius) {
            return -1;
        }
    
        let angle = Math.atan2(dy, dx);
        // normalize to the same range/origin the slices use
        angle = (angle + 2 * Math.PI) % (2 * Math.PI);
    
        return slices.findIndex((s) => angle >= s.startAngle && angle < s.endAngle);
    }
    1. Make the press handler a no-op on a miss.
    const handlePress = (e) => {
        const index = getSliceIndexAtPoint(...);
        if (index < 0) {
            return;
        }
        onSlicePress?.(slices[index]);
    };
    1. Keep the hover and cursor behavior consistent. Use the same hit-test for the hover and active-slice state. The pointer cursor and tooltip should show only over a slice, not over the hole. If the chart is wrapped in a PressableWithoutFeedback or Pressable that navigates on press, move the onPress down to the slice level or guard it with the hit-test result. The wrapper should not turn the whole bounding box into a link.

    2. Derive innerRadius and outerRadius from the single source of truth used for rendering (the same constants or props passed to the Skia/SVG pie). The hit area and the drawn ring can then never drift apart.

    What alternative solutions did you explore? (Optional)

    • pointerEvents="none" on a view overlaying the center. This is a quick hack, but it is fragile across web and native and depends on layout and size. It would not fix the angle-only hit-test logic, so I rejected it.
    • Render the center as a separate non-interactive element that swallows clicks (for example a View with an onPress no-op). This adds extra DOM and still leaves the incorrect hit-test in place, so I rejected it.
    • Drop the click-to-navigate behavior. This is a product change and out of scope.

    Testing

    1. On web (Chrome, Windows/Mac), use an account with a workspace that has several expenses. On Home, open the Insights card and switch the dropdown to "Top categories".
    2. Click the exact center of the donut. Nothing should happen: no navigation, no tooltip, and the cursor stays default.
    3. Click on a colored slice. It should still navigate to Insights, filtered or grouped as before.
    4. Click just inside the inner edge and just outside the outer edge of the ring. Inside the inner edge should do nothing. Just outside the outer edge should do nothing either. Clicks on the ring itself should work.
    5. Hover over the hole, the ring, and outside the chart. The pointer cursor and tooltip should appear only over slices.
    6. Check different data sets (1 slice, 2 slices, many slices, "Other" slice) and resize the window to confirm the radii remain aligned with the rendering.
    7. Add a unit test for getSliceIndexAtPoint. It should return -1 for points at distance < innerRadius and > outerRadius, and the correct index for points on the ring at various angles, including the wrap-around at 0/2π.
  7. changed the title [-]Web-Home- The empty center of Home Insights pie chart is clickable[/-] [+][$175] Web-Home- The empty center of Home Insights pie chart is clickable[/+] on Oct 22, 2026
  8. melvin-bot commented on Oct 22, 2026

    @melvin-bot
  9. camesenin commented on Oct 22, 2026

    @camesenin

    Proposal

    Problem

    In the Insights card on the Home screen, clicking on the empty center of the Top categories / Top merchants pie chart (donut hole) redirects the user to the Insights tab, instead of doing nothing.

    Root Cause

    1. In src/pages/home/InsightsSection/InsightsSectionContent.tsx (lines 112–124):
    if (!isInsightsPageEnabled || canUseTouchScreen()) {
        return widget;
    }
    
    return (
        <PressableWithoutFeedback
            accessible={false}
            onPress={navigateToInsights}
            sentryLabel={CONST.SENTRY_LABEL.HOME_PAGE.WIDGET_ITEM}
        >
            {widget}
        </PressableWithoutFeedback>
    );

    When isInsightsPageEnabled is true (PR #103592), the entire Home Insights widget is wrapped inside PressableWithoutFeedback with onPress={navigateToInsights}, which is intended so that clicking on the card navigates to the Insights page.
    On the Home screen, SearchChartView is passed shouldDrillDownOnPress={!isInsightsPageEnabled} (i.e. false).
    In src/components/Search/SearchChartView.tsx:

    const onItemPress = shouldDrillDownOnPress ? handleItemPress : undefined;

    For BarChart and LineChart, their interactions hook useChartInteractions configures useTapGesture with:

    enabled: !!handlePress || shouldPinTooltipOnTouch,
    1. However, in src/components/Charts/PieChart/PieChartContent.tsx:
      In PR Migrate chart gestures to Gesture Handler 3 hooks #103457 (Migrate chart gestures to Gesture Handler 3 hooks), the tap gesture was migrated to useTapGesture:
    const tapGesture = useTapGesture({
        onFinalize: onTapFinalize,
        onDeactivate: (e) => {
            'worklet';
    
            if (e.pointerType === PointerType.TOUCH) {
                hoverAt(e.x, e.y);
                scheduleOnRN(setIsTouchPinned, matchedIndex.get() >= 0);
                return;
            }
    
            const {centerX, centerY} = pieGeometry;
            const sliceIndex = findSliceAtPosition(e.x, e.y, centerX, centerY, radius, innerRadius, processedSlices);
    
            if (sliceIndex >= 0) {
                scheduleOnRN(handleSlicePress, sliceIndex);
            }
        },
    });

    findSliceAtPosition (in src/components/Charts/utils/index.ts:228-230) correctly checks:

    if (distance < innerRadius || distance > radius) {
        return -1;
    }

    When clicking the empty center of the donut, sliceIndex is -1. Since sliceIndex < 0, handleSlicePress is not invoked.
    Because useTapGesture in PieChartContent.tsx does not swallow or capture the non-slice tap when no slice is hit on web (and onSlicePress is undefined), the click event bubbles straight up to the parent PressableWithoutFeedback wrapping the entire InsightsSectionContent widget, triggering navigateToInsights.

    Moreover, the center total label in PieChartContent.tsx:

    <View
        pointerEvents="none"
        style={styles.pieChartCenterLabel}
    >

    explicitly has pointerEvents="none", allowing any click directly in the center to pass directly through the chart container to the outer PressableWithoutFeedback.

    Solution

    To prevent clicks in the empty center of the donut from bubbling to the outer widget pressable:

    1. In src/components/Charts/PieChart/PieChartContent.tsx:
      Make the center area intercept pointer clicks and absorb them without propagating to the outer card link.
      Remove pointerEvents="none" from the center label container or add a transparent hit absorber view over the donut hole with an empty onPress / onClick or stopPropagation:
    <View
        style={styles.pieChartCenterLabel}
        onClick={(e) => {
            e.stopPropagation();
        }}
    >
        <Text style={[styles.textLabelSupporting, styles.textAlignCenter]}>{translate('common.total')}</Text>
        <Text
            numberOfLines={1}
            style={[styles.textHeadlineH1, styles.textAlignCenter]}
        >
            {totalFormatted}
        </Text>
    </View>

    Alternatively and cleanly across web and native:
    Inside useTapGesture in PieChartContent.tsx, ensure that clicks within the chart bounding box absorb the gesture:
    Or in PieChartContent.tsx, wrap the donut area with an inner container that prevents propagation when clicking the donut center:

    <View
        onClick={(e) => {
            // If clicking inside the donut center, prevent navigating the parent card
            e.stopPropagation();
        }}
        pointerEvents="auto"
        style={styles.pieChartCenterLabel}
    >
        <Text style={[styles.textLabelSupporting, styles.textAlignCenter]}>{translate('common.total')}</Text>
        <Text
            numberOfLines={1}
            style={[styles.textHeadlineH1, styles.textAlignCenter]}
        >
            {totalFormatted}
        </Text>
    </View>

    Alternative Solutions Explored

  10. khizzcr7 commented on Oct 22, 2026

    @khizzcr7

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    On the Home screen Insights card, switching the dropdown to "Top categories" and clicking the empty center of the donut pie chart navigates the user to the Insights page. Expected: clicking the empty center does nothing.

    What is the root cause of that problem?

    In src/pages/home/InsightsSection/InsightsSectionContent.tsx, the entire card content - including the chart - is wrapped in <PressableWithoutFeedback onPress={navigateToInsights}> (the non-touch-screen branch). The donut chart's empty center is a transparent region with no press handler of its own, so the click bubbles straight through to the card-level onPress and fires navigateToInsights. Only slices are meant to be interactive (via shouldDrillDownOnPress); the empty center has no slice under it, so there is nothing meaningful to drill into.

    What changes do you think we should make in order to solve the problem?

    1. Wrap the chart container (the donut chart rendered in the PressableWithoutFeedback branch of InsightsSectionContent.tsx) in its own press handler that stops propagation: onPress={(event) => event.stopPropagation()} on a transparent overlay view sized to the chart's empty center, so center clicks are swallowed before they reach navigateToInsights.
    2. Alternatively, check event.target in the card-level onPress and skip navigation when the press originated from the chart center region. The overlay approach is smaller and keeps the existing card navigation untouched for clicks anywhere else.
    3. Keep slice drill-down behavior unchanged.

    What alternative solutions did you explore?

    Removing the card-level pressable entirely would kill the intended navigation for the whole card; making the donut center non-transparent (pointer-events none) on web only would leave the native behavior inconsistent. The stop-propagation overlay fixes exactly the reported dead zone on both platforms.

    I will verify: the exact repro (Home -> Insights card -> Top categories -> click empty center - nothing happens); clicks on donut slices still drill down; clicks elsewhere on the card still navigate to Insights; narrow and wide layouts.

  11. ZhenjaHorbach commented on Oct 22, 2026

    @ZhenjaHorbach
    Contributor

    @Abdallah-1551 @camesenin @khizzcr7
    Stop posting proposals without Help Wanted label
    Otherwise, you can get a warning

  12. HamzaKhanBUIC commented on Oct 24, 2026

    @HamzaKhanBUIC

    Contributor details
    Your Expensify account email: hamza135252@gmail.com
    Upwork Profile Link: https://www.upwork.com/freelancers/~015055563b6090af39

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    On Web/Desktop, when viewing the Home screen Insights card with a donut pie chart (e.g., Top categories), clicking on the empty center area of the donut pie chart redirects the user to the Insights page. Clicking on the empty center hole should do nothing.

    What is the root cause of that problem?

    The issue is caused by a combination of two factors:

    1. Outer Card Navigation Wrapper (src/pages/home/InsightsSection/InsightsSectionContent.tsx lines 112–124):

      if (!isInsightsPageEnabled || canUseTouchScreen()) {
          return widget;
      }
      
      return (
          <PressableWithoutFeedback
              accessible={false}
              onPress={navigateToInsights}
              sentryLabel={CONST.SENTRY_LABEL.HOME_PAGE.WIDGET_ITEM}
          >
              {widget}
          </PressableWithoutFeedback>
      );

      When isInsightsPageEnabled is true and running on non-touch desktop web, the entire widget container is wrapped in a <PressableWithoutFeedback> that navigates to the Insights dashboard on press.

    2. Transparent Center Hole & Passthrough Pointer Events (src/components/Charts/PieChart/PieChartContent.tsx lines 255–261):

      <View
          pointerEvents="none"
          style={styles.pieChartCenterLabel}
      >
          <Text style={[styles.textLabelSupporting, styles.textAlignCenter]}>{translate('common.total')}</Text>
          ...
      </View>
      • In PieChartCanvas, the gesture handler (GestureDetector) uses findSliceAtPosition(e.x, e.y, centerX, centerY, radius, innerRadius, processedSlices). When clicking inside innerRadius (the donut hole), findSliceAtPosition returns -1. The gesture handler does not trigger handleSlicePress, but neither does it stop native DOM event propagation on Web.
      • Furthermore, the center label view explicitly sets pointerEvents="none".
      • Consequently, clicks in the empty center hole pass through the chart canvas and bubble unintercepted up to the card-level <PressableWithoutFeedback onPress={navigateToInsights}>, triggering unexpected navigation to the Insights page.

    What changes do you think we should make in order to solve the problem?

    We should stop click event propagation on the chart area so that non-slice clicks within the donut boundaries do not bubble up to the parent card navigation wrapper.

    In src/components/Charts/PieChart/PieChartContent.tsx:

    On Web, prevent clicks inside the donut container from bubbling to outer ancestor pressables:

    <Animated.View
        style={[styles.chartContent, shouldUseResponsiveLegend && StyleUtils.getWidthStyle(donutWidth), isHoveringOverPie && styles.cursorPointer]}
        onTouchStart={onChartTouchStart}
        onClick={(e: React.MouseEvent) => e.stopPropagation()}
    >

    Or, inside the center donut hole (styles.pieChartCenterLabel), change pointerEvents="auto" and attach an inert click handler onClick={(e) => e.stopPropagation()} (or an unhandled Pressable) so clicks on the empty center / total text do not bubble to the outer card.

    Preventing bubbling at the donut container (onClick={(e) => e.stopPropagation()}) is the cleanest and most comprehensive approach:

    • Slices continue to trigger their designated drill-down/tooltip handlers (onSlicePress).
    • Clicks on the empty center hole or between slices stay within the chart bounds and do not accidentally trigger card-level navigation.
    • Normal clicks on the empty padding outside the chart still navigate as expected.

    What alternative solutions did you explore? (Optional)

    What automated tests can you add to prevent this from re-occurring?

    Add a unit test in tests/unit/components/Charts/PieChartTest.tsx or tests/ui/InsightsSectionContentTest.tsx:

    • Render InsightsSectionContent with isInsightsPageEnabled = true.
    • Simulate a click in the center hole of the donut chart.
    • Verify Navigation.navigate is not called.
    • Simulate a click on the card header/padding outside the chart and verify Navigation.navigate is called with the correct route.
  13. melvin-bot commented on Oct 24, 2026

    @melvin-bot

    ✅ Contributor details stored successfully. Thank you for contributing to Expensify!

  14. xian96xx commented on Oct 25, 2026

    @xian96xx

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    On Web (Home page), when the user clicks the empty center hole of the Home Insights donut (PieChart), it behaves as clickable (shows a pointer cursor and navigates to the Insights search page) instead of doing nothing as specified by the PR #103457 QA steps ("Click the empty center of the pie — nothing happens").

    What is the root cause of that problem?

    There are two interacting layers on the Home Insights widget:

    1. Inside PieChartContent.tsx (src/components/Charts/PieChart/PieChartContent.tsx:84-90, 180-194):
      findSliceAtPosition(x, y, centerX, centerY, radius, innerRadius, processedSlices) (src/components/Charts/utils/index.ts:228-230) already returns -1 when the click/hover point is inside the donut's empty center (distance < innerRadius). When PieChart is rendered on the Search page (shouldDrillDownOnPress = true), clicking the empty center hits tapGesture, finds sliceIndex === -1, does not call handleSlicePress, and nothing happens.
    2. Outside PieChartContent.tsx on the Home page (src/pages/home/InsightsSection/InsightsSectionContent.tsx:105, 112-123 and src/components/Search/SearchChartView.tsx:138):
      When the insightsPage beta (CONST.BETAS.INSIGHTS_PAGE) is enabled on desktop (!canUseTouchScreen()), InsightsSectionContent.tsx (updated in PR [NoQA] [Insights] Clicking anywhere on the Insight slot on Home should take you to the Insights page #103592) sets shouldDrillDownOnPress={!isInsightsPageEnabled} (false) and wraps the entire WidgetContainer in:
      <PressableWithoutFeedback
          onPress={navigateToInsights}
          accessibilityLabel={translate('homePage.insightsSection.title')}
          role={CONST.ROLE.BUTTON}
          sentryLabel={CONST.SENTRY_LABEL.HOME_PAGE.INSIGHTS_SECTION}
      >
          {widgetContent}
      </PressableWithoutFeedback>
      Because the outer <PressableWithoutFeedback onPress={navigateToInsights}> wraps the whole widget card on web:
      • The entire widget (including the empty center hole of the donut chart) inherits cursor: pointer.
      • Clicking the empty center of the donut chart is ignored by PieChartContent's Gesture.Tap() (sliceIndex === -1), so the DOM click event bubbles straight up to InsightsSectionContent's <PressableWithoutFeedback onPress={navigateToInsights}> and navigates to the Insights page.

    What changes do you think we should make in order to solve the problem?

    Note that existing proposals that put pointerEvents="auto" on styles.pieChartCenterLabel (StyleSheet.absoluteFillObject, which covers the entire donutWidth × canvasHeight rectangle) or stop propagation on the entire donut Animated.View will break hovering and clicking on the colored pie slices themselves.

    Instead, in src/components/Charts/PieChart/PieChartContent.tsx, we should render a circular hit-target overlay positioned over the exact inner hole (innerRadius > 0 && donutWidth > 0) that absorbs press/click events only within the circular hole (radius <= innerRadius) and restores the default cursor (styles.cursorDefault):

    {innerRadius > 0 && donutWidth > 0 && (
        <PressableWithoutFeedback
            accessible={false}
            role={CONST.ROLE.PRESENTATION}
            onPress={() => {}}
            style={[
                styles.pAbsolute,
                styles.alignItemsCenter,
                styles.justifyContentCenter,
                styles.cursorDefault,
                {
                    width: innerRadius * 2,
                    height: innerRadius * 2,
                    borderRadius: innerRadius,
                    left: centerX - innerRadius,
                    top: centerY - innerRadius,
                },
            ]}
        >
            {(!!centerLabelTitle || !!centerLabelSubtitle) && (
                <>
                    {!!centerLabelTitle && (
                        <Text
                            style={[styles.textStrong, styles.pieChartCenterTitle]}
                            numberOfLines={1}
                        >
                            {centerLabelTitle}
                        </Text>
                    )}
                    {!!centerLabelSubtitle && (
                        <Text
                            style={[styles.textMicroSupporting, styles.pieChartCenterSubtitle]}
                            numberOfLines={1}
                        >
                            {centerLabelSubtitle}
                        </Text>
                    )}
                </>
            )}
        </PressableWithoutFeedback>
    )}

    Why this works cleanly:

    1. Exact circular geometry: Because the PressableWithoutFeedback has width: innerRadius * 2, height: innerRadius * 2, borderRadius: innerRadius, and is centered at (centerX, centerY), browser hit-testing follows border-radius: 50%—so only points strictly inside distance < innerRadius hit this element.
    2. Slices remain fully interactive: Every point on the colored ring (innerRadius <= distance <= radius) falls outside the circular borderRadius box, so slice hover tooltips (panGesture) and slice clicks (including bubbling to InsightsSectionContent's navigateToInsights when a user clicks a colored slice or the widget header/legend) continue to work normally.
    3. No pointer cursor on the empty center: styles.cursorDefault ensures hovering over the empty center hole shows the default arrow cursor rather than a hand pointer.

    What alternative solutions did you explore? (Optional)

    • Setting pointerEvents="auto" on styles.pieChartCenterLabel: styles.pieChartCenterLabel uses ...StyleSheet.absoluteFillObject, covering the entire rectangular canvas (donutWidth × canvasHeight). Making that full rectangle capture pointer events blocks all slice hover tooltips and slice clicks across the entire pie chart.
    • Stopping click propagation on the outer donut Animated.View: When shouldDrillDownOnPress is false on the Home widget, onSlicePress is undefined, so clicking a colored slice relies on the click bubbling to InsightsSectionContent's PressableWithoutFeedback. Stopping propagation on the whole donut container breaks clicking on colored slices.
  15. melvin-bot commented on Oct 25, 2026

    @melvin-bot

    📣 @xian96xx! 📣
    Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork.
    Please follow these steps:

    1. Make sure you've read and understood the contributing guidelines.
    2. Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
    3. Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
    4. Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details.
      Screen Shot 2022-11-16 at 4 42 54 PM
      Format:
    Contributor details
    Your Expensify account email: <REPLACE EMAIL HERE>
    Upwork Profile Link: <REPLACE LINK HERE>
    
  16. fangjian-bit commented on Oct 26, 2026

    @fangjian-bit

    Contributor details
    Your Expensify account email: 3055073676@qq.com
    Upwork Profile Link: https://www.upwork.com/freelancers/~01a6c3832b8108493d

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    On Web/Desktop, when navigating to the Home screen Insights section and switching the dropdown to "Top categories" (which renders a donut-style PieChart), clicking the empty center hole of the donut chart redirects the user to the Insights tab, instead of doing nothing.

    What is the root cause of that problem?

    The issue is caused by the interaction between the card-level navigation wrapper and the chart gesture/hit-testing handling:

    1. In src/pages/home/InsightsSection/InsightsSectionContent.tsx (lines 116–124), when isInsightsPageEnabled is true on non-touch devices, the entire widget is wrapped in <PressableWithoutFeedback onPress={navigateToInsights}>.
    2. Inside src/components/Charts/PieChart/PieChartContent.tsx (lines 255–269), the donut center label container is explicitly styled with pointerEvents="none":
      <View
          pointerEvents="none"
          style={styles.pieChartCenterLabel}
      >
    3. Inside PieChartCanvas in src/components/Charts/PieChart/PieChartContent.tsx (lines 173–194), the tapGesture only invokes handleSlicePress when sliceIndex >= 0. When a user clicks in the empty center hole (distance < innerRadius), findSliceAtPosition returns -1. Because the center View has pointerEvents="none" and tapGesture performs no action for unhit areas within the chart bounds, the click event bubbles straight through the transparent donut hole directly to the outer PressableWithoutFeedback, triggering navigateToInsights.

    What changes do you think we should make in order to solve the problem?

    1. In src/components/Charts/PieChart/PieChartContent.tsx:

      • In tapGesture.onDeactivate, check if the click coordinates lie within the donut chart bounds (i.e. distance from center d <= radius). When clicked inside the donut boundary (including the empty center hole where sliceIndex < 0), explicitly prevent bubbling / handle it as a no-op so that clicks on the donut hole are absorbed and do not trigger outer card navigation.
      • Alternatively, remove pointerEvents="none" from pieChartCenterLabel (or wrap the center circle in an empty pressable/view with pointerEvents="auto" that stops event propagation) so that clicks on the inner donut hole are absorbed by the center overlay rather than passing through to the card container.
    2. Ensure that clicking on the actual pie slices still correctly triggers onSlicePress (or drill-down when enabled), while clicking the center hole does nothing.

    What alternative solutions did you explore? (Optional)

    Wrapping the chart canvas in an overlay that stops pointer events outside the slices, but absorbing the tap in tapGesture or on the center label overlay is the cleanest and requires the minimal diff without breaking hover or tooltip interactions.

  17. melvin-bot commented on Oct 26, 2026

    @melvin-bot

    ✅ Contributor details stored successfully. Thank you for contributing to Expensify!

  18. bhomvratrai-glitch commented on Oct 26, 2026

    @bhomvratrai-glitch

    Contributor details
    Your Expensify account email: bhomvratrai@gmail.com
    Upwork Profile Link: https://www.upwork.com/freelancers/~016c1aa34b51059d42

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    On Web/Desktop, when viewing the Insights widget on the Home page in "Top categories" view (pie/donut chart), clicking the empty center of the donut chart redirects the user to the Insights tab instead of doing nothing.

    What is the root cause of that problem?

    In src/pages/home/InsightsSection/InsightsSectionContent.tsx (lines 116–124), on non-touch devices where isInsightsPageEnabled is true, the entire widget card is wrapped in a clickable container to allow navigating to the full Insights page:

    <PressableWithoutFeedback
        accessible={false}
        onPress={navigateToInsights}
        sentryLabel={CONST.SENTRY_LABEL.HOME_PAGE.WIDGET_ITEM}
    >
        {widget}
    </PressableWithoutFeedback>

    In src/components/Charts/PieChart/PieChartContent.tsx:

    1. The center label container (lines 256–269) has pointerEvents="none", allowing pointer events in the center hole to pass directly through to the underlying canvas/container.
    2. In tapGesture.onDeactivate (lines 177–193), findSliceAtPosition checks if a slice was clicked. When clicking the empty center hole (distance < innerRadius), findSliceAtPosition returns -1, so no slice action is scheduled.
    3. Because the click is within the chart container but unhandled by Gesture Handler, the native web click event bubbles up the DOM tree from Animated.View directly to the parent <PressableWithoutFeedback onPress={navigateToInsights}>, triggering unexpected navigation.

    What changes do you think we should make in order to solve the problem?

    In src/components/Charts/PieChart/PieChartContent.tsx, stop native click event propagation on the donut chart container so clicks inside the chart bounds (whether on a slice or in the empty donut center) are contained within the chart and do not bubble up to outer card navigation wrappers:

    <Animated.View
        style={[styles.chartContent, shouldUseResponsiveLegend && StyleUtils.getWidthStyle(donutWidth), isHoveringOverPie && styles.cursorPointer]}
        onTouchStart={onChartTouchStart}
        onClick={(e: React.MouseEvent) => e.stopPropagation()}
    >

    This ensures that:

    • Slices continue to handle their hover and press interactions via Gesture Handler.
    • Clicking inside the donut center hole is absorbed cleanly and does nothing.
    • Clicking anywhere on the widget card outside the chart canvas continues to trigger navigateToInsights.

    What alternative solutions did you explore? (Optional)

    Removing pointerEvents="none" from styles.pieChartCenterLabel; however, because pieChartCenterLabel is styled with position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, removing pointerEvents="none" would cause the full-bounding box overlay to intercept pointer events on the pie slices themselves, interfering with hover states. Stopping event propagation on chartContent cleanly resolves event bubbling without altering hit-test geometry.

    Test Result / Verification:

    1. Open Expensify web app.
    2. On the Home page Insights card, select "Top categories".
    3. Click the empty center hole of the donut chart. Verify nothing happens (no redirection).
    4. Click on a donut slice. Verify the slice interaction/tooltip works as expected.
    5. Click on the widget card background/header. Verify it navigates to Insights as expected.
  19. melvin-bot commented on Oct 26, 2026

    @melvin-bot

    ✅ Contributor details stored successfully. Thank you for contributing to Expensify!

  20. bhomvratrai-glitch commented on Oct 26, 2026

    @bhomvratrai-glitch

    Proposal Update: Full Working Fix Verified & Branch Pushed

    We have implemented and verified the fix on branch:
    bhomvratrai-glitch:fix/104771-piechart-empty-center-click-bubbling
    Commit: ade1a9cd

    Summary of Changes

    • In src/components/Charts/PieChart/PieChartContent.tsx, added onClick={(e: React.MouseEvent) => e.stopPropagation()} to the donut chart's Animated.View container.
    • Clicks on the donut chart (including the empty center hole) are contained within the chart element and prevented from bubbling up to the outer PressableWithoutFeedback card link.
    • Slice tooltips, touch pinning, and press gestures continue to function normally.

    Ready to open the PR immediately upon assignment!

  21. melvin-bot commented on Oct 27, 2026

    @melvin-bot

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

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

Metadata

Metadata

Assignees

Labels

BugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributorOverdue

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions