Skip to content

Commit 4a1bcda

Browse files
authored
Migrate fixed dom context views into Shadow DOM (microsoft#102401)
* initial * clean up css * clean up contextview css * cleanup
1 parent 09904a6 commit 4a1bcda

13 files changed

Lines changed: 500 additions & 248 deletions

File tree

src/vs/base/browser/contextmenu.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ export interface IContextMenuDelegate {
3434
actionRunner?: IActionRunner;
3535
autoSelectFirstItem?: boolean;
3636
anchorAlignment?: AnchorAlignment;
37-
anchorAsContainer?: boolean;
37+
domForShadowRoot?: HTMLElement;
3838
}

src/vs/base/browser/ui/codicons/codiconStyles.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function initialize() {
2828
delayer.schedule();
2929
}
3030

31-
function formatRule(c: Codicon) {
31+
export function formatRule(c: Codicon) {
3232
let def = c.definition;
3333
while (def instanceof Codicon) {
3434
def = def.definition;

src/vs/base/browser/ui/contextview/contextview.ts

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ import { IDisposable, toDisposable, Disposable, DisposableStore } from 'vs/base/
1010
import { Range } from 'vs/base/common/range';
1111
import { BrowserFeatures } from 'vs/base/browser/canIUse';
1212

13+
export const enum ContextViewDOMPosition {
14+
ABSOLUTE = 1,
15+
FIXED,
16+
FIXED_SHADOW
17+
}
18+
1319
export interface IAnchor {
1420
x: number;
1521
y: number;
@@ -105,32 +111,62 @@ export class ContextView extends Disposable {
105111
private container: HTMLElement | null = null;
106112
private view: HTMLElement;
107113
private useFixedPosition: boolean;
114+
private useShadowDOM: boolean;
108115
private delegate: IDelegate | null = null;
109116
private toDisposeOnClean: IDisposable = Disposable.None;
110117
private toDisposeOnSetContainer: IDisposable = Disposable.None;
118+
private shadowRoot: ShadowRoot | null = null;
119+
private shadowRootHostElement: HTMLElement | null = null;
111120

112-
constructor(container: HTMLElement, useFixedPosition: boolean) {
121+
constructor(container: HTMLElement, domPosition: ContextViewDOMPosition) {
113122
super();
114123

115124
this.view = DOM.$('.context-view');
116125
this.useFixedPosition = false;
126+
this.useShadowDOM = false;
117127

118128
DOM.hide(this.view);
119129

120-
this.setContainer(container, useFixedPosition);
130+
this.setContainer(container, domPosition);
121131

122-
this._register(toDisposable(() => this.setContainer(null, false)));
132+
this._register(toDisposable(() => this.setContainer(null, ContextViewDOMPosition.ABSOLUTE)));
123133
}
124134

125-
setContainer(container: HTMLElement | null, useFixedPosition: boolean): void {
135+
setContainer(container: HTMLElement | null, domPosition: ContextViewDOMPosition): void {
126136
if (this.container) {
127137
this.toDisposeOnSetContainer.dispose();
128-
this.container.removeChild(this.view);
138+
139+
if (this.shadowRoot) {
140+
this.shadowRoot.removeChild(this.view);
141+
this.shadowRoot = null;
142+
DOM.removeNode(this.shadowRootHostElement!);
143+
this.shadowRootHostElement = null;
144+
} else {
145+
this.container.removeChild(this.view);
146+
}
147+
129148
this.container = null;
130149
}
131150
if (container) {
132151
this.container = container;
133-
this.container.appendChild(this.view);
152+
153+
this.useFixedPosition = domPosition !== ContextViewDOMPosition.ABSOLUTE;
154+
this.useShadowDOM = domPosition === ContextViewDOMPosition.FIXED_SHADOW;
155+
156+
if (this.useShadowDOM) {
157+
this.shadowRootHostElement = DOM.$('.shadow-root-host');
158+
this.container.appendChild(this.shadowRootHostElement);
159+
this.shadowRoot = this.shadowRootHostElement.attachShadow({ mode: 'closed' });
160+
this.shadowRoot.innerHTML = `
161+
<style>
162+
${SHADOW_ROOT_CSS}
163+
</style>
164+
`;
165+
this.shadowRoot.appendChild(this.view);
166+
this.shadowRoot.appendChild(DOM.$('slot'));
167+
} else {
168+
this.container.appendChild(this.view);
169+
}
134170

135171
const toDisposeOnSetContainer = new DisposableStore();
136172

@@ -148,8 +184,6 @@ export class ContextView extends Disposable {
148184

149185
this.toDisposeOnSetContainer = toDisposeOnSetContainer;
150186
}
151-
152-
this.useFixedPosition = useFixedPosition;
153187
}
154188

155189
show(delegate: IDelegate): void {
@@ -162,6 +196,7 @@ export class ContextView extends Disposable {
162196
this.view.className = 'context-view';
163197
this.view.style.top = '0px';
164198
this.view.style.left = '0px';
199+
this.view.style.zIndex = '2500';
165200
this.view.style.position = this.useFixedPosition ? 'fixed' : 'absolute';
166201
DOM.show(this.view);
167202

@@ -300,3 +335,45 @@ export class ContextView extends Disposable {
300335
super.dispose();
301336
}
302337
}
338+
339+
let SHADOW_ROOT_CSS = /* css */ `
340+
:host {
341+
all: initial; /* 1st rule so subsequent properties are reset. */
342+
}
343+
344+
@font-face {
345+
font-family: "codicon";
346+
src: url("./codicon.ttf?5d4d76ab2ce5108968ad644d591a16a6") format("truetype");
347+
}
348+
349+
.codicon[class*='codicon-'] {
350+
font: normal normal normal 16px/1 codicon;
351+
display: inline-block;
352+
text-decoration: none;
353+
text-rendering: auto;
354+
text-align: center;
355+
-webkit-font-smoothing: antialiased;
356+
-moz-osx-font-smoothing: grayscale;
357+
user-select: none;
358+
-webkit-user-select: none;
359+
-ms-user-select: none;
360+
}
361+
362+
:host-context(.mac) { font-family: -apple-system, BlinkMacSystemFont, sans-serif; }
363+
:host-context(.mac:lang(zh-Hans)) { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; }
364+
:host-context(.mac:lang(zh-Hant)) { font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; }
365+
:host-context(.mac:lang(ja)) { font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; }
366+
:host-context(.mac:lang(ko)) { font-family: -apple-system, BlinkMacSystemFont, "Nanum Gothic", "Apple SD Gothic Neo", "AppleGothic", sans-serif; }
367+
368+
:host-context(.windows) { font-family: "Segoe WPC", "Segoe UI", sans-serif; }
369+
:host-context(.windows:lang(zh-Hans)) { font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; }
370+
:host-context(.windows:lang(zh-Hant)) { font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; }
371+
:host-context(.windows:lang(ja)) { font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; }
372+
:host-context(.windows:lang(ko)) { font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; }
373+
374+
:host-context(.mac).linux) { font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; }
375+
:host-context(.mac).linux:lang(zh-Hans)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; }
376+
:host-context(.mac).linux:lang(zh-Hant)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif; }
377+
:host-context(.mac).linux:lang(ja)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; }
378+
:host-context(.mac).linux:lang(ko)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; }
379+
`;

src/vs/base/browser/ui/dropdown/dropdown.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ export class DropdownMenu extends BaseDropdown {
270270
onHide: () => this.onHide(),
271271
actionRunner: this.menuOptions ? this.menuOptions.actionRunner : undefined,
272272
anchorAlignment: this.menuOptions ? this.menuOptions.anchorAlignment : AnchorAlignment.LEFT,
273-
anchorAsContainer: this.menuAsChild
273+
domForShadowRoot: this.menuAsChild ? this.element : undefined
274274
});
275275
}
276276

src/vs/base/browser/ui/menu/menu.css

Lines changed: 0 additions & 225 deletions
This file was deleted.

0 commit comments

Comments
 (0)