Skip to content

Conversation

@joaomoreno
Copy link
Member

@joaomoreno joaomoreno commented Nov 16, 2025

Fixes #238095


Brainstorming session with @bpasero and @lszomoru:

Here's how we stitch things up:

We decorate the DOM:

<div quick-pick-in-context="ID">
  <span>Encoding</span>
</div>

Then we augment the quick pick service API to allow passing an anchor name (anchor) that would match up with ID.

The quick pick service should:

  1. Track mouse clicks and keyboard presses.
  2. Whenever the mouse gets clicked or Enter gets pressed and the current active element is within a DOM hierarchy that contains [quick-pick-in-context], then remember that ID and DOM node as state.
  3. If there's any mouse click or keyboard press meanwhile, clear that state.
  4. Likewise, if there's any generic quick pick invocation, clear that state.
  5. If, on the other hand, there's a quick pick invocation that passes anchor: ID, then render it in context and clear that state.

@joaomoreno joaomoreno added this to the November 2025 milestone Nov 16, 2025
Copilot AI review requested due to automatic review settings November 16, 2025 13:19
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for in-context quick pick functionality, allowing quick pick dialogs to be positioned relative to UI elements (like buttons) rather than always appearing centered. The main implementation involves refactoring layout logic into a common module and extending the quick input system with anchor positioning.

Key changes:

  • Refactored layout logic from contextview into a new common/layout.ts module for reusability
  • Extended quick input API to accept anchor positioning parameters
  • Integrated anchor-based positioning into the SCM history view's repository picker

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/vs/base/common/layout.ts New file containing extracted layout logic for positioning views relative to anchors
src/vs/base/browser/ui/contextview/contextview.ts Refactored to use common layout module and export getAnchorRect utility
src/vs/base/browser/ui/menu/menu.ts Updated to use refactored layout API which now returns an object instead of a number
src/vs/platform/quickinput/common/quickInput.ts Added anchor property to IPickOptions and IQuickInput interfaces
src/vs/platform/quickinput/browser/quickInputController.ts Implemented anchor-based positioning logic in updateLayout method
src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts Modified repository picker to pass anchor element through the call chain
src/vs/base/test/common/layout.test.ts Updated tests to access position property from layout function's return value

}

override onClick(event: EventLike, preserveFocus?: boolean): void {
this.actionRunner?.run(this.action, this.element);
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

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

The onClick override ignores both the event and preserveFocus parameters. The event parameter should be passed to the action runner as the second argument (where this.element is currently passed) to provide anchor positioning context. Based on the PR's purpose, this.element appears to be the anchor element, but it should come from the event target.

Suggested change
this.actionRunner?.run(this.action, this.element);
const anchor = (event && typeof event === 'object' && 'target' in event && event.target) ? event.target : this.element;
this.actionRunner?.run(this.action, anchor);

Copilot uses AI. Check for mistakes.
@joaomoreno
Copy link
Member Author

@lszomoru and I got this to work for some status bar items, there were challenges:

  • We had to figure out how to wire anchors up in the layers
  • We also had to make QuickAccess work (for Go To Line/Column)

We found pre-existing issues:

  • Pressing Enter while DOM focused on the Select Indentation status bar item will immediately select the first item.
  • The line ending command would always focus the editor even if the user cancelled the quick pick operation. We fixed this.

Known issues:

  • Multi level quick picks are not solved. For example, click the line ending and choose the first option. You will get an in context quick pick and a global one. How can we wire these two up together? Should we just rely on focus being restored to the element that was clicked/pressed Enter?
  • We learned that the Change Indentation status bar command sets focus in the active editor regardless of whether the user makes a decision to change any indentation in the next quick picks. This was causing the second quick pick to be global and not in context. We pushed a hack to comment out that focus call, and it needs to be moved into each command that actually needs it.
  • Many status bar items have the window id in their id, which we now use to name anchors. This is problematic in indentation.ts where we need to specify an id, and just decided to hack it in for now.

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.

Explore a QuickPick-like experience close to what invoked it

4 participants