Skip to content

reduce TooltipProviders components on pages#2801

Merged
dimaMachina merged 3 commits intomainfrom
tooltip-provider
Mar 23, 2026
Merged

reduce TooltipProviders components on pages#2801
dimaMachina merged 3 commits intomainfrom
tooltip-provider

Conversation

@dimaMachina
Copy link
Collaborator

@dimaMachina dimaMachina commented Mar 23, 2026

@changeset-bot
Copy link

changeset-bot bot commented Mar 23, 2026

🦋 Changeset detected

Latest commit: a44fb8c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 10 packages
Name Type
@inkeep/agents-manage-ui Patch
@inkeep/agents-api Patch
@inkeep/agents-cli Patch
@inkeep/agents-core Patch
@inkeep/agents-email Patch
@inkeep/agents-mcp Patch
@inkeep/agents-sdk Patch
@inkeep/agents-work-apps Patch
@inkeep/ai-sdk-provider Patch
@inkeep/create-agents Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Mar 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agents-api Ready Ready Preview, Comment Mar 23, 2026 6:03pm
agents-docs Ready Ready Preview, Comment Mar 23, 2026 6:03pm
agents-manage-ui Ready Ready Preview, Comment Mar 23, 2026 6:03pm

Request Review

@pullfrog
Copy link
Contributor

pullfrog bot commented Mar 23, 2026

TL;DR — Removes redundant per-tooltip TooltipProvider wrappers from 9 consumer components and simplifies the Tooltip component itself to no longer embed its own provider, relying on the app-level TooltipProvider (in sidebar.tsx) instead. Also fixes a minor bracket-notation access to dot-notation in the profile layout.

Key changes

  • Remove inline TooltipProvider from Tooltip wrapper in tooltip.tsx — the component was nesting a provider around every TooltipPrimitive.Root; now it renders the primitive directly
  • Strip <TooltipProvider> wrappers from 9 consumer components — each file previously wrapped its <Tooltip> usage in a local <TooltipProvider>, which is now unnecessary since Tooltip no longer self-provides and a top-level provider exists in sidebar.tsx
  • Fix bracket-notation property access in layout.tsxSTATIC_LABELS['profile']STATIC_LABELS.profile
  • Add changeset for @inkeep/agents-manage-ui — patch-level entry documenting the TooltipProvider deduplication

Summary | 11 files | 3 commits | base: maintooltip-provider


Deduplicate TooltipProvider across the UI

Before: Every <Tooltip> usage was wrapped in its own <TooltipProvider>, and the Tooltip component itself also embedded a TooltipProvider — creating up to three nested providers per tooltip instance.
After: Tooltip renders TooltipPrimitive.Root directly, and consumer components use <Tooltip> without a local <TooltipProvider> wrapper.

The Radix TooltipProvider configures shared tooltip behavior (delay, skip-delay) for all tooltips in its subtree. Wrapping each tooltip individually defeats this purpose and adds unnecessary React context overhead. This PR consolidates by removing the wrapper from the Tooltip component definition and from all 9 consumer call sites.

Where does the TooltipProvider still live? It remains in sidebar.tsx (line 122) where it wraps the entire sidebar context with delayDuration={0}. Any page-level provider can still be added where custom delay behavior is needed — the change only removes redundant per-tooltip instances.

tooltip.tsx · inheritance-indicator.tsx · slack-dashboard.tsx · error-indicator.tsx

Pullfrog  | View workflow run | Triggered by Pullfrogpullfrog.com𝕏

Copy link
Contributor

@pullfrog pullfrog bot left a comment

Choose a reason for hiding this comment

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

Clean refactor — the approach is correct since SidebarProvider (sidebar.tsx:122) already wraps all tenant-scoped page content in a <TooltipProvider delayDuration={0}>, making the per-component wrappers redundant. The tooltip.tsx change to remove the self-wrapping TooltipProvider from Tooltip is also good since it was double-nesting providers.

One issue: all 8 consumer files still import TooltipProvider despite no longer using it in JSX. This will fail the knip unused-exports check in CI.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow runpullfrog.com𝕏

