Skip to content

refactor(ui): shared ConfirmDialog, Panel, SettingRow, KeyValue, tone and error-rate primitives - #1265

Merged
Makisuo merged 5 commits into
mainfrom
refactor/ui-shared-components
Oct 5, 2026
Merged

Makisuo merged 5 commits into
mainfrom
refactor/ui-shared-components

Conversation

@Makisuo

@Makisuo Makisuo commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

What

A fourth pass at unifying hand-rolled UI onto shared primitives. It adds the missing primitives to @maple/ui, then moves about 270 call sites across apps/web, apps/local-ui and packages/ui onto them, deleting the local copies.

New in @maple/ui

  • ConfirmDialog: the confirm-before-acting AlertDialog. If onConfirm returns a promise, the dialog shows the pending spinner and closes when it resolves. Also has confirmDisabled and secondaryAction.
  • Panel / PanelHeader / PanelBody: flat bordered section frame. SectionCard and ChartCard now build on it.
  • SettingRow: label and description on the left, control on the right. The control is labelled through Base UI Field.
  • KeyValueList / KeyValue: split, grid and stacked layouts, with mono, copyValue and wrap.
  • Meter, SegmentedBar, Delta, ListFooter / LoadMoreButton / LoadingMoreRow, SkeletonList, TruncatedId, TruncatedText, HttpStatusCode, ErrorRateValue.
  • Libs: tone.ts (one severity palette), error-rate.ts (one threshold pair), ids.ts (display lengths for trace, span, SHA and session ids), formatCountdown, httpStatusTone.
  • Extended existing primitives:
    • Badge: shape="pill", size="xs", mono, muted/meta variants.
    • Table: size="sm"|"xs", variant="bare", scroll={false}, TableHeader sticky.
    • Alert: size="sm".
    • Item: card/flush variants and an lg size.
    • Toggle: size="xs".
    • StatusDot: tone="live".

New in apps/web/src/components/common

  • RelativeTime (absolute time on hover, in the viewer's timezone setting) and SheetDetailHeader.
  • Moved here: PageHero, DataTable and the underline link tabs.
  • The infra search row is renamed SearchToolbar, so it no longer shares a name with the tabs ListToolbar.

Deleted local copies: MetaChip, Pill, FilterTabs, KpiCard, StatCard, about 7 local delta components, and duplicate formatErrorRate / formatRate / formatCountdown / truncateId / shortId / truncateCommitSha helpers.

Why

The same patterns existed in many slightly different versions:

  • 22 hand-built confirm dialogs.
  • About 90 pill and chip spans.
  • About 10 error-rate maps with conflicting thresholds.
  • 7 delta chips that disagreed on arrows and colour.
  • About 45 relative timestamps, some using toLocaleString() tooltips that ignored the timezone setting.

Behaviour changes for review

  • Error rate thresholds are one pair everywhere: >= 5% critical, >= 1% warning. Previously some tables coloured anything above 0, one deploy chip warned at 0.1%, and agent tool breakdowns only went critical at 10%. Small rates now format as <0.01% (the shared formatter) instead of <1%.
  • Deltas are coloured by improvement (info = better, error = worse), always with an arrow.
  • Severity colours: several destructive and amber classes moved to the severity-* palette.
  • Span tooltip: 4xx is amber (was red) and 3xx is neutral (was amber).
  • PageHero titles use the PageLayout.Title typography, so the anomaly and investigation heroes shrink from 3xl/4xl to 2xl.
  • Stat cards: billing, data-platform and integration stat cards are now StatRail tiles. One integration card's whole-tile link became an "Open" link in the tile's action slot.
  • Destructive confirm buttons show a spinner instead of "Removing..." text.
  • Settings switches in SettingRows now have accessible names (they had none).

Deliberately left alone:

  • The 4-level error severity badge palette.
  • Alert threshold radio groups (ToggleGroup would change radio semantics).
  • Feature usage cards and the AI analytics tiles.
  • The releases table's old to new value delta.
  • Spoken-duration helpers whose output differs from the shared formatters.

Verification

  • tsc --noEmit is clean for packages/ui, apps/web and apps/local-ui.
  • oxlint is clean (0 errors) on all changed files.
  • Vitest passes for the 33 web test files colocated with or covering the changed components (353 tests) and the packages/ui lib tests (208 tests).
  • In a browser, the /lab infra, agent-session, errors and verdict pages rendered with no React errors (only network errors from running without the API).
  • Not run: the full monorepo test suite and a repo-wide typecheck. CI covers both.

The commits are cherry-picked onto main from the previous sweep branch (#1256 was squash-merged). The touched files are byte-identical to the branch where the checks above ran.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Devin Review

…a, ListFooter, TruncatedId/Text primitives

Badge gains pill shape, xs size, mono and muted/meta variants; Table gains
sm/xs density, a bare variant and a sticky header; Alert gets a compact size;
Item gets card/flush variants and an lg size. Shared tone, error-rate and
HTTP-status maps live in @maple/ui/lib. RelativeTime, SheetDetailHeader,
PageHero, DataTable, SearchToolbar and the link tab strip move to
apps/web common.
ConfirmDialog, SettingRow, Panel, KeyValueList, Meter/SegmentedBar, Delta,
ListFooter, SkeletonList, TruncatedId/Text, RelativeTime, SheetDetailHeader,
Badge pill/xs/mono, Table density, Alert sm, StatRail tiles and the shared
tone, error-rate and HTTP-status maps replace their hand-rolled copies across
web, local-ui and the ui package. Error rates now share one threshold pair
(5% crit, 1% warn). Deletes MetaChip, Pill, FilterTabs, KpiCard, StatCard and
the local delta, countdown and id-shortening helpers.
@maple-review-bot

maple-review-bot Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Note

A newer push replaced 2dbcf07 before its review finished. The latest commit is reviewed in a new comment.

@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 311 files, which is 161 over the limit of 150.

To get a review, reduce the PR to 150 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

Usage-priced reviews support at most 300 files.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: dbdf1308-0cbc-4558-8cd1-aacbdf130adf
📥 Commits

Reviewing files that changed from the base of the PR and between 99b88bd and 9be30bd.

📒 Files selected for processing (311)
  • apps/local-ui/src/components/log-detail-sheet.tsx
  • apps/local-ui/src/components/service-map-panel.tsx
  • apps/local-ui/src/components/span-detail-panel.tsx
  • apps/local-ui/src/components/view-states.tsx
  • apps/local-ui/src/views/errors-view.tsx
  • apps/local-ui/src/views/metric-detail-view.tsx
  • apps/local-ui/src/views/metrics-list-view.tsx
  • apps/local-ui/src/views/service-detail-view.tsx
  • apps/local-ui/src/views/services-list-view.tsx
  • apps/local-ui/src/views/session-detail-view.tsx
  • apps/local-ui/src/views/sessions-list-view.tsx
  • apps/local-ui/src/views/trace-detail-view.tsx
  • apps/local-ui/src/views/trace-list-view.tsx
  • apps/web/src/components/account/active-sessions-section.tsx
  • apps/web/src/components/account/connected-accounts-section.tsx
  • apps/web/src/components/account/email-addresses-section.tsx
  • apps/web/src/components/account/passkeys-section.tsx
  • apps/web/src/components/account/password-section.tsx
  • apps/web/src/components/account/profile-section.tsx
  • apps/web/src/components/account/two-factor-section.tsx
  • apps/web/src/components/agent-sessions/agent-sessions-list.tsx
  • apps/web/src/components/agent-sessions/session-detail/payload-view.tsx
  • apps/web/src/components/agent-sessions/session-detail/pill.tsx
  • apps/web/src/components/agent-sessions/session-detail/session-header.tsx
  • apps/web/src/components/agent-sessions/session-detail/session-overview.tsx
  • apps/web/src/components/agent-sessions/session-detail/session-transcript.tsx
  • apps/web/src/components/agent-sessions/session-detail/session-waterfall.tsx
  • apps/web/src/components/agent-sessions/session-detail/span-expansion.tsx
  • apps/web/src/components/agent-sessions/session-detail/tool-io.tsx
  • apps/web/src/components/agent-sessions/tools/tool-breakdown-tables.tsx
  • apps/web/src/components/agent-sessions/tools/tool-detail-sessions.tsx
  • apps/web/src/components/agent-sessions/tools/tool-errors-table.tsx
  • apps/web/src/components/agent-sessions/tools/tool-metric-strip.tsx
  • apps/web/src/components/ai-elements/inline/inline-error.tsx
  • apps/web/src/components/ai-elements/inline/inline-log.tsx
  • apps/web/src/components/ai-elements/inline/inline-service.tsx
  • apps/web/src/components/ai-elements/inline/inline-trace.tsx
  • apps/web/src/components/ai-elements/markdown-table.tsx
  • apps/web/src/components/ai-elements/renderers/components/data-table.tsx
  • apps/web/src/components/ai-elements/renderers/components/error-list.tsx
  • apps/web/src/components/ai-elements/renderers/components/metrics-list.tsx
  • apps/web/src/components/ai-elements/renderers/components/span-tree.tsx
  • apps/web/src/components/ai-elements/renderers/components/trace-list.tsx
  • apps/web/src/components/alerts/alert-severity-badge.tsx
  • apps/web/src/components/alerts/destination-card.tsx
  • apps/web/src/components/alerts/destination-dialog.tsx
  • apps/web/src/components/alerts/notifications-section.tsx
  • apps/web/src/components/analytics/ai/ai-sections.tsx
  • apps/web/src/components/analytics/ai/analytics-ai-tab.tsx
  • apps/web/src/components/analytics/analytics-breakdown-panel.tsx
  • apps/web/src/components/analytics/analytics-metric-strip.tsx
  • apps/web/src/components/analytics/product-event-trace-samples.tsx
  • apps/web/src/components/anomalies/anomaly-format.ts
  • apps/web/src/components/anomalies/anomaly-hero.tsx
  • apps/web/src/components/anomalies/anomaly-linked-issue-card.tsx
  • apps/web/src/components/anomalies/anomaly-row.tsx
  • apps/web/src/components/anomalies/anomaly-sidebar.tsx
  • apps/web/src/components/anomalies/meta-chip.tsx
  • apps/web/src/components/chat/approval-card.tsx
  • apps/web/src/components/chat/approval-renderers/dashboard.tsx
  • apps/web/src/components/chat/approval-renderers/index.tsx
  • apps/web/src/components/chat/auto-contexts.ts
  • apps/web/src/components/chat/chat-conversation.tsx
  • apps/web/src/components/chat/chat-page.tsx
  • apps/web/src/components/chat/chat-sidebar.tsx
  • apps/web/src/components/chat/investigation-attachment-card.tsx
  • apps/web/src/components/chat/task-card.tsx
  • apps/web/src/components/chat/turn-failure-notice.tsx
  • apps/web/src/components/chat/widget-fix-attachment-card.tsx
  • apps/web/src/components/code-review/code-review-analytics.tsx
  • apps/web/src/components/code-review/code-review-format.ts
  • apps/web/src/components/code-review/code-review-layout.tsx
  • apps/web/src/components/code-review/code-review-settings.tsx
  • apps/web/src/components/code-review/review-detail-sheet.tsx
  • apps/web/src/components/code-review/review-rules-form.tsx
  • apps/web/src/components/common/data-table.tsx
  • apps/web/src/components/common/page-hero.tsx
  • apps/web/src/components/common/relative-time.tsx
  • apps/web/src/components/common/search-toolbar.tsx
  • apps/web/src/components/common/sheet-detail-header.tsx
  • apps/web/src/components/common/stat-rail.tsx
  • apps/web/src/components/common/underline-link-tabs.tsx
  • apps/web/src/components/dashboard-builder/config/list-config-panel.tsx
  • apps/web/src/components/dashboard-builder/config/query-panel.tsx
  • apps/web/src/components/dashboard-builder/config/variables-manager-dialog.tsx
  • apps/web/src/components/dashboard-builder/config/warning-list.tsx
  • apps/web/src/components/dashboard-builder/history/preview-banner.tsx
  • apps/web/src/components/dashboard-builder/list/dashboard-list.tsx
  • apps/web/src/components/dashboard-builder/sections/section-dialogs.tsx
  • apps/web/src/components/dashboard-builder/templates/template-list.tsx
  • apps/web/src/components/dashboard-builder/toolbar/share-dashboard-dialog.tsx
  • apps/web/src/components/dashboard-builder/widgets/list-widget.tsx
  • apps/web/src/components/dashboard-builder/widgets/table-widget.tsx
  • apps/web/src/components/dashboard-builder/widgets/types/preset-preview.tsx
  • apps/web/src/components/dashboard/service-health-section.tsx
  • apps/web/src/components/dashboard/service-health.ts
  • apps/web/src/components/dashboard/service-usage-cards.tsx
  • apps/web/src/components/errors/errors-hub-view.tsx
  • apps/web/src/components/errors/issue-detail-skeleton.tsx
  • apps/web/src/components/errors/issue-fact-strip.tsx
  • apps/web/src/components/errors/issue-incidents-table.tsx
  • apps/web/src/components/errors/issue-notes-callout.tsx
  • apps/web/src/components/errors/issue-occurrences-table.tsx
  • apps/web/src/components/errors/issue-pull-requests-panel.tsx
  • apps/web/src/components/errors/issue-tabs.tsx
  • apps/web/src/components/errors/issue-timeline.tsx
  • apps/web/src/components/errors/lease-hud.tsx
  • apps/web/src/components/errors/signal-state-chip.tsx
  • apps/web/src/components/header/onboarding-checklist-button.tsx
  • apps/web/src/components/infra/cloudflare/cloudflare-breakdown-panel.tsx
  • apps/web/src/components/infra/cloudflare/cloudflare-kpi-cards.tsx
  • apps/web/src/components/infra/cloudflare/cloudflare-platform-table.tsx
  • apps/web/src/components/infra/cloudflare/cloudflare-worker-table.tsx
  • apps/web/src/components/infra/cloudflare/cloudflare-zone-chart.tsx
  • apps/web/src/components/infra/cloudflare/cloudflare-zone-dns.tsx
  • apps/web/src/components/infra/cloudflare/cloudflare-zone-security.tsx
  • apps/web/src/components/infra/cloudflare/cloudflare-zone-table.tsx
  • apps/web/src/components/infra/cloudflare/constants.ts
  • apps/web/src/components/infra/container-summary-band.tsx
  • apps/web/src/components/infra/container-table.tsx
  • apps/web/src/components/infra/host-detail-header.tsx
  • apps/web/src/components/infra/host-summary-band.tsx
  • apps/web/src/components/infra/host-table.tsx
  • apps/web/src/components/infra/kubernetes/pod-peek-sheet.tsx
  • apps/web/src/components/infra/node-table.tsx
  • apps/web/src/components/infra/overview/infra-overview.tsx
  • apps/web/src/components/infra/overview/summaries.ts
  • apps/web/src/components/infra/planetscale/planetscale-activity-feed.tsx
  • apps/web/src/components/infra/planetscale/planetscale-branch-breakdown-panel.tsx
  • apps/web/src/components/infra/planetscale/planetscale-database-table.tsx
  • apps/web/src/components/infra/planetscale/planetscale-top-queries.tsx
  • apps/web/src/components/infra/pod-table.tsx
  • apps/web/src/components/infra/primitives/chart-card.tsx
  • apps/web/src/components/infra/primitives/fleet-band.tsx
  • apps/web/src/components/infra/primitives/scope-chip.tsx
  • apps/web/src/components/infra/railway/railway-service-table.tsx
  • apps/web/src/components/infra/service-lens/service-lens-rail.tsx
  • apps/web/src/components/infra/severity-tokens.ts
  • apps/web/src/components/infra/status-badge.tsx
  • apps/web/src/components/infra/workload-table.tsx
  • apps/web/src/components/ingest/connection-status.tsx
  • apps/web/src/components/integrations/chat-integration-card.tsx
  • apps/web/src/components/integrations/cloudflare-account-card.tsx
  • apps/web/src/components/integrations/cloudflare-stat-cards.tsx
  • apps/web/src/components/integrations/cloudflare-zone-board.tsx
  • apps/web/src/components/integrations/github-integration-card.tsx
  • apps/web/src/components/integrations/hazel-integration-card.tsx
  • apps/web/src/components/integrations/integration-catalog.tsx
  • apps/web/src/components/integrations/planetscale-integration-card.tsx
  • apps/web/src/components/integrations/planetscale-metrics-health.tsx
  • apps/web/src/components/integrations/planetscale-metrics-token-form.tsx
  • apps/web/src/components/integrations/railway-integration-card.tsx
  • apps/web/src/components/investigations/action-detail-sheet.tsx
  • apps/web/src/components/investigations/flow/flow-nodes.tsx
  • apps/web/src/components/investigations/flow/provenance-canvas.tsx
  • apps/web/src/components/investigations/investigation-table.tsx
  • apps/web/src/components/investigations/investigation-tabs.tsx
  • apps/web/src/components/investigations/run-progress.tsx
  • apps/web/src/components/investigations/verdict-card.tsx
  • apps/web/src/components/logs/log-hero-header.tsx
  • apps/web/src/components/logs/log-meta-strip.tsx
  • apps/web/src/components/logs/log-trace-timeline.tsx
  • apps/web/src/components/logs/logs-table.tsx
  • apps/web/src/components/metrics/metric-breakdown.tsx
  • apps/web/src/components/metrics/metric-detail.tsx
  • apps/web/src/components/metrics/metric-metadata-panel.tsx
  • apps/web/src/components/metrics/metric-preview-card.tsx
  • apps/web/src/components/metrics/metric-preview-grid.tsx
  • apps/web/src/components/metrics/metrics-summary-cards.tsx
  • apps/web/src/components/metrics/metrics-table.tsx
  • apps/web/src/components/onboarding/step-region.tsx
  • apps/web/src/components/region/region-badge.tsx
  • apps/web/src/components/releases/release-deploy-overview.tsx
  • apps/web/src/components/releases/release-detail-panels.tsx
  • apps/web/src/components/releases/release-health.tsx
  • apps/web/src/components/releases/release-issues-panel.tsx
  • apps/web/src/components/releases/release-model.ts
  • apps/web/src/components/releases/releases-live-now.tsx
  • apps/web/src/components/releases/releases-table.tsx
  • apps/web/src/components/releases/releases-timeline.tsx
  • apps/web/src/components/replays/replay-editor-timeline.tsx
  • apps/web/src/components/replays/session-detail-parts.tsx
  • apps/web/src/components/replays/session-events-panel.tsx
  • apps/web/src/components/replays/session-pills.tsx
  • apps/web/src/components/replays/sessions-list.tsx
  • apps/web/src/components/replays/trace-replay-link.tsx
  • apps/web/src/components/service-map/service-map-view.tsx
  • apps/web/src/components/service-map/three/spatial-layout.ts
  • apps/web/src/components/service-map/three/viewport.tsx
  • apps/web/src/components/services/dependency-table.tsx
  • apps/web/src/components/services/issue-line.tsx
  • apps/web/src/components/services/section-card.tsx
  • apps/web/src/components/services/service-api-tab.tsx
  • apps/web/src/components/services/service-dependencies-tab.tsx
  • apps/web/src/components/services/service-errors-panel.tsx
  • apps/web/src/components/services/service-operations-tab.tsx
  • apps/web/src/components/services/service-recent-deploys.tsx
  • apps/web/src/components/services/service-table-cells.tsx
  • apps/web/src/components/services/service-top-operations-panel.tsx
  • apps/web/src/components/services/service-usage-panel.tsx
  • apps/web/src/components/services/service-workloads-panel.tsx
  • apps/web/src/components/services/services-table.tsx
  • apps/web/src/components/settings/ai-triage-settings-section.tsx
  • apps/web/src/components/settings/api-keys-section.tsx
  • apps/web/src/components/settings/attribute-mappings-section.tsx
  • apps/web/src/components/settings/audit-log-section.tsx
  • apps/web/src/components/settings/automation-section.tsx
  • apps/web/src/components/settings/billing-controls-card.tsx
  • apps/web/src/components/settings/billing-controls-dialog.tsx
  • apps/web/src/components/settings/billing-details-dialog.tsx
  • apps/web/src/components/settings/billing-details-section.tsx
  • apps/web/src/components/settings/billing-kpis.tsx
  • apps/web/src/components/settings/cost-breakdown.tsx
  • apps/web/src/components/settings/create-api-key-dialog.tsx
  • apps/web/src/components/settings/data-platform-usage-section.tsx
  • apps/web/src/components/settings/escalation-policy-section.tsx
  • apps/web/src/components/settings/feature-usage-cards.tsx
  • apps/web/src/components/settings/filter-tab.tsx
  • apps/web/src/components/settings/format-feature-usage.ts
  • apps/web/src/components/settings/ingestion-section.tsx
  • apps/web/src/components/settings/invoices-section.tsx
  • apps/web/src/components/settings/members-section.tsx
  • apps/web/src/components/settings/notifications-section.tsx
  • apps/web/src/components/settings/org-clickhouse-settings-section.tsx
  • apps/web/src/components/settings/organization-section.tsx
  • apps/web/src/components/settings/plan-offer.tsx
  • apps/web/src/components/settings/pricing-cards.tsx
  • apps/web/src/components/settings/recommended-mappings-section.tsx
  • apps/web/src/components/settings/roll-api-key-dialog.tsx
  • apps/web/src/components/settings/scrape-targets-section.tsx
  • apps/web/src/components/settings/setup-audit-section.tsx
  • apps/web/src/components/traces/advanced-filter-dialog.tsx
  • apps/web/src/components/traces/span-detail-panel.tsx
  • apps/web/src/components/traces/trace-anatomy-strip.tsx
  • apps/web/src/components/traces/trace-logs-link.tsx
  • apps/web/src/components/traces/trace-peek-sheet.tsx
  • apps/web/src/components/traces/traces-table.tsx
  • apps/web/src/components/vcs/commit-markers/commit-markers-layer.tsx
  • apps/web/src/components/vcs/commit-markers/marker-layout.ts
  • apps/web/src/components/vcs/commit-sha-hover-card.tsx
  • apps/web/src/hooks/use-actor-directory.ts
  • apps/web/src/hooks/use-table-sort.ts
  • apps/web/src/lab/infra-lab.tsx
  • apps/web/src/lab/service-map-3d/index.tsx
  • apps/web/src/lib/logs/log-search-query.ts
  • apps/web/src/routes/agent-sessions/$sessionId.tsx
  • apps/web/src/routes/alerts/$ruleId.tsx
  • apps/web/src/routes/analytics/index.tsx
  • apps/web/src/routes/anomalies/$incidentId.tsx
  • apps/web/src/routes/anomalies/index.tsx
  • apps/web/src/routes/code-review/issues.tsx
  • apps/web/src/routes/code-review/pull-requests.tsx
  • apps/web/src/routes/dashboards/$dashboardId.tsx
  • apps/web/src/routes/dashboards/$dashboardId_.widgets.$widgetId.tsx
  • apps/web/src/routes/dashboards/index.tsx
  • apps/web/src/routes/errors/issues/$issueId.tsx
  • apps/web/src/routes/infra/cloudflare/$zoneName.tsx
  • apps/web/src/routes/infra/containers/$containerName.tsx
  • apps/web/src/routes/infra/containers/index.tsx
  • apps/web/src/routes/infra/hosts/$hostName.tsx
  • apps/web/src/routes/infra/hosts/index.tsx
  • apps/web/src/routes/infra/index.tsx
  • apps/web/src/routes/infra/kubernetes/nodes/$nodeName.tsx
  • apps/web/src/routes/infra/kubernetes/nodes/index.tsx
  • apps/web/src/routes/infra/kubernetes/pods/$podName.tsx
  • apps/web/src/routes/infra/kubernetes/pods/index.tsx
  • apps/web/src/routes/infra/kubernetes/services/$serviceName.tsx
  • apps/web/src/routes/infra/kubernetes/workloads/$kind/$workloadName.tsx
  • apps/web/src/routes/infra/kubernetes/workloads/index.tsx
  • apps/web/src/routes/infra/planetscale/$dbName.tsx
  • apps/web/src/routes/infra/planetscale/index.tsx
  • apps/web/src/routes/infra/railway/$serviceId.tsx
  • apps/web/src/routes/infra/railway/index.tsx
  • apps/web/src/routes/integrations.tsx
  • apps/web/src/routes/investigations/index.tsx
  • apps/web/src/routes/logs/$logId.tsx
  • apps/web/src/routes/logs/index.tsx
  • apps/web/src/routes/mcp-authorize.tsx
  • apps/web/src/routes/recommendations/$recommendationKey.tsx
  • apps/web/src/routes/releases/$commitSha.tsx
  • apps/web/src/routes/replays/$sessionId.tsx
  • apps/web/src/routes/select-plan.tsx
  • apps/web/src/routes/traces/$traceId.tsx
  • packages/ui/src/components/error-rate-value.tsx
  • packages/ui/src/components/http-status-code.tsx
  • packages/ui/src/components/service-map/service-map-node.tsx
  • packages/ui/src/components/traces/flow-node.tsx
  • packages/ui/src/components/traces/span-row.tsx
  • packages/ui/src/components/traces/span-tooltip.tsx
  • packages/ui/src/components/ui/alert.tsx
  • packages/ui/src/components/ui/badge.tsx
  • packages/ui/src/components/ui/confirm-dialog.tsx
  • packages/ui/src/components/ui/delta.tsx
  • packages/ui/src/components/ui/item.tsx
  • packages/ui/src/components/ui/key-value.tsx
  • packages/ui/src/components/ui/list-footer.tsx
  • packages/ui/src/components/ui/meter.tsx
  • packages/ui/src/components/ui/panel.tsx
  • packages/ui/src/components/ui/setting-row.tsx
  • packages/ui/src/components/ui/skeleton.tsx
  • packages/ui/src/components/ui/status-dot.tsx
  • packages/ui/src/components/ui/table.tsx
  • packages/ui/src/components/ui/toggle.tsx
  • packages/ui/src/components/ui/truncated-id.tsx
  • packages/ui/src/components/ui/truncated-text.tsx
  • packages/ui/src/lib/error-rate.ts
  • packages/ui/src/lib/http.ts
  • packages/ui/src/lib/ids.ts
  • packages/ui/src/lib/log-attributes.ts
  • packages/ui/src/lib/time-format.ts
  • packages/ui/src/lib/tone.ts

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

  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@devin-ai-integration devin-ai-integration 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.

Devin Review found 1 potential issue.

1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

Comment thread packages/ui/src/components/ui/confirm-dialog.tsx
…lure

Exit-returning mutations resolve on failure, so closing on any resolution
dismissed the dialog after a failed API key revoke. A handler can now resolve
to false to keep it open for a retry; revoke does so on failure.
@maple-review-bot

maple-review-bot Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Note

A newer push replaced dba4c12 before its review finished. The latest commit is reviewed in a new comment.

The effect lint rejects a prop named for structure, so `shape="pill"`
becomes `pill`. ConfirmDialog now pads its children itself, which the
dialog-padding sweep requires for AlertDialog bodies; callers drop their px-6.
@maple-review-bot

maple-review-bot Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Maple review

🔴 Confidence 2/5 · risky as written
Only the packages/ui primitives and a handful of call-site groups were read; the bulk of the 259 migrated apps/web files went unreviewed.
quality 76/100 · 2 warnings · 2 notes · tests partial · risk medium

Warning

This review ended early; what follows is what it established.

Adds shared UI primitives (ConfirmDialog, Panel, SettingRow, KeyValueList, Meter/SegmentedBar, Delta, TruncatedId/Text, tone and error-rate helpers) and migrates ~250 call sites onto them. The primitives are additive and safe, but a few migrations change user-visible behavior.

  • ConfirmDialog keeps itself open when the confirm handler returns false or rejects
  • tone.ts and error-rate.ts unify severity and error-rate colour thresholds across tables and maps
  • Migrations drop local helpers: pill.tsx, meta-chip.tsx, infra/severity-tokens maps, per-file id/relative-time formatting
  • Table gains size/variant="bare"/sticky header and Badge gains pill/mono/muted/meta

Findings

🟠 Warning · F1 · onConfirm={() => void handleDelete()} never closes the delete dialog

correctness · apps/web/src/components/account/profile-section.tsx:295

ConfirmDialog only auto-closes when the confirm handler returns a promise (confirm-dialog.tsx:67-78), so returning undefined leaves open true. handleDelete resets isDeleting only in its catch and never calls setDeleteOpen(false), so after a successful deleteAccount() the dialog stays mounted with the Cancel button disabled and no way out except the redirect. Pass the promise (onConfirm={handleDelete}) or call setDeleteOpen(false) on success.

`onConfirm={handleDelete}`
🟠 Warning · F2 · 3xx spans lose their redirect colour in the span tooltip

correctness · packages/ui/src/components/traces/span-tooltip.tsx:102

httpStatusTone returns neutral for every code below 400 (http.ts:201), so a 302 falls into the same branch as 2xx and renders text-severity-info. The sibling migrations of this helper (traces-table.tsx:115, trace-anatomy-strip.tsx:25) both keep a code >= 300 branch, so redirects stay distinguishable here only if that branch is restored.

Keep the 3xx case explicit, e.g. `tone !== "neutral" ? TONE_TEXT[tone] : code >= 300 ? "text-chart-p50" : "text-severity-info"`.
🔵 Note · F3 · Error-rate thresholds become inclusive on the service map

correctness · packages/ui/src/components/service-map/service-map-node.tsx:61

errorRateLevel tests rate >= 0.05 and rate >= 0.01 while the local helpers this replaces tested > 0.05 and > 0.01, so exactly 5% now draws the critical dot/border and exactly 1% the warning one. If the new inclusive boundary is intended, it is worth stating it in error-rate.ts; otherwise use > in the replacement helpers.

Either accept the inclusive boundary as the contract, or keep the strict comparison in the node's helper.
🔵 Note · F4 · "vs previous" subline renders on tiles with no delta

correctness · apps/web/src/components/code-review/code-review-analytics.tsx:109

When previous.pullRequests / reviews / avgMergeSeconds is null or 0, relativeChange returns null and the tile renders no Delta, but subline={versus} still claims a comparison against the previous window (also at 116 and 124). The removed Headline only showed that label when a delta existed, so the tile now asserts a comparison it has no baseline for.

Pass `subline` only when the matching `changeOf(...)` returns a ratio, or move the label into `Delta`'s `suffix`.
🤖 Prompt to fix all 4 findings with an AI agent
Findings from an automated review of commit 9be30bd9c05c9af798227bec79c0d7214f48c427. Verify each one against the current code before changing anything, fix only those that still apply, and keep each fix to the lines it names.

---

F1 · Warning · correctness · apps/web/src/components/account/profile-section.tsx:295
`onConfirm={() => void handleDelete()}` never closes the delete dialog
`ConfirmDialog` only auto-closes when the confirm handler returns a promise (confirm-dialog.tsx:67-78), so returning `undefined` leaves `open` true. `handleDelete` resets `isDeleting` only in its `catch` and never calls `setDeleteOpen(false)`, so after a successful `deleteAccount()` the dialog stays mounted with the Cancel button disabled and no way out except the redirect. Pass the promise (`onConfirm={handleDelete}`) or call `setDeleteOpen(false)` on success.
Suggested fix: `onConfirm={handleDelete}`

---

F2 · Warning · correctness · packages/ui/src/components/traces/span-tooltip.tsx:102
3xx spans lose their redirect colour in the span tooltip
`httpStatusTone` returns `neutral` for every code below 400 (http.ts:201), so a 302 falls into the same branch as 2xx and renders `text-severity-info`. The sibling migrations of this helper (traces-table.tsx:115, trace-anatomy-strip.tsx:25) both keep a `code >= 300` branch, so redirects stay distinguishable here only if that branch is restored.
Suggested fix: Keep the 3xx case explicit, e.g. `tone !== "neutral" ? TONE_TEXT[tone] : code >= 300 ? "text-chart-p50" : "text-severity-info"`.

---

F3 · Note · correctness · packages/ui/src/components/service-map/service-map-node.tsx:61
Error-rate thresholds become inclusive on the service map
`errorRateLevel` tests `rate >= 0.05` and `rate >= 0.01` while the local helpers this replaces tested `> 0.05` and `> 0.01`, so exactly 5% now draws the critical dot/border and exactly 1% the warning one. If the new inclusive boundary is intended, it is worth stating it in `error-rate.ts`; otherwise use `>` in the replacement helpers.
Suggested fix: Either accept the inclusive boundary as the contract, or keep the strict comparison in the node's helper.

---

F4 · Note · correctness · apps/web/src/components/code-review/code-review-analytics.tsx:109
"vs previous" subline renders on tiles with no delta
When `previous.pullRequests` / `reviews` / `avgMergeSeconds` is null or 0, `relativeChange` returns null and the tile renders no `Delta`, but `subline={versus}` still claims a comparison against the previous window (also at 116 and 124). The removed `Headline` only showed that label when a delta existed, so the tile now asserts a comparison it has no baseline for.
Suggested fix: Pass `subline` only when the matching `changeOf(...)` returns a ratio, or move the label into `Delta`'s `suffix`.
What was checked
  • ConfirmDialog promise contract at confirm-dialog.tsx:67-78 matches the fix in dba4c12 and the earlier review comment
  • formatCountdown, shortId, widthPercent clamp/round arithmetic checked at zero, negative and non-finite input
  • New Badge/Table/Toggle/Alert variants are additive (new keys only), so existing call sites keep their classes
Files not reviewed (189)

The review ended before it read these diffs, so nothing above vouches for them.

  • apps/local-ui/src/views/metrics-list-view.tsx
  • apps/local-ui/src/views/service-detail-view.tsx
  • apps/local-ui/src/views/trace-detail-view.tsx
  • apps/web/src/components/agent-sessions/agent-sessions-list.tsx
  • apps/web/src/components/agent-sessions/session-detail/payload-view.tsx
  • apps/web/src/components/agent-sessions/session-detail/pill.tsx
  • apps/web/src/components/agent-sessions/session-detail/session-header.tsx
  • apps/web/src/components/agent-sessions/session-detail/session-overview.tsx
  • apps/web/src/components/agent-sessions/session-detail/session-transcript.tsx
  • apps/web/src/components/agent-sessions/session-detail/session-waterfall.tsx
  • apps/web/src/components/agent-sessions/session-detail/span-expansion.tsx
  • apps/web/src/components/agent-sessions/session-detail/tool-io.tsx
  • apps/web/src/components/ai-elements/inline/inline-error.tsx
  • apps/web/src/components/ai-elements/inline/inline-log.tsx
  • apps/web/src/components/ai-elements/inline/inline-service.tsx
  • apps/web/src/components/ai-elements/inline/inline-trace.tsx
  • apps/web/src/components/ai-elements/markdown-table.tsx
  • apps/web/src/components/ai-elements/renderers/components/data-table.tsx
  • apps/web/src/components/ai-elements/renderers/components/error-list.tsx
  • apps/web/src/components/ai-elements/renderers/components/metrics-list.tsx
  • apps/web/src/components/ai-elements/renderers/components/span-tree.tsx
  • apps/web/src/components/ai-elements/renderers/components/trace-list.tsx
  • apps/web/src/components/alerts/alert-severity-badge.tsx
  • apps/web/src/components/alerts/destination-card.tsx
  • apps/web/src/components/alerts/destination-dialog.tsx
  • apps/web/src/components/alerts/notifications-section.tsx
  • apps/web/src/components/analytics/ai/ai-sections.tsx
  • apps/web/src/components/analytics/ai/analytics-ai-tab.tsx
  • apps/web/src/components/analytics/analytics-breakdown-panel.tsx
  • apps/web/src/components/analytics/analytics-metric-strip.tsx
  • and 159 more

9be30bd · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@Makisuo
Makisuo merged commit 4546d3e into main Oct 5, 2026
43 checks passed
@Makisuo
Makisuo deleted the refactor/ui-shared-components branch October 5, 2026 22:04

@maple-review-bot maple-review-bot 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.

2 inline notes from Maple's review. The score and summary are in the review comment above.

confirmLabel="Delete account"
pending={isDeleting}
confirmDisabled={!confirmMatches}
onConfirm={() => void handleDelete()}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

onConfirm={() => void handleDelete()} never closes the delete dialog

F1 · Warning · correctness

ConfirmDialog only auto-closes when the confirm handler returns a promise (confirm-dialog.tsx:67-78), so returning undefined leaves open true. handleDelete resets isDeleting only in its catch and never calls setDeleteOpen(false), so after a successful deleteAccount() the dialog stays mounted with the Cancel button disabled and no way out except the redirect. Pass the promise (onConfirm={handleDelete}) or call setDeleteOpen(false) on success.

`onConfirm={handleDelete}`
🤖 Prompt to fix with an AI agent
In `apps/web/src/components/account/profile-section.tsx:295`: `onConfirm={() => void handleDelete()}` never closes the delete dialog.

`ConfirmDialog` only auto-closes when the confirm handler returns a promise (confirm-dialog.tsx:67-78), so returning `undefined` leaves `open` true. `handleDelete` resets `isDeleting` only in its `catch` and never calls `setDeleteOpen(false)`, so after a successful `deleteAccount()` the dialog stays mounted with the Cancel button disabled and no way out except the redirect. Pass the promise (`onConfirm={handleDelete}`) or call `setDeleteOpen(false)` on success.

Suggested fix: `onConfirm={handleDelete}`

Verify the problem exists at that location before changing it, and keep the fix to those lines.

: httpInfo.statusCode >= 300
? "text-severity-warn"
: "text-severity-info"
httpStatusTone(httpInfo.statusCode) === "neutral"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

3xx spans lose their redirect colour in the span tooltip

F2 · Warning · correctness

httpStatusTone returns neutral for every code below 400 (http.ts:201), so a 302 falls into the same branch as 2xx and renders text-severity-info. The sibling migrations of this helper (traces-table.tsx:115, trace-anatomy-strip.tsx:25) both keep a code >= 300 branch, so redirects stay distinguishable here only if that branch is restored.

Keep the 3xx case explicit, e.g. `tone !== "neutral" ? TONE_TEXT[tone] : code >= 300 ? "text-chart-p50" : "text-severity-info"`.
🤖 Prompt to fix with an AI agent
In `packages/ui/src/components/traces/span-tooltip.tsx:102`: 3xx spans lose their redirect colour in the span tooltip.

`httpStatusTone` returns `neutral` for every code below 400 (http.ts:201), so a 302 falls into the same branch as 2xx and renders `text-severity-info`. The sibling migrations of this helper (traces-table.tsx:115, trace-anatomy-strip.tsx:25) both keep a `code >= 300` branch, so redirects stay distinguishable here only if that branch is restored.

Suggested fix: Keep the 3xx case explicit, e.g. `tone !== "neutral" ? TONE_TEXT[tone] : code >= 300 ? "text-chart-p50" : "text-severity-info"`.

Verify the problem exists at that location before changing it, and keep the fix to those lines.

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