Skip to content

feat(menu): open a provider's full card in a hover flyout - #4902

Open
Chipagosfinest wants to merge 3 commits into
steipete:mainfrom
Chipagosfinest:design-v2/menu-hover-flyout
Open

Chipagosfinest wants to merge 3 commits into
steipete:mainfrom
Chipagosfinest:design-v2/menu-hover-flyout

Conversation

@Chipagosfinest

@Chipagosfinest Chipagosfinest commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Part of a four-PR Overview redesign, each standalone on main: #4899 rows, #4900 footer, #4901 chart, #4902 flyout. Rebase needed after #4899: see below.

Hovering a row in compact Overview opens the provider's full card beside the menu, with its chart one level further in. A click still opens the provider's tab, and the parent menu does not move, so detail can't push the footer away. Detailed keeps its chart submenu.

Packaged-app interaction proof (2026-11-02 UTC)

Actual-app run · screenshots, recording, checks, saved defaults and hashes. Product 0ff1e04c1043ebb549dd0df28f34884141fd3b90, unmodified release package; installed binary matches the package. Real CGEvent pointer input. Synthetic fixture data; saved Compact with three selected providers on 1024×768. No real accounts or Keychain prompts. 18 of 18 checks pass. This is the standalone head, before #4899's one-line rows.

Show details, the same click before and after the fix:

Before (ccadfbc33, run) After (0ff1e04c1)
Click
Reopen the menu Still on Overview On the Claude tab
Saved mergedMenuLastSelectedWasOverview true false, selectedMenuProvider = claude

The after-run passes both routes: straight to the item, and after visiting the nested chart. Recording · checks.json.

The rest still holds on this head:

Exact interaction Inspected actual screen / result
Pointer hover opens full card v2-hover-claude-flyout-screen.png: Session 65%, Weekly 78%, Plan Usage and Show details.
Nested chart reached from flyout v3-nested-chart-screen.png
Pointer click on Compact row selects Claude v10-row-click-selects-provider-screen.png
Normal Refresh with Overview open, then reopen r1-first-flyout-screen.png → r3-reopened-flyout-screen.png: Session 30%, Weekly 56%, new Sonnet 20%, height 250 → 290pt; provider request recorded in the refresh phase.

Root cause, from a lifecycle log on a temporary instrumented build (run), the same in 3 of 3 clicks. Passing over Plan Usage opens and closes its chart, which queues a flyout rebuild that waits on the native highlight. Mouse-up clears the highlight, so the rebuild ran and removeAllItems() detached the clicked item. AppKit then still sent the action, with sender.menu == nil, and selectOverviewProvider(_:) returned without selecting.

Fix: mouse-up no longer resumes the deferred rebuild, since the menu is closing and the next open rebuilds anyway. The action also falls back to the merged menu, for a data refresh landing in the same gap, and still selects through selectOverviewProvider.

The same log shows the flyout rebuilding on every open with the fixture's reset countdowns, even without new provider data. I think the countdown text changes its signature; I did not confirm that. It is unchanged here and did not affect these results.

Screenshots retain the native full-SHA/synthetic banner. No post-#4899 integration claim is made. The rebase stays pending until #4899 merges.

Earlier appearance references (test-menu / optional local integration)
Hover a row Before (main): chart After: full card
Dark
Light

Each shot is a real NSMenu popped on macOS by production populateMenu, captured by window ID from a local test target (kit). Data is synthetic. This is not a packaged-app run: this Mac has no Xcode, so the app bundle can't be built here. The flyout was opened by warping the cursor onto the row and posting a mouse-moved event, and its window was then present beside the menu.

Combined with the other three PRs (local merge, not on any branch), on the one-line rows:

Optional comparison outside this PR head: combined local-integration capture.

