Skip to content

Editor: Refine connected tabs UI - #337126

Merged
Cherry Wang (chryw) merged 30 commits into
mainfrom
dev/cherwan/agents/connected-tabs-ui-refinement
Sep 23, 2026
Merged

Cherry Wang (chryw) merged 30 commits into
mainfrom
dev/cherwan/agents/connected-tabs-ui-refinement

Conversation

@chryw

@chryw Cherry Wang (chryw) commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Connected editor tabs and the editor surface should read as one document well. Today the seam between them breaks down: wrapped rows leave gutters, selection shifts tab geometry, the strip repaints the whole theme's tab palette, and close targets move as a tab is selected, hovered, or focused. This PR refines that boundary so the tab strip, editor frame, and close affordances stay visually and physically stable.

Classic tabs, the pill tab style, and the Agents window are unchanged.

Refs #336320. Consolidates the close-spacing work from #336791.

Changes

Theming — the strip no longer repaints the whole palette

  • Adds editorGroupHeader.connectedTabsBackground (defaults to editorGroupHeader.tabsBackground), so connected strips get their own restrained neutral fill without rewriting each theme's global editorGroupHeader.tabsBackground and tab.inactiveBackground. Classic tabs keep their original colors.
  • The outside stroke, shoulders, and strip separator now use editorGroupHeader.tabsBorder (falling back to tab.border) instead of editor.background, so the seam is a real border rather than a coincidence of matching fills.
  • Inactive labels use tab.inactiveForeground instead of dimming foreground to 50%, keeping at least 4.5:1 contrast, including in inactive editor groups.

Frame — one continuous boundary instead of stacked edges

  • First tabs and wrapped-row starts drop their own left stroke and outside shoulder; the editor frame paints that edge once.
  • An active tab on the outermost row reuses the editor frame's top stroke rather than drawing a second line beside it.
  • In high-contrast themes, a single rounded editor-group frame encloses the title and editor surface on all four sides, including breadcrumbs.
  • Free corners stay rounded; only corners adjoining the frame are squared.

Layout — geometry stops depending on selection

  • Wrapped rows lose their horizontal gutters, so painted row surfaces meet edge to edge; spacing remains only between rows.
  • Selecting a tab no longer changes its width or margin, and row classification no longer triggers a second fit-tab reflow.
  • Shoulder space is reserved only after the final tab; intermediate shoulders paint over adjacent surfaces instead of inserting a gap.

Close targets — stable across every state

  • Close-action clearance is derived from tab height and row gutters rather than the shoulder radius, and is reserved on inactive tabs too, so selecting a tab never moves its close target.
  • The 20px hover target keeps even inset spacing on all sides and stays clear of the terminal shoulder in wrapped rows, single rows, and separate pinned rows.
  • High-contrast hover and focus indicators belong to the close target itself, not to a second border around its container. Disabled Close Others (Alt) no longer shifts the target.

Structure

  • The connected root marker now lives with the editor control constants and is shared by editor layout, the Modern UI contribution, and theming.
  • connectedEditorTabs.css owns marker-gated geometry; connectedEditorTabs.ts owns marker-gated theme derivations. Core editor-tab code keeps only what CSS cannot express: row classification, label compression, shoulder-aware reveal, and viewport clipping.

How to test

  1. Run Code OSS and set "workbench.experimental.modernUI": true (modernUIEditorTabStyle defaults to connected).
  2. Open about eight editors and narrow the window until tabs wrap onto two rows. Confirm rows meet without horizontal gutters and no gutter appears below the last row.
  3. Select tabs on both rows. The selected tab must not change width or shift its neighbours, and its close button must not move.
  4. Hover a clean inactive tab, then Tab into its close action. The hover or focus indicator should sit on the close target with even inset spacing.
  5. Hold Alt to turn the close action into a disabled Close Others action; the target must stay in place.
  6. Switch to Dark High Contrast and Light High Contrast. The editor group should have one continuous rounded frame, with tabs sharing its strokes rather than doubling them.
  7. Turn Modern UI off and confirm Classic tabs are visually unchanged.

Screenshots

The automated screenshot report is the primary visual evidence for this PR. It compares the base and current implementations across all bundled themes and fixture states.

When reviewing the report, focus on:

  • connected versus Classic tab colors, especially inactive labels and editor-group backgrounds;
  • single-row, wrapped-row, and separate pinned-row geometry;
  • shared frame edges, shoulders, and corner treatment in default and high-contrast themes;
  • close-action position and indicators across inactive, selected, hover, focus, and disabled states.

Validation

  • Targeted unit tests cover row geometry, viewport clipping, connected-theme derivation, and high-contrast frame behavior.
  • Component fixtures cover default and compact density, single and wrapped rows, separate pinned rows, action placement, and bundled themes.
  • A Playwright fixture test asserts that close-target position remains stable across selection, hover, and focus.
  • Client compilation, ESLint, Stylelint, and hygiene checks pass.

Cherry Wang (chryw) and others added 2 commits September 21, 2026 12:23
Let bottom-row connected tabs own the strip geometry directly instead of cancelling inherited pill gutters with negative offsets. This keeps their cap and document boundary aligned when Chromium rounds fractional zoom values while preserving upper-row pill spacing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update the editor-tab layout expectations for direct bottom-row geometry and the intentional one-stroke overlap with the document surface.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings September 21, 2026 19:27

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.

Copilot review overview

🟢 Approval recommended

The scoped CSS changes match the stated geometry model and are covered by targeted regression tests.

Review effort: Balanced
Findings: None

What changed in this PR

Stabilizes connected-tab geometry across fractional zoom levels by removing compensating pill gutters from document-connected rows.

Changes:

  • Makes lower rows directly occupy the tab strip.
  • Preserves pill geometry for upper wrapped and pinned rows.
  • Updates geometry regression coverage.
File Description
connectedEditorTabs.css Revises connected-row geometry.
modernUI.contribution.test.ts Adds CSS geometry coverage.
multiEditorTabsControl.test.ts Updates layout expectations.

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

@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Screenshot Changes

Base: b2a29a84 Current: 290632c1

The screenshot report exceeds GitHub's comment size limit. View the full report in the workflow summary.

Cherry Wang (chryw) and others added 4 commits September 21, 2026 12:52
Top-align the non-wrapping connected strip and give editor actions the same full row height so their controls remain vertically centered with tab labels.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Accept the Ubuntu CI hash for the dark responsive model resize fixture after verifying the delta is limited to corner antialiasing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Own the non-wrapping row-height formula in the shared Modern UI tab layout so connected editor actions cannot drift from tab density changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore the original dark responsive model resize hash after CI oscillated back, confirming the alternate corner-antialias hash was nondeterministic.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Give connected document tabs their own strip color, restore shared 2026 tab colors for Classic and Agents surfaces, and use the existing strip separator color for connected cap and shoulder outlines.

Refs #336320

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@chryw Cherry Wang (chryw) changed the title Editor: Stabilize connected tabs across zoom levels Editor: Refine connected tabs UI Sep 21, 2026
Cherry Wang (chryw) and others added 8 commits September 21, 2026 14:46
Overlap first and wrapped-row-start connected fills by one stroke so their left edge reuses the editor body border instead of drawing an adjacent double border.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use a single editorGroupHeader.connectedTabsBackground token and emit its derived styles only under the connected-tabs root marker.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Document editorGroupHeader.connectedTabsBackground by visual role rather than feature enablement so it remains suitable for any connected tab treatment.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Share the connected-tab root marker across editor controls, contribution setup, and theming, and document the dedicated stylesheet scoping invariant.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Document the reusable connected header color, border ownership, marker lifecycle, and separation between CSS geometry and editor control behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use flex stretch and the existing separator stroke so connected editor actions follow default and compact row heights without a special row-height variable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move every strip background introduced by #335605 to editorGroupHeader.connectedTabsBackground while preserving the original shared tab backgrounds and independent foreground contrast fixes.

Refs #336320

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reserve upper-row pill insets consistently in tab width and close-action positioning, with single, terminal, wrapped, and left-action regression coverage.

Consolidates #336791

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cherry Wang (chryw) and others added 8 commits September 21, 2026 15:48
Restore the terminal close-action shoulder reservation from the consolidated fix and remove the generic wrapped-row top inset so connected strips meet the header edge directly.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Let the external shoulder reservation own terminal geometry so close actions keep the same visible inset as ordinary and wrapped tabs. Add a regression assertion for balanced label- and edge-side action spacing.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Classify the outermost connected tab row explicitly so active tabs can reuse the editor frame's top stroke. First-position active tabs also reuse the left stroke, while inner wrapped rows retain pill gutters and balanced close actions.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Avoid overlapping the connected tab and editor frame strokes. The outermost tab now starts at the frame's inner edge with transparent top and left borders, allowing the editor frame and its clipping radius to be the sole painter at every zoom level.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Center the close glyph in its painted action surface and shift that surface outward by the same inset so label- and shoulder-side spacing remain balanced. Preserve sole editor-frame ownership of the outer border.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Preserve high contrast outlines where the outer editor frame is transparent. Account for both cap radii when hiding clipped tab slivers, and update stale assertions for centered actions and editor-owned first-tab borders.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Share action clearance across row densities and label reservation, accounting for painted borders instead of shoulder width. Keep standard row starts on the editor frame and join top-row side strokes directly to its shared top edge.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Let the selected tab fill own its surface instead of painting a second opaque action-container background over the trailing cap stroke. Preserve the close target's own hover and keyboard focus treatment.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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.

Copilot review overview

🟡 Changes recommended

The new high-contrast hover rule incorrectly gives disabled tab actions an actionable outline.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)

Comment thread src/vs/workbench/contrib/modernUI/browser/media/connectedEditorTabs.css Outdated
Exclude disabled actions without raising hover specificity over keyboard focus. Cover the real Alt-to-Close-Others transition in both high-contrast themes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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.

Copilot review overview

🔵 Needs a closer look

Broad visual geometry changes still have acknowledged native zoom, pane-seam, and Agents isolation validation gaps.

Review effort: Balanced
Findings: None

Resolved since last review (1)

Share the HC editor-group frame without changing close-target geometry, keep shared strip theming separate from the Modern UI editor palette, and update regression coverage and documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@chryw
Cherry Wang (chryw) marked this pull request as ready for review September 23, 2026 17:36
@chryw
Cherry Wang (chryw) requested a balanced review from Copilot September 23, 2026 17:36
@vs-code-engineering

Copy link
Copy Markdown
Contributor

📬 CODENOTIFY

The following users are being notified based on files changed in this PR:

Benjamin Christopher Simmonds (@benibenj)

Matched files:

  • src/vs/workbench/browser/parts/editor/editor.ts
  • src/vs/workbench/browser/parts/editor/editorTabsControl.ts
  • src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts

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.

Copilot review overview

🔵 Needs a closer look

The broad visual and theme-sensitive changes still have acknowledged native zoom, pane-seam, and Agents-window validation gaps.

Review effort: Balanced
Findings: None

All four browser and Electron CI failures asserted black for an absent frame whose unused border color inherits currentColor. Assert the color only for the rendered HC frame, retaining geometry and frame-presence coverage. Seed a non-black foreground so focused runs reproduce the full-suite inheritance.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@chryw
Cherry Wang (chryw) enabled auto-merge (squash) September 23, 2026 18:34
@chryw
Cherry Wang (chryw) merged commit ab8f31f into main Sep 23, 2026
53 of 55 checks passed
@chryw
Cherry Wang (chryw) deleted the dev/cherwan/agents/connected-tabs-ui-refinement branch September 23, 2026 18:52
@vs-code-engineering vs-code-engineering Bot added this to the 1.140.0 milestone Sep 23, 2026
Comment thread src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts
@chryw

Copy link
Copy Markdown
Contributor Author

also fixes #337480 by using a dedicated token for connected tab strip background so the style doesn't leak into legacy style.

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.

8 participants