refactor(ui): extract shared DropdownMenu component - #363
Merged
Conversation
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.
There was a problem hiding this comment.
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.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 sharedAgentKindand 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 reusableDropdownMenucomponent that:selectedindex..selected/.closedevent 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.[]const []const u8, so it's fully generic — not tied toAgentKind.Both overlays were rewired onto it, removing their duplicated fields (
show_agent_dropdown/agent_dropdown_hovered/selected_agent/agent_tex, and the localdropdownItemAthelper) in favor of a singleagent_dropdown: DropdownMenufield each.Two intentional behavior changes fell out of the unification:
docs/ARCHITECTURE.mdwas updated with a new table row documenting the shared component and its consumers.Context
None.
Test plan
mainto confirm no unintended styling regressions (colors, radius, fade animation on the diff view's dropdown).