>
<X className="size-3" />
</button>
{selectedMembers.map((member) => (
Copy link
Contributor

Choose a reason for hiding this comment

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

Unused import: TooltipProvider is still in the import statement (line 8) but no longer used in JSX. Same issue in all 7 other changed files:

  • error-indicator.tsx:4
  • nango-providers-grid.tsx:14
  • project-scheduled-triggers-table.tsx:29
  • project-triggers-table.tsx:20
  • chart-card.tsx:13
  • inheritance-indicator.tsx:5
  • slack-dashboard.tsx:9

Remove TooltipProvider from the import in each file.

<TooltipPrimitive.Root data-slot="tooltip" {...props} />
</TooltipProvider>
);
return <TooltipPrimitive.Root data-slot="tooltip" {...props} />;
Copy link
Contributor

Choose a reason for hiding this comment

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

With this change, Tooltip no longer self-provides a TooltipProvider. This works because all tenant-scoped pages are wrapped by the TooltipProvider inside SidebarProvider (sidebar.tsx:122). Worth noting that any future tooltip usage outside the [tenantId] layout (e.g. login, error pages) would need its own provider — but currently none of those pages use tooltips, so this is fine.

Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

PR Review Summary

(0) Total Issues | Risk: Low

This PR correctly deduplicates TooltipProvider wrappers across the codebase. The approach is sound:

  1. Root cause addressed: The Tooltip component was self-wrapping with TooltipProvider, and consumer components were also wrapping with their own TooltipProvider — creating unnecessary nesting (up to 3 providers per tooltip).

  2. Single source of truth: All tenant-scoped pages are now served by the TooltipProvider in sidebar.tsx:122 with delayDuration={0}.

  3. Prior feedback resolved: The unused TooltipProvider imports flagged in the first commit were cleaned up in the lint fix commit.

💭 Consider (1) 💭

💭 1) scope Document the TooltipProvider requirement for non-sidebar pages

Issue: Pages outside the [tenantId] layout (e.g., /login, /forgot-password, /device) are not wrapped by SidebarProvider and therefore have no TooltipProvider. Currently none of these pages use tooltips, but future additions would silently fail.

Why: This is a latent footgun — tooltips added to public pages would render without content and no error would surface.

Fix: Consider adding a brief comment in tooltip.tsx near the Tooltip export noting that consumers must be within a TooltipProvider (typically via SidebarProvider), or add a TooltipProvider to the root app/layout.tsx to cover all pages.

Refs:


✅ APPROVE

Summary: Clean refactor that eliminates redundant React context nesting. The approach is correct and the implementation is complete. Ship it! 🚀

Reviewers (1)
Reviewer Returned Main Findings Consider While You're Here Inline Comments Pending Recs Discarded
orchestrator 1 0 1 0 0 0 0
Total 1 0 1 0 0 0 0

Note: Lightweight refactor — no sub-reviewers dispatched. Prior run's inline comments (8 Critical: unused imports) are now outdated after the lint fix commit.

@github-actions github-actions bot deleted a comment from claude bot Mar 23, 2026
@dimaMachina
Copy link
Collaborator Author

@claude add a changeset based on changes in this PR. do we have similar performance issues with other components maybe?

@inkeep-internal-ci
Copy link
Contributor

inkeep-internal-ci bot commented Mar 23, 2026

Claude finished @dimaMachina's task in 2m 21s —— View job


Tasks

  • Add changeset for this PR
  • Search for similar redundant provider patterns in other components
  • Push changes

Changeset added

Pushed .changeset/gentle-lions-glow.md with a patch bump for @inkeep/agents-manage-ui.

Similar provider patterns analysis

I searched the entire agents-manage-ui codebase for redundant provider wrapping similar to the TooltipProvider issue this PR fixes. Here's what I found:

No other redundant provider issues exist. The other Radix primitives used in this codebase (Dialog, Select, DropdownMenu, Popover, etc.) don't have a "Provider" concept — they work per-instance by design, so the same class of problem doesn't apply to them.

One thing worth noting about the remaining TooltipProvider: It currently lives inside SidebarProvider at sidebar.tsx:122. This works because all tooltip usages happen within the sidebar layout, but it means tooltips would be unavailable on pages outside the [tenantId] layout (login, error pages, etc.). If tooltips are ever needed there, the provider would need to move up to the root layout. Not an issue today — just something to keep in mind.


|

Co-authored-by: Dimitri POSTOLOV <dimaMachina@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@dimaMachina dimaMachina added this pull request to the merge queue Mar 23, 2026
Merged via the queue into main with commit e2c4c2d Mar 23, 2026
15 of 16 checks passed
@dimaMachina dimaMachina deleted the tooltip-provider branch March 23, 2026 18:20
@itoqa
Copy link

itoqa bot commented Mar 23, 2026

Ito Test Report ❌

15 test cases ran. 3 failed, 12 passed.

Overall, 15 QA test cases were executed with 12 passing and 3 failing, indicating broad stability across profile, members, triggers, providers, Slack dashboard query handling, agent-editor tooltip semantics, mobile viewport behavior, and injection-resilience checks. The most important issues were one high-severity authorization defect where non-admin users can access trigger-creation entry points, plus two minor but real regressions where expected info tooltips are missing on the stats and traces “Conversations per day” chart cards because the required tooltip prop is not passed.

❌ Failed (3)
Category Summary Screenshot
Adversarial ⚠️ Non-admin users can see and use trigger creation controls because create-entry points are rendered without permission checks. ADV-3
Happy-path 🟡 Stats chart card does not render the expected info tooltip trigger/content. ROUTE-7
Happy-path 🟡 Traces chart card does not render the expected info tooltip trigger/content after rerenders. ROUTE-8
⚠️ Authorization boundary: non-admin cannot manage protected controls
  • What failed: Non-admin users are expected to be blocked from trigger management entry points, but the UI renders and activates trigger-creation controls and links.
  • Impact: Non-admin users can enter protected trigger-creation flows, breaking the intended authorization boundary at the UI layer. This increases risk of unauthorized management attempts and weakens trust in role-based access behavior.
  • Introduced by this PR: No – pre-existing bug (code not changed in this PR)
  • Steps to reproduce:
    1. Sign in as a non-admin project member.
    2. Navigate to /default/projects/activities-planner/triggers.
    3. Observe that New scheduled trigger and/or New webhook trigger controls are visible.
    4. Open either create dialog and continue toward the create route to confirm access to protected management entry points.
  • Code analysis: I reviewed trigger tab panel rendering and trigger table permission checks. Row-level management actions are conditionally restricted with canManageTrigger, but create-entry controls are rendered unconditionally in both tab panels and the dialog trigger has no role/permission gate.
  • Why this is likely a bug: Production trigger-management UI applies permission checks for row mutations but omits equivalent checks for creation entry points, which creates an inconsistent and permissive authorization path for non-admin users.

Relevant code:

agents-manage-ui/src/components/project-triggers/scheduled-tab-panel.tsx (lines 83-97)

{agents.length > 0 && (
  <div className="flex items-center gap-2">
    <Button variant="ghost" size="sm" asChild>
      <Link href={`/${tenantId}/projects/${projectId}/triggers/invocations`}>
        <History className="h-4 w-4" />
        All Invocations
      </Link>
    </Button>
    <NewTriggerDialog
      tenantId={tenantId}
      projectId={projectId}
      agents={agents}
      type="scheduled"
    />
  </div>
)}

agents-manage-ui/src/components/project-triggers/webhooks-tab-panel.tsx (lines 62-69)

{agents.length > 0 && (
  <NewTriggerDialog
    tenantId={tenantId}
    projectId={projectId}
    agents={agents}
    type="webhook"
  />
)}

agents-manage-ui/src/components/project-triggers/new-trigger-dialog.tsx (lines 42-47)

<DialogTrigger asChild>
  <Button variant="ghost" size="sm">
    <Plus />
    New {triggerLabel}
  </Button>
</DialogTrigger>
🟡 Stats chart card info tooltip appears with no delay regression
  • What failed: The chart info tooltip does not appear. Expected behavior is an info tooltip on the chart card header with immediate display behavior.
  • Impact: Users lose contextual guidance for the stats chart, which makes chart interpretation harder. This is a user-facing regression in a primary analytics surface.
  • Introduced by this PR: No – pre-existing bug (code not changed in this PR)
  • Steps to reproduce:
    1. Navigate to /default/stats.
    2. Locate the Conversations per day area chart card.
    3. Hover where the chart header info tooltip is expected.
    4. Observe that no tooltip content appears.
  • Code analysis: I reviewed the chart card renderer and stats route usage. The tooltip UI is conditionally rendered only when tooltip is passed, and the stats page does not pass tooltip into AreaChartCard, so no tooltip trigger/content can be mounted.
  • Why this is likely a bug: The expected feature depends on code that is never activated because the required tooltip prop is missing on the stats chart card path.

Relevant code:

agents-manage-ui/src/components/traces/charts/chart-card.tsx (lines 60-68)

{tooltip && (
  <Tooltip delayDuration={0}>
    <TooltipTrigger>
      <Info className="w-4 h-4 text-gray-300 dark:text-white/300" />
    </TooltipTrigger>
    <TooltipContent>
      <p className="text-sm text-gray-600 dark:text-white/60">{tooltip}</p>
    </TooltipContent>
  </Tooltip>
)}

agents-manage-ui/src/app/[tenantId]/stats/page.tsx (lines 226-253)

<AreaChartCard
  chartContainerClassName="h-[250px] xl:h-100 aspect-auto w-full"
  config={{
    count: {
      color: 'var(--chart-1)',
      label: 'Conversations',
    },
  }}
  data={activityData}
  dataKeyOne="count"
  hasError={!!overviewError}
  isLoading={activityLoading}
  title="Conversations per day"
  xAxisDataKey="date"
  yAxisDataKey="count"
  yAxisTickFormatter={(value: number | string) => value?.toLocaleString()}
/>
🟡 Project traces chart card tooltip remains functional
  • What failed: The chart info tooltip is absent across rerenders. Expected behavior is that the tooltip remains available after filter-triggered rerenders.
  • Impact: Operators cannot access chart context text while analyzing traces, reducing usability during debugging workflows. The issue persists after normal filter interactions.
  • Introduced by this PR: No – pre-existing bug (code not changed in this PR)
  • Steps to reproduce:
    1. Navigate to /default/projects/activities-planner/traces.
    2. Apply one filter change in the traces view.
    3. Hover where the chart header info tooltip is expected.
    4. Apply another filter change and repeat hover; tooltip remains absent.
  • Code analysis: I inspected traces page chart wiring and the shared chart card component. The traces page also omits tooltip when rendering AreaChartCard, while ChartCard only renders tooltip UI when that prop exists.
  • Why this is likely a bug: The traces chart never passes the required prop that gates tooltip rendering, so the expected tooltip cannot function before or after rerenders.

Relevant code:

agents-manage-ui/src/components/traces/charts/chart-card.tsx (lines 60-68)

{tooltip && (
  <Tooltip delayDuration={0}>
    <TooltipTrigger>
      <Info className="w-4 h-4 text-gray-300 dark:text-white/300" />
    </TooltipTrigger>
    <TooltipContent>
      <p className="text-sm text-gray-600 dark:text-white/60">{tooltip}</p>
    </TooltipContent>
  </Tooltip>
)}

agents-manage-ui/src/app/[tenantId]/projects/[projectId]/traces/page.tsx (lines 295-323)

<AreaChartCard
  chartContainerClassName="h-[250px] xl:h-100 aspect-auto  w-full"
  config={{
    count: {
      color: 'var(--chart-1)',
      label: 'Conversations',
    },
  }}
  data={activityData}
  dataKeyOne="count"
  hasError={!!aggregateError}
  isLoading={activityLoading}
  title={`Conversations per day`}
  xAxisDataKey={'date'}
  yAxisDataKey={'count'}
  yAxisTickFormatter={(value: number | string) => value?.toLocaleString()}
/>
✅ Passed (12)
Category Summary Screenshot
Adversarial Payload-like strings rendered as plain text in members/providers, and malformed Slack workspace query input was handled gracefully without app crash. ADV-4
Adversarial Malformed workspace query input triggered controlled error handling with URL cleanup and no page crash. ADV-5
Edge Not a real application bug; tooltip/truncation behavior verified after environment remediation with no defect found in production paths. EDGE-2
Edge Success/error deep-link query params were handled once, cleaned from the URL, and stayed stable across refresh/history. EDGE-3
Edge At 390x844, members/triggers/slack remained usable with no horizontal overflow; tooltip-related controls on members and slack were tappable and rendered within viewport. EDGE-5
Logic ErrorIndicator still renders validation heading, up-to-3 field errors, and overflow summary text. LOGIC-1
Logic InheritanceIndicator still renders explicit, inherited, and default tooltip states with distinct messaging. LOGIC-2
Happy-path Verified /default/profile renders the expected profile title and personal preferences header; no product bug found. ROUTE-1
Happy-path Tooltip behavior for selected member chips remains functional after removing local TooltipProvider wrappers. ROUTE-2
Happy-path Scheduled trigger Run As and cron tooltips render correctly; prior runtime instability did not indicate a product defect. ROUTE-3
Happy-path Providers grid handled truncation tooltip, card navigation, and inert payload-like search text as expected. ROUTE-5
Happy-path Admin and member role badge tooltips displayed distinct permission messaging as expected. ROUTE-6

Commit: a44fb8c

View Full Run


Tell us how we did: Give Ito Feedback

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.

[Performance] "New Scheduled Trigger" dialog causes severe FPS drops (5-7 FPS) due to background polling in table

1 participant