Skip to content

sessions: add rich GitHub reference previews - #335583

Open
Cherry Wang (chryw) wants to merge 14 commits into
mainfrom
dev/cherwan/agents/popup-layout-design-issue-metadata
Open

sessions: add rich GitHub reference previews#335583
Cherry Wang (chryw) wants to merge 14 commits into
mainfrom
dev/cherwan/agents/popup-layout-design-issue-metadata

Conversation

@chryw

@chryw Cherry Wang (chryw) commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Exploratory follow-up to #335448, building on the first-level title work from #335387.

This proposal adds a compact issue/PR preview to Agents Window reference pills so users can identify a GitHub object and decide whether to open it without leaving their current context.

Design rationale

  • Progressive disclosure: collections keep the existing scannable list; focusing a row reveals detail. A single reference shows the same detail directly.
  • Source-product hierarchy: GitHub's own hover cards inform the order of information, while VS Code continues to own typography, color, spacing, popup chrome, focus, and keyboard behavior. Collection rows lead with the lifecycle icon, followed by the canonical title and a muted trailing ID.
  • Bounded transient content: the card provides identity and enough context to make a decision, rather than becoming a full issue reader.
  • Consistent information budget: standalone and collection cards contain the same information; only their outer density differs.

The resulting card order is repository/date → title/ID → lifecycle and CI state → bounded description → PR branches → author. Open and draft pull requests show the shared overall checks state as Checks pending, Checks failed, or Checks passed; closed, merged, and no-check states stay quiet. Pending uses GitHub's familiar attention-colored static dot rather than a spinner or sync metaphor because the aggregate may include both queued and running checks. Both status pills use neutral text and surfaces, while their icons carry restrained semantic color.

Descriptions are normalized from Markdown and bounded to 200 Unicode code points. Visible titles are bounded to 80 Unicode code points. The final visible title word and linked ID are grouped so the number cannot interrupt the sentence or become clipped at narrow widths.

#335448 also explores a full Markdown reader across broader GitHub-reference surfaces; this iteration focuses on the compact pill-hover treatment.

What inspired the design

  • GitHub hover cards: provenance first, title and ID as the lead, state next, then context, routing details, and authorship/viewer context.
  • GitLab and GitHub PR experiences: emphasize identity, state, and short context before secondary metadata.
  • Linear/Slack unfurls: keep transient previews concise and action-oriented instead of reproducing the full work item.
  • JetBrains and VS Code GitHub PR lists: use an overall checks result in compact references, while reserving individual checks, review state, and denser metadata for persistent triage surfaces.
  • Existing VS Code patterns: reuse the issue/PR hover components, ActionList list/dialog semantics, SessionSummaryHover hierarchy, branch pills, popup chrome, focus indicators, and spacing tokens.

Those examples drove the current boundary: enough content to understand and route the reference, with individual checks, labels, reactions, comments, assignees, and full Markdown left to richer or persistent surfaces.

Collection item interactions

Pull request collection

Pull request collection expanded with the first-level list and second-level rich preview showing draft and checks-pending status

github-hover-collection-pr.mp4

Starts on the focused Pull Requests parent pill, opens the first-level list, moves across PR states and the live overall CI result, then traverses Copy URL, repository, ID, and base/head branches. The clip follows the complete reverse Shift+Tab sequence back through every card control and row action.

Issue collection

Issue collection expanded with the first-level list and second-level rich issue preview

github-hover-collection-issue.mp4

Starts on the focused Issues parent pill, opens the first-level list, covers long-title/closed/open rows, then traverses Copy URL, repository, and ID before reversing through each control back to the list.

Single-reference interactions

A single reference skips the list but keeps the same information budget.

Single pull request

Single pull request chip expanded with its rich preview showing draft and checks-pending status

github-hover-single-pr.mp4

Uses Shift+Tab and ArrowRight to focus the direct PR chip, then opens its hover with the live overall CI result and moves through repository, linked ID, and base/head branch controls.

Single issue

Single issue chip expanded with its rich issue preview

github-hover-single-issue.mp4

Uses Shift+Tab and ArrowRight to focus the direct issue chip, then opens its hover and moves through repository and linked ID.

Keyboard and screen-reader behavior

  • Collections: Shift+Tab from the chat input focuses the first pill; Left/Right moves between pills.
  • Collections: Enter/Space opens the list, Up/Down moves through rows, and the metadata card follows the focused item.
  • Collections: Tab moves through Copy URL, repository, resource ID, and PR branch controls; Shift+Tab returns to Copy URL.
  • Single references: Enter/Space activates the reference directly; pointer hover exposes the same detail content and its links/branch controls.
  • The listbox retains keyboard focus while the named detail dialog remains available in screen-reader reading order.
  • Rows announce the full resource title, lifecycle state, and overall CI result. The detail card reads provenance → title/ID → lifecycle/CI state → description → branches → author.
  • Focusing a bounded title's ID reveals the full canonical title; blur restores the compact title.

Implementation

  • reuses ChatDropdownPillActionViewItem, ActionListWidget, createIssueHoverElement, and createPullRequestHoverElement
  • keeps standalone and collection content identical
  • reads the existing shared CI model; no additional GitHub request path is introduced
  • polls CI for open pull requests, including drafts, while keeping review-thread icon refinement limited to non-drafts
  • preserves GitHub's distinct Duplicate and Not planned issue terminology
  • makes ActionList and managed-hover padding ownership explicit instead of using compensating offsets
  • uses standard ActionWidget border, radius, background, shadow, and spacing tokens
  • uses measured panel dimensions for viewport positioning

Validation

  • npm run compile
  • npm run typecheck-client
  • targeted ESLint and stylelint
  • focused ActionList and Sessions toolbar tests: 103 passing
  • dark/light and keyboard-focus fixtures
  • standalone issue and PR paths
  • live Open, Draft, Closed, Merged, Completed, and Not planned resources
  • live draft PR with pending checks; unit coverage for pending, passing, failing, and no-check states
  • 567-character title and 300px-width stress cases
  • linked ID remains fully visible and focusing it does not scroll clipped content

Related

Copilot AI balanced review requested due to automatic review settings September 10, 2026 22:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Several moderate review findings remain around focus behavior, event propagation, and regression coverage.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This pull request adds rich GitHub issue and pull-request previews to Sessions pills, with keyboard-accessible detail cards.

Changes:

  • Adds lifecycle metadata, descriptions, links, and branch-copy controls.
  • Integrates ActionList focus traversal and padding ownership.
  • Adds styling, tests, accessibility guidance, and fixtures.
File summaries
File Description
src/vs/workbench/test/browser/componentFixtures/sessions/githubReferenceHoverLayouts.fixture.ts Adds themed GitHub hover layout fixtures.
src/vs/workbench/contrib/chat/browser/chatInputPills.ts Exposes chat pill focus behavior.
src/vs/workbench/browser/chatPills.ts Supports enriched entries and first-pill focusing.
src/vs/sessions/contrib/github/common/types.ts Extends GitHub models with closure metadata.
src/vs/sessions/contrib/github/browser/pullRequestHover.ts Renders PR details and branch-copy controls.
src/vs/sessions/contrib/github/browser/media/pullRequestHover.css Styles PR cards and branch pills.
src/vs/sessions/contrib/github/browser/media/issueHover.css Styles issue cards.
src/vs/sessions/contrib/github/browser/issueHover.ts Renders issue preview cards.
src/vs/sessions/contrib/github/browser/githubHover.ts Normalizes and bounds descriptions.
src/vs/sessions/contrib/github/browser/fetchers/githubPRFetcher.ts Maps GitHub closure dates.
src/vs/sessions/contrib/chat/test/browser/sessionChatInputToolbar.test.ts Tests rich preview behavior and controls.
src/vs/sessions/contrib/chat/browser/sessionsChatAccessibilityHelp.ts Documents pill keyboard navigation.
src/vs/sessions/contrib/chat/browser/sessionChatInputToolbar.ts Builds rich GitHub pill entries.
src/vs/sessions/contrib/chat/browser/chatView.ts Routes Shift+Tab to visible pills.
src/vs/platform/actionWidget/test/browser/actionList.test.ts Tests panel keyboard navigation.
src/vs/platform/actionWidget/browser/actionWidget.css Styles content-owned panel padding.
src/vs/platform/actionWidget/browser/actionList.ts Adds panel focus and padding contracts.
Review details