Known limits

  • Tall card: the flyout is 946pt here, because it reuses main's full card. It fits this display but is taller than the redesign's target of about 485pt, which needs a separate denser-card change that is not in this series.
  • Brand-coloured bars: that card keeps its existing brand-coloured bars and chart, including Claude's coral on dark.
  • Not tried by hand: AppKit delays submenus, but moving down the list with a real mouse could still flash flyouts.

After #4899 merges

This wires the flyout into main's row loop. #4899 adds a new row path, so one line must move there, and row tests must go through the flyout's "Show details". The exact change was verified on the local merge: 565 tests in 43 suites, 1 failure (the same flake below).

Tests

  • New OverviewProviderFlyoutTests: the flyout carries the detail, reopening never rebuilds it as the root menu (the type marks it hosted), the parent keeps its items, "Show details" opens the tab through the parent, Detailed keeps its chart.
  • Lifecycle regressions in that suite: one replays the logged order (chart closes, highlight, mouse-up, menus close, then AppKit sendAction from the item), the other sends the action from an item a rebuild already detached. Both fail without the fix and pass with it (6 of 6 in the suite locally; the full suite runs in CI).
  • Focused run: 532 tests in 39 suites, 1 failure. StatusMenuScopedCodexRefreshTests "scoped refresh publishes compatible quota" fails under load in this harness, on untouched main too, and passes alone.
  • make check: format, lint and locale checks pass, then it stops at test_packaged_app_launch.py, which fails identically on main on this Mac. XCTest suites can't run here (no Xcode), so those rely on CI.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@clawsweeper

clawsweeper Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-01T22:33:06.023827Z c254d8b PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c254d8b459

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

private func hostedSubviewIdentity(for menu: NSMenu)
-> HostedSubviewIdentity? {
// Its rows are built with the flyout, and "Show details" carries a row ID rather than a chart ID.
if menu is OverviewProviderDetailMenu, menu.items.first?.view != nil { return nil }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Refresh hydrated flyouts when their model changes

If a previously opened flyout is hovered again after a background refresh adds a quota window or changes provider details while Overview remains open, this early return leaves refreshHostedSubviewMenu doing only a height refresh. MenuCardRefreshMonitor.model cannot supply the new data because its hasCompatibleTrackedLayout check rejects those changes, and the root menu deliberately defers rebuilding during tracking. Consequently, the newly reopened full card still shows its original snapshot until the root menu is rebuilt. Retain the provider identity and refresh/rebuild the detail content on reopen, as the existing hosted chart submenus do.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in ccadfbc: the flyout menu keeps its provider, so hostedSubviewIdentity still resolves after hydration. Its render signature covers the current card model, so a reopen rebuilds only when the data changed, like the hosted chart submenus. Covered by a reopened flyout rebuilds only when its provider's data changed, which fails without the fix and also asserts no rebuild when nothing changed.

@clawsweeper clawsweeper Bot added clawsweeper:intake:feature Preliminary submission classification; full source review pending. P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed clawsweeper:intake:feature Preliminary submission classification; full source review pending. labels Nov 1, 2026
@clawsweeper

clawsweeper Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Codex review: blocked before merge.

What this changes

This PR replaces Compact Overview’s chart hover submenu with a full provider card containing a nested chart and Show details action.

Example: Hover Claude in Compact Overview with Session 65% and Weekly 78% remaining.

  • Before: The row opens its chart submenu directly.
  • After: The row opens the full Claude card, with Plan Usage and Show details below it.

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) Strong app evidence resolves the earlier blockers; incomplete storage invalidation and unresolved product direction prevent readiness.
Proof confidence 🦞 diamond lobster (5/6) ✨ media proof bonus Sufficient (screenshot): The unmodified packaged app at the reviewed head is shown using synthetic data on a 1024×768 display: hover opens the full card, its nested chart is reachable, direct and post-chart Show details activation select Claude, row clicks select the provider, and refresh adds the Sonnet window with updated values.
Patch quality 🦐 gold shrimp (3/6) 1 actionable review finding remain.

Product

Kind: Feature · Worth it: Needs a maintainer decision · Fix scope: Complete
User problem: Compact Overview omits full provider detail, requiring users to switch tabs to inspect it.
Reason: The flyout provides useful detail without enlarging the parent menu, but changes an existing owner-built hover interaction.

Merge readiness

⛔ Blocked before merge - 2 items remain

Keep open: the earlier findings are resolved, but storage-only updates can leave the flyout stale, and the new hover interaction needs an owner decision.

Priority: P3
Reviewed head: 0ff1e04c1043ebb549dd0df28f34884141fd3b90
Owner decision: Required. See Decision needed.

Decision needed

  • Question: Should existing Compact Overview users get a full-card hover flyout with charts moved one level deeper?
  • Recommendation: Adopt the full-card flyout: Approve the additional detail on hover while retaining direct row navigation and Detailed’s existing chart interaction.
  • Why: This changes the interaction established by Compact Overview, and the reviewed discussion contains no owner approval of that direction.

Before merge

  • Include storage content in the flyout reuse signature (P2) - With storage footprints enabled, a scan can change the displayed storage total while the provider’s usage-card model remains unchanged—for example, an unavailable provider with a stable error. appendOverviewProviderDetail captures storageFootprintText separately, but this signature omits it, so refreshHostedSubviewMenu returns early and the open flyout retains the old total or omits newly available storage content until another change rebuilds it. Include the storage presentation in the signature and cover a storage-only update. This concern was missed in the earlier review: the responsible line is unchanged from ccadfbc.
  • Resolve maintainer decision - Resolve the maintainer decision shown above before merge.

Findings

  • [P2] Include storage content in the flyout reuse signature — Sources/CodexBar/StatusItem/StatusItemController+HostedSubmenus.swift:299-301
Agent review details

How this fits together

The menu controller turns cached provider models and storage footprints into Overview rows, hosted flyouts, charts, and provider-tab navigation.

flowchart LR
  A[Provider snapshots] --> C[Menu controller]
  B[Storage footprints] --> C
  C --> D[Compact Overview row]
  D --> E[Full card flyout]
  E --> F[Nested chart]
  E --> G[Provider tab]
Loading

Technical review

Best possible solution:

Reuse the existing hosted-menu lifecycle, include separately rendered storage content in invalidation, and adopt the hover change only with owner agreement.

Do we have a high-confidence way to reproduce the issue?

Source shows that a storage-only update leaves the usage-model signature unchanged and skips rebuilding the captured storage text; this review did not execute target code.

Is this the best way to solve the issue?

Reusing full-card rendering and hosted submenus is appropriately scoped, but the reuse signature must cover all content captured by the flyout.

Full review comments:

  • [P2] Include storage content in the flyout reuse signature — Sources/CodexBar/StatusItem/StatusItemController+HostedSubmenus.swift:299-301
    With storage footprints enabled, a scan can change the displayed storage total while the provider’s usage-card model remains unchanged—for example, an unavailable provider with a stable error. appendOverviewProviderDetail captures storageFootprintText separately, but this signature omits it, so refreshHostedSubviewMenu returns early and the open flyout retains the old total or omits newly available storage content until another change rebuilds it. Include the storage presentation in the signature and cover a storage-only update. This concern was missed in the earlier review: the responsible line is unchanged from ccadfbc.
    Confidence: 0.92
    Late finding: first raised on code an earlier review cycle already covered.

Overall correctness: patch is incorrect
Overall confidence: 0.92

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 897bff31731b.

Provenance checked

  • Compact Overview hover behavior changes intended behavior with a stated reason (0741047: Compact reduced card detail while sharing submenu behavior and provider navigation with Detailed.)
  • Overview account and plugin boundaries keeps the original intent (096c957: Account rows deliberately omitted provider-level history submenus; plugin rows use their existing independent rendering path.)
  • Provider selection lifecycle keeps the original intent (9778128: Provider selection preserves shared menu caches and avoids expensive structural work during activation; the new fallback retains that owner.)
  • Native-highlight rebuild deferral changes intended behavior with a stated reason (fe52324: Selection tracking preserves native interactions; the latest change explains and demonstrates why mouse-up must not resume a rebuild before action delivery.)

Testing

Proof path: shipped entry point.

Security

None.

Evidence

What I checked:

Likely related people:

  • Peter Steinberger: Raw commit 096c957 adds Sources/CodexBar/StatusItemController+Menu.swift:621 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 096c957f9c5c; files: Sources/CodexBar/StatusItemController+Menu.swift)
  • Zihao Qi: Raw commit 0741047 adds Sources/CodexBar/StatusItemController+MenuTypes.swift:42 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 0741047cb7a2; files: Sources/CodexBar/StatusItemController+MenuTypes.swift)

Labels

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action.
  • remove status: 📣 needs proof: Current PR status label is status: ⏳ waiting on author.
  • remove rating: 🦪 silver shellfish: Current PR rating is rating: 🦐 gold shrimp, so this older rating label is no longer current.

Label justifications:

  • P3: This is an optional menu navigation improvement with limited user impact.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action.
  • proof: sufficient: Contributor real behavior proof is sufficient.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

History

Review history (3 earlier review cycles)
  • reviewed 2026-11-01T22:42:26.383Z sha c254d8b :: needs real behavior proof before merge. :: [P2] Refresh the provider card when reopening a hydrated flyout
  • reviewed 2026-11-02T01:10:48.463Z sha ccadfbc :: needs real behavior proof before merge. :: none
  • reviewed 2026-11-02T02:41:26.724Z sha ccadfbc :: needs real behavior proof before merge. :: [P2] Make Show details select its provider during native activation

Reviewed November 2, 2026, 12:55 AM ET / 05:55 UTC (Revision 4).

Keep the provider on the flyout menu so reopening compares the current
card model against what was rendered and rebuilds a stale card, the same
way hosted chart submenus do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chipagosfinest pushed a commit to Chipagosfinest/CodexBar that referenced this pull request Nov 2, 2026
@Chipagosfinest

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot added clawsweeper:intake:feature Preliminary submission classification; full source review pending. and removed clawsweeper:intake:feature Preliminary submission classification; full source review pending. labels Nov 2, 2026
Chipagosfinest pushed a commit to Chipagosfinest/CodexBar that referenced this pull request Nov 2, 2026
Chipagosfinest pushed a commit to Chipagosfinest/CodexBar that referenced this pull request Nov 2, 2026
Chipagosfinest pushed a commit to Chipagosfinest/CodexBar that referenced this pull request Nov 2, 2026
Chipagosfinest pushed a commit to Chipagosfinest/CodexBar that referenced this pull request Nov 2, 2026
Chipagosfinest pushed a commit to Chipagosfinest/CodexBar that referenced this pull request Nov 2, 2026
@Chipagosfinest

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot added clawsweeper:intake:feature Preliminary submission classification; full source review pending. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. clawsweeper:intake:feature Preliminary submission classification; full source review pending. labels Nov 2, 2026
@clawsweeper clawsweeper Bot added the rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. label Nov 2, 2026
A real click cleared the native highlight, which resumed a flyout rebuild queued when the nested chart closed. That rebuild detached the clicked item before AppKit sent its action, so the selector saw no menu and returned.

Mouse-up no longer resumes the deferred rebuild, and the action falls back to the merged menu if another rebuild detached its item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chipagosfinest pushed a commit to Chipagosfinest/CodexBar that referenced this pull request Nov 2, 2026
@Chipagosfinest

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot added clawsweeper:intake:feature Preliminary submission classification; full source review pending. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. clawsweeper:intake:feature Preliminary submission classification; full source review pending. labels Nov 2, 2026

This branch has not been deployed

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

Labels

P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant