fix performance regression caused by modern UI styles#325985
Conversation
📬 CODENOTIFYThe following users are being notified based on files changed in this PR: @benibenjMatched files:
|
There was a problem hiding this comment.
Pull request overview
Replaces an expensive Explorer-wide :has() selector while preserving title casing.
Changes:
- Exposes the active pane composite ID as a DOM data attribute.
- Uses that attribute to target Explorer titles efficiently.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
paneCompositePart.ts |
Maintains the active composite data attribute. |
fontRamp.css |
Replaces the costly selector with an attribute selector. |
mrleemurray
left a comment
There was a problem hiding this comment.
Reviewed the approach and verified both the specificity math and the DOM wiring — this is a sound, minimal, behavior-preserving fix. Approving in spirit; a couple of optional notes below.
Correctness
this.elementinAbstractPaneCompositePartis the part container that receives the.partclass (part.classList.add('part', ...)inworkbench.ts), sodataset.activeComposite→data-active-compositelands exactly on the.part:not(.editor)[...]element the selector targets. ✔- The set/delete pair is symmetric under the existing
activePaneContextKey.get() === idguard, and each part instance manages its own element, so there's no cross-part interference. ✔
Specificity is preserved — the subtle bit the original :has() comment flagged. The rule must out-specify the shared capitalize ramp rule (… .part:not(.editor) > .title > .title-label h2, specificity (0,6,1)):
- Old
:has()selector:(0,9,1) - New attribute selector:
(0,7,1)— the[data-active-composite="…"]still contributes a class-level weight
(0,7,1) beats (0,6,1), and text-transform: none also comes later in source order, so the Explorer title-casing behavior is fully maintained. ✔
Optional note: the attribute is written for every composite (search, scm, etc.) while the CSS only keys on the explorer value — that's fine and keeps the attribute reusable.
| */ | ||
| .style-override.monaco-workbench .part:not(.editor):has(> .content > .composite.explorer-viewlet) > .title > .title-label h2, | ||
| .style-override.monaco-workbench .part:not(.editor)[data-active-composite="workbench.view.explorer"] > .title > .title-label h2, | ||
| .style-override .monaco-pane-view .pane > .pane-header:has(> .icon.codicon-explorer-view-icon) > .title { |
There was a problem hiding this comment.
This sibling :has() selector is left unchanged. It's far cheaper than the removed one (scoped to .pane-header elements rather than re-evaluating on every workbench subtree mutation), so leaving it is reasonable. Since the linked issue title is generic ("Modern UI can impact UI performance"), could you add a one-line note in the PR description that this pane-view variant was intentionally kept? Optional, non-blocking.
Fixes #325984
This issue is caused by the performance overhead of the
:has()selector and is similar to the issue discussed in #324986 .The regression was introduced by #325013 , which added these selectors for the modern UI styles.
Additional note: The
:has()selector on.pane-headeris intentionally left unchanged. Compared with the removed selector, it has a much narrower scope and does not cause the same level of style invalidation overhead, so keeping it should be reasonable.For more details about the
:has()pseudo-class, refer to the MDN documentation.