Skip to content

refactor(ui): extract shared DropdownMenu component - #363

Merged
forketyfork merged 2 commits into
mainfrom
refactor/agent-dropdown-menu
Aug 17, 2026
Merged

refactor(ui): extract shared DropdownMenu component#363
forketyfork merged 2 commits into
mainfrom
refactor/agent-dropdown-menu

Conversation

@forketyfork

@forketyfork forketyfork commented Aug 16, 2026

Copy link
Copy Markdown
Owner

Issue

The diff view's "Send to agent" dropdown (diff_overlay.zig) and the selection dialog's agent picker (selection_agent_overlay.zig) were two independently implemented dropdowns. They shared AgentKind and rendering primitives, but each had its own hand-rolled hit-testing, hover tracking, and box/highlight rendering, which could drift out of sync over time.

Solution

Added src/ui/components/dropdown_menu.zig, a reusable DropdownMenu component that:

  • Owns open/hover/keyboard-nav state and the committed selected index.
  • Caches its own item-label textures (invalidated on font-cache generation/size/content changes).
  • Reports a .selected / .closed event on click, Enter, or Escape, so the owning component reacts (persist the pick, or act on it immediately) instead of re-implementing hit-testing and highlight rendering.
  • Takes menu items as a plain []const []const u8, so it's fully generic — not tied to AgentKind.

Both overlays were rewired onto it, removing their duplicated fields (show_agent_dropdown/agent_dropdown_hovered/selected_agent/agent_tex, and the local dropdownItemAt helper) in favor of a single agent_dropdown: DropdownMenu field each.

Two intentional behavior changes fell out of the unification:

  • The diff view's dropdown now supports Up/Down/Enter keyboard navigation, which it didn't have before (only Escape worked).
  • Both dropdowns now seed a highlighted row on open and capture all keyboard input while open, treating an open dropdown as modal to the keyboard — consistent with the selection dialog's prior behavior.

docs/ARCHITECTURE.md was updated with a new table row documenting the shared component and its consumers.

Context

None.

Test plan

  • Open the diff view, add a review comment, click "Send to agent" — confirm the dropdown lists "Paste directly" + each agent, hover/click selection works, and picking an item sends as before.
  • With the "Send to agent" dropdown open, try Up/Down/Enter and Escape — confirm keyboard navigation selects/dismisses correctly.
  • Open the selection-agent dialog (select terminal text, launch agent flow), open the agent selector dropdown, and confirm click/hover/keyboard selection still works and the closed selector shows the chosen agent.
  • Visually compare both dropdowns against main to confirm no unintended styling regressions (colors, radius, fade animation on the diff view's dropdown).

Issue: the diff view's "Send to agent" dropdown and the selection dialog's
agent picker were two independently implemented dropdowns, duplicating
hit-testing, hover tracking, and box/highlight rendering.
Solution: added ui/components/dropdown_menu.zig with a DropdownMenu that
owns open/hover/keyboard-nav state and the committed selection, caches its
own label textures, and reports a .selected/.closed event so callers react
instead of tracking picks themselves. Both overlays were rewired onto it,
and the diff view's dropdown gained keyboard navigation it didn't have
before.
@forketyfork
forketyfork requested a balanced review from Copilot August 16, 2026 20:26
@forketyfork
forketyfork marked this pull request as ready for review August 16, 2026 20:26

Copilot AI 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.

Pull request overview

Extracts duplicated agent-picker behavior into a reusable dropdown component.

Changes:

  • Adds shared dropdown state, rendering, caching, and tests.
  • Migrates both agent dropdown consumers.
  • Documents and registers the new component’s tests.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/ui/components/dropdown_menu.zig Implements the shared dropdown.
src/ui/components/selection_agent_overlay.zig Adopts the shared dropdown.
src/ui/components/diff_overlay.zig Adopts dropdown keyboard and selection handling.
src/main.zig Registers dropdown tests.
docs/ARCHITECTURE.md Documents the component.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/ui/components/selection_agent_overlay.zig
Comment thread src/ui/components/diff_overlay.zig Outdated
Issue: PR review flagged that the new DropdownMenu keyboard handling
wasn't actually exclusive: SDL_EVENT_TEXT_INPUT bypassed the dropdown-open
check in both overlays and kept inserting into the prompt/comment editor,
and in diff_overlay.zig the dropdown's KEY_DOWN handling ran after the
comment-editor branch, so Up/Down/Enter went to the editor instead of the
menu whenever a comment was being edited.
Solution: gate SDL_EVENT_TEXT_INPUT on `agent_dropdown.open` in both
overlays, and move diff_overlay.zig's dropdown KEY_DOWN handling above the
editor_interactive branch so an open dropdown always wins keyboard
priority. Added regression tests for both event-ordering bugs, and
registered diff_overlay.zig in the test suite (it previously had no
tests, so it wasn't wired into main.zig's test import block).

Addresses PR #363 review comments 3792751196 and 3792751210.
@forketyfork
forketyfork merged commit e4377a3 into main Aug 17, 2026
4 checks passed
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.

2 participants