Suppressed comments (5)

src/vs/platform/actionWidget/browser/actionList.ts:2286

  • When a row has both Copy URL and Remove (multi-entry pull-request pills append removeAction after toolbarActions), this always focuses the last toolbar action. Shift+Tab from the detail card therefore lands on Remove instead of Copy URL, contradicting the documented focus order. Please define the intended return action for this traversal (or reorder/exclude the removal action) and cover the multi-action case.
			if (inPanel) {
				if (controls.toolbar?.length()) {
					dom.EventHelper.stop(event, true);
					controls.toolbar.focus(controls.toolbar.length() - 1);

src/vs/sessions/contrib/chat/browser/chatView.ts:351

  • This handler routes only Shift+Tab from the chat input into the pills, but the existing sessionsChat.inputPills accessibility-help entry still tells users to press Tab to reach the pills above the input. Normal Tab is not intercepted here, so that instruction does not reach the intended control; update the help text to match this Shift+Tab behavior.
			if (event.keyCode === KeyCode.Tab && event.shiftKey && !event.ctrlKey && !event.metaKey && !event.altKey && this._chatPills.focusFirst()) {

src/vs/sessions/contrib/chat/browser/chatView.ts:354

  • This adds a new global Shift+Tab focus transition, but the Sessions ChatView tests do not dispatch this handler. A regression in the modifier filtering, focusFirst() result, or cancellation behavior could silently break keyboard access to the status pills; add a focused test for the matching and non-matching paths.
		this._register(this._widget.inputEditor.onKeyDown(event => {
			if (event.keyCode === KeyCode.Tab && event.shiftKey && !event.ctrlKey && !event.metaKey && !event.altKey && this._chatPills.focusFirst()) {
				event.preventDefault();
				event.stopPropagation();
			}

src/vs/sessions/contrib/github/browser/fetchers/githubPRFetcher.ts:352

  • The new closedAt mapping drives the card's closed-PR transition date, but the fetcher tests never include closed_at in makePRResponse or assert pr.data?.closedAt. A regression in this wire-to-domain mapping would therefore leave the UI showing the updated date while all current tests still pass; add a response fixture and assertion for the closed timestamp.
		...(data.closed_at ? { closedAt: data.closed_at } : {}),

src/vs/sessions/contrib/github/browser/pullRequestHover.ts:143

  • Activating either branch button bubbles a click to the ActionList root. Unlike the link handler above, this callback does not stop propagation, so List.onViewPointer sees a click outside a row and clears the focused row. After copying a branch, Up/Down and the panel Tab sequence lose their list context; stop propagation before invoking the copy callback.
	branch.onclick = onDidClick;
  • Files reviewed: 17/17 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/vs/sessions/contrib/github/browser/pullRequestHover.ts Outdated
@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Screenshot Changes

Base: d0bfeb17 Current: 49699daf

3 insignificant change(s) omitted (≤20 px, Δ≤2). See CI logs for details.

Added (12)

sessions/githubReferenceHoverLayouts/GitHubReferenceHover_Issue/Dark

current

sessions/githubReferenceHoverLayouts/GitHubReferenceHover_Issue/Light

current

sessions/githubReferenceHoverLayouts/GitHubReferenceHover_PullRequest/Dark

current

sessions/githubReferenceHoverLayouts/GitHubReferenceHover_PullRequest/Light

current

sessions/githubReferenceHoverLayouts/GitHubReferenceHover_SingleIssue/Dark

current

sessions/githubReferenceHoverLayouts/GitHubReferenceHover_SingleIssue/Light

current

sessions/githubReferenceHoverLayouts/GitHubReferenceHover_SinglePullRequest/Dark

current

sessions/githubReferenceHoverLayouts/GitHubReferenceHover_SinglePullRequest/Light

current

sessions/githubReferenceHoverLayouts/GitHubReferenceHover_LongTitleCollectionIssue/Dark

current

sessions/githubReferenceHoverLayouts/GitHubReferenceHover_LongTitleCollectionIssue/Light

current

sessions/githubReferenceHoverLayouts/GitHubReferenceHover_LongTitleSingleIssue/Dark

current

sessions/githubReferenceHoverLayouts/GitHubReferenceHover_LongTitleSingleIssue/Light

current

@chryw

Copy link
Copy Markdown
Contributor Author

Addressed the remaining review findings from the latest Copilot review pass (a4c1c0c7aad):

  • actionList.ts: Shift+Tab from the hover panel now returns to the last non-removal toolbar action (skips a trailing Remove action) instead of always focusing toolbar.length() - 1. Added a multi-action (Copy + Remove) regression test.
  • chatView.ts: extracted the Shift+Tab-to-pills condition into isFocusChatPillsKeyDown and added regression tests for modifier filtering and the preventDefault/stopPropagation cancellation path. Updated the sessionsChat.inputPills accessibility-help string to say Shift+Tab (it previously said Tab).
  • githubPRFetcher.ts: added a fixture/assertion covering the closed_atclosedAt mapping (both present and absent cases).
  • pullRequestHover.ts: branch-pill clicks now call stopPropagation() so copying a branch no longer clears the owning ActionList row's focus. Added a regression test asserting the click doesn't bubble to an ancestor row.

Also rebased onto latest main (no conflicts) and pushed.

@chryw
Cherry Wang (chryw) force-pushed the dev/cherwan/agents/popup-layout-design-issue-metadata branch 3 times, most recently from ad39018 to 5123a6d Compare September 11, 2026 19:02
@chryw
Cherry Wang (chryw) marked this pull request as ready for review September 11, 2026 19:23
@chryw
Cherry Wang (chryw) force-pushed the dev/cherwan/agents/popup-layout-design-issue-metadata branch from 8ea390f to c849093 Compare September 11, 2026 20:01
Cherry Wang (chryw) and others added 14 commits September 11, 2026 14:00
Reuse the existing issue and pull request hover components for dropdown details, with compact metadata, explicit spacing ownership, and bounded readable descriptions. Integrate the pill, row action, detail link, and branch-copy controls into one accessible keyboard flow.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use existing relative-time, title, spacing, and popup patterns consistently across standalone and collection references. Bound long titles, keep transient content concise, and make HTML hover padding ownership explicit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the existing 8px SessionSummaryHover rhythm between the title and description in both standalone and collection cards.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Let the card root own a uniform 8px gap between metadata, title, description, and branch rows instead of splitting relationship spacing across child padding.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Follow GitHub hover cards for provenance, title and ID, state, context, routing, and author order while preserving VS Code styling and the bounded transient content budget.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Group the final visible title word with the linked reference ID, bound pathological titles safely, and allow narrow cards to wrap without clipping focusable content.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use measured submenu height for positioning and reveal the full bounded GitHub title when keyboard focus reaches its linked reference.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Render shared hover actions as centered inline flex rows so codicons and text use the same vertical center.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- actionList: Shift+Tab from a hover panel now returns to the last
  non-removal toolbar action instead of a trailing Remove control,
  covered by a new multi-action regression test.
- pullRequestHover: stop branch-pill clicks from bubbling to the
  ActionList row so copying a branch no longer clears list focus.
- chatView: extract the Shift+Tab-to-pills predicate into a testable
  helper and add regression tests for modifier filtering and
  preventDefault/stopPropagation cancellation; align the accessibility
  help text with the Shift+Tab shortcut.
- githubPRFetcher: cover the closed_at -> closedAt mapping with a
  dedicated fixture and assertion.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Surface the shared overall checks state alongside PR lifecycle metadata, including draft pull requests, while keeping no-check and completed PR cards quiet. Preserve the same status in single-pill and collection-row accessibility descriptions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the familiar static pending dot and aggregate 'Checks pending' label rather than a sync metaphor that implies active execution or refresh.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Traverse rich-hover controls and row actions symmetrically with Shift+Tab, and preserve GitHub's distinct Duplicate issue terminology.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants