Repository navigation
feat(plugin): let composer pills render their own popover content - #59764
Merged
Merged
Conversation
Replace ComposerPillView.actions with ComposerPill.menu: the host keeps the capsule and the popover (placement, focus, dismissal, heading) and the plugin renders what goes inside. The goal pill uses it for its pause, resume and clear buttons.
opencode-agent
Bot
requested review from
Brendonovich and
Hona
as code owners
October 27, 2026 23:18
3 of 6 tasks
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.
Stacked on #59437, targeting
client-done-check.Lets a composer pill render its own popover content instead of adding more declarative fields to the view. The host keeps the pill and the overlay; the plugin owns only what's inside, like every other slot.
SDK (
packages/plugin/src/gui/registries.ts)ComposerPillActionandComposerPillView.actions(added in feat(core): add /goal with a client-side done check #59437, never shipped).ComposerPill.menu?(input: ComposerPillMenuProps): JSX.Element, whereComposerPillMenuPropsisComposerPillPropsplusclose().menulives on the pill rather than the view:showre-runs whenever its inputs change, so a render function on the view would remount the content on every goal update. On the item it renders once per open and updates through its own reactivity, likeSlot.renderandPanel.render.menu, clicking it opens the popover and the view'srows/runare unused. The capsule stays locked tolabel,icon,toneandtitle.Host (
packages/app/src/session/composer/plugin-pills.tsx)menuopens a KobaltePopover(as the todo pill does), notMenu, because arbitrary content does not belong in a menu's keyboard model. The host renders the heading (title ?? label, three lines max) and the panel chrome, then the plugin's content, untracked and inside the plugin's existingContributionerror boundary.Goal plugin
@opencode/uiButtons in the goal'smenu. Each one closes the popover and then sends the command.Tests
menu: the host heading, the plugin content,menuwinning overrows,close(), and a fresh render on reopen. Makingclosea no-op makes the new story fail.Checks
plugin,gui-pluginsandappbun run lint:changedscript/sdk-docs.tsplugin-host.spec.ts -g "composer pill": 2 passedI haven't checked the goal popover visually against a real session.
Requested by: @neriousy (Filip via Slack)