microsoft/vscode · #336340
sessions: keep Codicon confetti behind conversations
src/vs/sessions/contrib/chat/test/browser/chatView.test.ts127 + / 46 −
@@ -620,6 +620,7 @@ suite('Sessions - Chat View', () => { test('makes one random codicon an accessible confetti button', () => { const workbench = dom.$('.monaco-workbench.agent-sessions-workbench');+ workbench.style.setProperty('--vscode-spacing-size240', '24px'); const part = dom.append(workbench, dom.$('.part.sessionspart')); dom.getWindow(workbench).document.body.appendChild(workbench); disposables.add(toDisposable(() => workbench.remove()));@@ -639,12 +640,18 @@ suite('Sessions - Chat View', () => { top: cell.style.top, iconTransform: cell.querySelector<HTMLElement>('.codicon')?.style.transform, }));- const initialButton = layer?.querySelector<HTMLElement>('.sessions-chat-codicon-button');+ const initialButton = part.querySelector<HTMLElement>(':scope > .sessions-chat-codicon-hit-target');+ const initialCell = cellsBefore.find(cell => cell.style.left === initialButton?.style.left && cell.style.top === initialButton?.style.top); const buttonStyle = initialButton ? dom.getWindow(initialButton).getComputedStyle(initialButton) : undefined;+ const backgroundStyle = backgroundLayer ? dom.getWindow(backgroundLayer).getComputedStyle(backgroundLayer) : undefined;+ const initialButtonPosition = `${initialButton?.style.left}:${initialButton?.style.top}`; initialButton?.focus(); initialButton?.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key: 'Enter', keyCode: 13 })); const cellsAfter = layer ? [...layer.querySelectorAll<HTMLElement>('.sessions-chat-codicon-cell')] : [];- const nextButton = layer?.querySelector<HTMLElement>('.sessions-chat-codicon-button');+ const nextButton = part.querySelector<HTMLElement>(':scope > .sessions-chat-codicon-hit-target');+ const activeCells = cellsAfter.filter(cell => cell.classList.contains('sessions-chat-codicon-button-active'));+ const focusedButtonStyle = nextButton ? dom.getWindow(nextButton).getComputedStyle(nextButton) : undefined;+ const activationParent = activationTarget?.parentElement; const layoutAfter = cellsAfter.map(cell => ({ left: cell.style.left, top: cell.style.top,@@ -654,52 +661,61 @@ suite('Sessions - Chat View', () => { assert.deepStrictEqual({ backgroundAriaHidden: backgroundLayer?.ariaHidden, layerAriaHidden: layer?.ariaHidden,- buttonCount: layer?.querySelectorAll('.sessions-chat-codicon-button').length,+ buttonCount: part.querySelectorAll(':scope > .sessions-chat-codicon-hit-target').length,+ buttonIsOutsideBackground: !backgroundLayer?.contains(nextButton ?? null),+ buttonPrecedesBackground: initialButton?.nextElementSibling === backgroundLayer,+ buttonChildCount: nextButton?.childElementCount, role: nextButton?.getAttribute('role'), tabIndex: nextButton?.tabIndex, ariaLabel: nextButton?.getAttribute('aria-label'),- iconAriaHidden: nextButton?.querySelector<HTMLElement>('.codicon')?.ariaHidden,- display: buttonStyle?.display,- placeItems: buttonStyle?.placeItems,+ buttonOpacity: buttonStyle?.opacity,+ buttonZIndex: buttonStyle?.zIndex,+ backgroundZIndex: backgroundStyle?.zIndex,+ visualCellSize: { width: initialCell?.offsetWidth, height: initialCell?.offsetHeight },+ activeCellCount: activeCells.length,+ activeCellMatchesButton: activeCells[0]?.style.left === nextButton?.style.left && activeCells[0]?.style.top === nextButton?.style.top,+ iconsAriaHidden: cellsAfter.every(cell => cell.ariaHidden === 'true' && cell.querySelector<HTMLElement>('.codicon')?.ariaHidden === 'true'), activationTarget: activationTarget?.className,- activationTargetRetained: activationTarget?.parentElement === initialButton,+ activationTargetRetained: activationParent ? cellsBefore.includes(activationParent) : false, activations,- targetChanged: nextButton !== initialButton,+ buttonReused: nextButton === initialButton,+ targetPositionChanged: `${nextButton?.style.left}:${nextButton?.style.top}` !== initialButtonPosition, focusTransferred: dom.getWindow(part).document.activeElement === nextButton,+ focusedButtonOpacity: focusedButtonStyle?.opacity, cellElementsRetained: cellsAfter.length === cellsBefore.length && cellsAfter.every((cell, index) => cell === cellsBefore[index]), layoutStable: layoutAfter,- initialButtonAfterActivation: {- ariaHidden: initialButton?.ariaHidden,- role: initialButton?.getAttribute('role'),- tabIndex: initialButton?.tabIndex,- }, }, {- backgroundAriaHidden: null,- layerAriaHidden: null,+ backgroundAriaHidden: 'true',+ layerAriaHidden: 'true', buttonCount: 1,+ buttonIsOutsideBackground: true,+ buttonPrecedesBackground: true,+ buttonChildCount: 0, role: 'button', tabIndex: 0, ariaLabel: 'Celebrate',- iconAriaHidden: 'true',- display: 'grid',- placeItems: 'center',+ buttonOpacity: '0',+ buttonZIndex: '3',+ backgroundZIndex: '0',+ visualCellSize: { width: 24, height: 24 },+ activeCellCount: 1,+ activeCellMatchesButton: true,+ iconsAriaHidden: true, activationTarget: 'sessions-chat-codicon-button-animation', activationTargetRetained: true, activations: 1,- targetChanged: true,+ buttonReused: true,+ targetPositionChanged: true, focusTransferred: true,+ focusedButtonOpacity: '0', cellElementsRetained: true, layoutStable: layoutBefore,- initialButtonAfterActivation: {- ariaHidden: 'true',- role: null,- tabIndex: -1,- }, }); }); - test('keeps the confetti button fully inside the viewport', async () => {+ test('keeps the confetti button fully inside the viewport and clear of conversation content', async () => { const workbench = dom.$('.monaco-workbench.agent-sessions-workbench');+ workbench.style.setProperty('--vscode-spacing-size240', '24px'); const part = dom.append(workbench, dom.$('.part.sessionspart')); part.style.width = '850px'; part.style.height = '641px';@@ -723,28 +739,19 @@ suite('Sessions - Chat View', () => { const renderer = disposables.add(new SessionsChatBackgroundRenderer(part, true, () => 0.999)); renderer.setBackground({ kind: 'codicons' }); const layer = part.querySelector<HTMLElement>(':scope > .sessions-chat-background > .sessions-chat-codicon-background');- const initialButton = layer?.querySelector<HTMLElement>('.sessions-chat-codicon-button');+ const initialButton = part.querySelector<HTMLElement>(':scope > .sessions-chat-codicon-hit-target');+ const initialButtonPosition = `${initialButton?.style.left}:${initialButton?.style.top}`; const initialViewport = { width: part.clientWidth, height: part.clientHeight }; const initialCells = layer ? [...layer.querySelectorAll<HTMLElement>('.sessions-chat-codicon-cell')] : [];- const overlaps = (button: HTMLElement | null | undefined, left: number, width: number) => {+ const overlapsBounds = (button: HTMLElement | null | undefined, left: number, top: number, width: number, height: number) => { const centerX = Number.parseFloat(button?.style.left ?? ''); const centerY = Number.parseFloat(button?.style.top ?? ''); const horizontalRadius = (button?.offsetWidth ?? 0) / 2; const verticalRadius = (button?.offsetHeight ?? 0) / 2; return centerX - horizontalRadius < left + width && centerX + horizontalRadius > left- && centerY - verticalRadius < 641 && centerY + verticalRadius > 0;+ && centerY - verticalRadius < top + height && centerY + verticalRadius > top; };- const initialButtonOverlapsOccluder = overlaps(initialButton, occluderLeft, occluderWidth);- const hasOccludedCells = initialCells.some(cell => overlaps(cell, occluderLeft, occluderWidth));-- occluderLeft = 0;- occluderWidth = 400;- occluder.style.left = '0';- occluder.style.width = '400px';- await timeout(20);- const refreshedButton = layer?.querySelector<HTMLElement>('.sessions-chat-codicon-button');- refreshedButton?.click();- const nextButton = layer?.querySelector<HTMLElement>('.sessions-chat-codicon-button');+ const overlaps = (button: HTMLElement | null | undefined, left: number, width: number) => overlapsBounds(button, left, 0, width, 641); const isFullyVisible = (button: HTMLElement | null | undefined, viewport: { width: number; height: number }) => { const centerX = Number.parseFloat(button?.style.left ?? ''); const centerY = Number.parseFloat(button?.style.top ?? '');@@ -755,31 +762,105 @@ suite('Sessions - Chat View', () => { && centerY - verticalRadius >= 0 && centerY + verticalRadius <= viewport.height; };+ const initialButtonFullyVisible = isFullyVisible(initialButton, initialViewport);+ const initialButtonOverlapsOccluder = overlaps(initialButton, occluderLeft, occluderWidth);+ const hasOccludedCells = initialCells.some(cell => overlaps(cell, occluderLeft, occluderWidth));++ occluderLeft = 0;+ occluderWidth = 400;+ occluder.style.left = '0';+ occluder.style.width = '400px';+ await timeout(20);+ const refreshedButton = part.querySelector<HTMLElement>(':scope > .sessions-chat-codicon-hit-target');+ const refreshedButtonPosition = `${refreshedButton?.style.left}:${refreshedButton?.style.top}`;+ const refreshedButtonFullyVisible = isFullyVisible(refreshedButton, initialViewport);+ const refreshedButtonOverlapsOccluder = overlaps(refreshedButton, occluderLeft, occluderWidth);+ refreshedButton?.click();+ const nextButton = part.querySelector<HTMLElement>(':scope > .sessions-chat-codicon-hit-target');+ const nextButtonPosition = `${nextButton?.style.left}:${nextButton?.style.top}`;+ const nextButtonFullyVisible = isFullyVisible(nextButton, initialViewport);+ const nextButtonOverlapsOccluder = overlaps(nextButton, occluderLeft, occluderWidth);+ const dynamicOccluderRelocations = [];+ for (const selector of ['.interactive-item-container.interactive-response', '.scrollbar', '.monaco-sash']) {+ const currentButton = part.querySelector<HTMLElement>(':scope > .sessions-chat-codicon-hit-target');+ const currentButtonPosition = `${currentButton?.style.left}:${currentButton?.style.top}`;+ const left = Number.parseFloat(currentButton?.style.left ?? '') - 12;+ const top = Number.parseFloat(currentButton?.style.top ?? '') - 12;+ const dynamicOccluder = dom.append(part, dom.$(selector));+ dynamicOccluder.style.position = 'absolute';+ dynamicOccluder.style.left = `${left}px`;+ dynamicOccluder.style.top = `${top}px`;+ dynamicOccluder.style.width = '24px';+ dynamicOccluder.style.height = '24px';+ dynamicOccluder.getBoundingClientRect = () => DOMRect.fromRect({+ x: partBounds.left + left,+ y: partBounds.top + top,+ width: 24,+ height: 24,+ });+ await timeout(20);+ const relocatedButton = part.querySelector<HTMLElement>(':scope > .sessions-chat-codicon-hit-target');+ dynamicOccluderRelocations.push({+ className: dynamicOccluder.className,+ buttonReused: relocatedButton === currentButton,+ targetChanged: `${relocatedButton?.style.left}:${relocatedButton?.style.top}` !== currentButtonPosition,+ buttonFullyVisible: isFullyVisible(relocatedButton, initialViewport),+ buttonOverlapsOccluder: overlapsBounds(relocatedButton, left, top, 24, 24),+ });+ } const cells = layer ? [...layer.querySelectorAll<HTMLElement>('.sessions-chat-codicon-cell')] : []; const refreshedViewport = { width: part.clientWidth, height: part.clientHeight }; assert.deepStrictEqual({ initialButtonSize: { width: initialButton?.offsetWidth, height: initialButton?.offsetHeight },- initialButtonFullyVisible: isFullyVisible(initialButton, initialViewport),+ initialButtonFullyVisible, initialButtonOverlapsOccluder,- targetChangedAfterOccluderMove: refreshedButton !== initialButton,- refreshedButtonFullyVisible: isFullyVisible(refreshedButton, refreshedViewport),- refreshedButtonOverlapsOccluder: overlaps(refreshedButton, occluderLeft, occluderWidth),- targetChangedAfterActivation: nextButton !== refreshedButton,- nextButtonFullyVisible: isFullyVisible(nextButton, refreshedViewport),- nextButtonOverlapsOccluder: overlaps(nextButton, occluderLeft, occluderWidth),+ buttonReusedAfterOccluderMove: refreshedButton === initialButton,+ targetChangedAfterOccluderMove: refreshedButtonPosition !== initialButtonPosition,+ refreshedButtonFullyVisible,+ refreshedButtonOverlapsOccluder,+ buttonReusedAfterActivation: nextButton === refreshedButton,+ targetChangedAfterActivation: nextButtonPosition !== refreshedButtonPosition,+ nextButtonFullyVisible,+ nextButtonOverlapsOccluder,+ dynamicOccluderRelocations, hasClippedCells: cells.some(cell => !isFullyVisible(cell, refreshedViewport)), hasOccludedCells, }, { initialButtonSize: { width: 24, height: 24 }, initialButtonFullyVisible: true, initialButtonOverlapsOccluder: false,+ buttonReusedAfterOccluderMove: true, targetChangedAfterOccluderMove: true, refreshedButtonFullyVisible: true, refreshedButtonOverlapsOccluder: false,+ buttonReusedAfterActivation: true, targetChangedAfterActivation: true, nextButtonFullyVisible: true, nextButtonOverlapsOccluder: false,+ dynamicOccluderRelocations: [+ {+ className: 'interactive-item-container interactive-response',+ buttonReused: true,+ targetChanged: true,+ buttonFullyVisible: true,+ buttonOverlapsOccluder: false,+ },+ {+ className: 'scrollbar',+ buttonReused: true,+ targetChanged: true,+ buttonFullyVisible: true,+ buttonOverlapsOccluder: false,+ },+ {+ className: 'monaco-sash',+ buttonReused: true,+ targetChanged: true,+ buttonFullyVisible: true,+ buttonOverlapsOccluder: false,+ },+ ], hasClippedCells: true, hasOccludedCells: true, });src/vs/sessions/services/chatBackground/browser/chatBackgroundRenderer.ts75 + / 63 −
@@ -18,7 +18,14 @@ import { ISessionsChatBackground } from './chatBackgroundService.js'; const codiconCellSize = 80; const codiconButtonSize = 24; const codiconDefaults = { width: 960, height: 800 };-const codiconButtonOccluderClasses = ['new-chat-input-container', 'new-chat-bottom-container', 'interactive-input-part'];+const codiconButtonOccluderClasses = [+ 'interactive-item-container',+ 'monaco-sash',+ 'new-chat-input-container',+ 'new-chat-bottom-container',+ 'interactive-input-part',+ 'scrollbar',+]; const codiconButtonOccluderTags = new Set(['A', 'BUTTON', 'INPUT', 'SELECT', 'SUMMARY', 'TEXTAREA']); const codiconButtonOccluderRoles = new Set(['button', 'checkbox', 'combobox', 'link', 'menuitem', 'option', 'radio', 'slider', 'spinbutton', 'switch', 'tab', 'textbox', 'treeitem']); const codiconChoices = [@@ -103,7 +110,9 @@ function isCodiconButtonOccluder(element: HTMLElement): boolean { function* getCodiconButtonOccluders(element: HTMLElement): Iterable<HTMLElement> { for (const child of element.children) {- if (!isHTMLElement(child) || child.classList.contains('sessions-chat-background')) {+ if (!isHTMLElement(child)+ || child.classList.contains('sessions-chat-background')+ || child.classList.contains('sessions-chat-codicon-hit-target')) { continue; } if (isCodiconButtonOccluder(child)) {@@ -123,7 +132,6 @@ interface ICodiconCell { readonly element: HTMLElement; readonly icon: HTMLElement; readonly animationElement?: HTMLElement;- readonly disposable?: IDisposable; } export class SessionsChatBackgroundRenderer extends Disposable {@@ -133,6 +141,7 @@ export class SessionsChatBackgroundRenderer extends Disposable { private readonly codiconCells = new Map<string, ICodiconCell>(); private readonly confettiCandidates = new Set<string>(); private readonly foregroundResizeObservations = new Map<HTMLElement, IDisposable>();+ private readonly confettiButton: Button | undefined; private readonly _onDidActivateCodicon = this._register(new Emitter<HTMLElement>()); readonly onDidActivateCodicon: Event<HTMLElement> = this._onDidActivateCodicon.event; private readonly refreshScheduler: RunOnceScheduler;@@ -153,17 +162,11 @@ export class SessionsChatBackgroundRenderer extends Disposable { )); this.backgroundLayer = $('.sessions-chat-background');- if (!this.interactive) {- this.backgroundLayer.ariaHidden = 'true';- } else {- this.backgroundLayer.classList.add('sessions-chat-background-interactive');- }+ this.backgroundLayer.ariaHidden = 'true'; this.backgroundLayer.hidden = true; this.codiconLayer = $('.sessions-chat-codicon-background');- if (!this.interactive) {- this.codiconLayer.ariaHidden = 'true';- }+ this.codiconLayer.ariaHidden = 'true'; this.codiconLayer.hidden = true; this.backgroundLayer.appendChild(this.codiconLayer); this.element.prepend(this.backgroundLayer);@@ -173,6 +176,17 @@ export class SessionsChatBackgroundRenderer extends Disposable { this.backgroundLayer.remove(); })); + if (this.interactive) {+ const label = localize('sessionsChatBackground.confettiButton', "Celebrate");+ this.confettiButton = this._register(new Button(this.element, { ariaLabel: label, title: label }));+ this.confettiButton.element.classList.add('sessions-chat-codicon-hit-target');+ this.element.insertBefore(this.confettiButton.element, this.backgroundLayer);+ this.confettiButton.element.hidden = true;+ this._register(this.confettiButton.onDidClick(() => this.activateConfettiCell()));+ } else {+ this.confettiButton = undefined;+ }+ this.resizeObserver = this._register(new DisposableResizeObserver( 'SessionsChatBackgroundRenderer', () => this.refreshScheduler.schedule(),@@ -188,7 +202,7 @@ export class SessionsChatBackgroundRenderer extends Disposable { childList: true, subtree: true, })(mutations => {- if (mutations.some(mutation => !this.backgroundLayer.contains(mutation.target))) {+ if (mutations.some(mutation => !this.backgroundLayer.contains(mutation.target) && !this.confettiButton?.element.contains(mutation.target))) { this.refreshScheduler.schedule(); } }));@@ -244,22 +258,19 @@ export class SessionsChatBackgroundRenderer extends Disposable { } } - const preserveFocus = !!this.confettiCell- && this.codiconCells.get(this.confettiCell)?.element === getWindow(this.element).document.activeElement; if (this.interactive && (!this.confettiCell || !this.confettiCandidates.has(this.confettiCell))) { const candidates = [...this.confettiCandidates]; this.confettiCell = candidates.length ? candidates[Math.min(candidates.length - 1, Math.floor(this.random() * candidates.length))] : undefined; } if (gridSize === this.codiconGridSize) {- this.updateConfettiButtons(preserveFocus);+ this.updateConfettiButton(); return; } this.codiconGridSize = gridSize; for (const [cell, codiconCell] of this.codiconCells) { if (!visibleCells.has(cell)) {- codiconCell.disposable?.dispose(); codiconCell.element.remove(); this.codiconCells.delete(cell); }@@ -273,7 +284,7 @@ export class SessionsChatBackgroundRenderer extends Disposable { } const icon = codiconChoices[hashCodiconCell(row, column, 1) % codiconChoices.length];- const codiconCell = this.interactive ? this.createCodiconButton(cell, icon) : this.createDecorativeCodicon(icon);+ const codiconCell = this.interactive ? this.createInteractiveCodicon(icon) : this.createDecorativeCodicon(icon); if (this.interactive) { codiconCell.element.style.left = `${layout.left}px`; codiconCell.element.style.top = `${layout.top}px`;@@ -289,7 +300,7 @@ export class SessionsChatBackgroundRenderer extends Disposable { this.codiconLayer.appendChild(codiconCell.element); } - this.updateConfettiButtons(preserveFocus);+ this.updateConfettiButton(); } private getConfettiCandidateGeometry(): IConfettiCandidateGeometry {@@ -338,64 +349,64 @@ export class SessionsChatBackgroundRenderer extends Disposable { return { element, icon: element }; } - private createCodiconButton(cell: string, icon: ThemeIcon): ICodiconCell {- const disposables = new DisposableStore();- const button = disposables.add(new Button(this.codiconLayer, {}));- button.element.classList.add('sessions-chat-codicon-cell');- button.element.style.width = `${codiconButtonSize}px`;- button.element.style.height = `${codiconButtonSize}px`;+ private createInteractiveCodicon(icon: ThemeIcon): ICodiconCell {+ const element = $('.sessions-chat-codicon-cell');+ element.ariaHidden = 'true'; const animationElement = $('.sessions-chat-codicon-button-animation');- const buttonIcon = renderIcon(icon);- buttonIcon.ariaHidden = 'true';- animationElement.appendChild(buttonIcon);- button.element.appendChild(animationElement);- disposables.add(button.onDidClick(event => {- if (this.confettiCell !== cell) {- return;- }+ const iconElement = renderIcon(icon);+ iconElement.ariaHidden = 'true';+ animationElement.appendChild(iconElement);+ element.appendChild(animationElement);+ return { element, icon: iconElement, animationElement };+ } - this._onDidActivateCodicon.fire(animationElement);- this.selectNextConfettiCell(cell, event.type === EventType.KEY_DOWN);- }));- return { element: button.element, icon: buttonIcon, animationElement, disposable: disposables };+ private activateConfettiCell(): void {+ if (!this.confettiCell) {+ return;+ }++ const cell = this.codiconCells.get(this.confettiCell);+ if (!cell?.animationElement) {+ return;+ }++ this._onDidActivateCodicon.fire(cell.animationElement);+ this.selectNextConfettiCell(this.confettiCell); } - private selectNextConfettiCell(currentCell: string, preserveFocus: boolean): void {+ private selectNextConfettiCell(currentCell: string): void { const candidates = [...this.confettiCandidates].filter(cell => cell !== currentCell); if (!candidates.length) { return; } const candidateIndex = Math.min(candidates.length - 1, Math.floor(this.random() * candidates.length)); this.confettiCell = candidates[candidateIndex];- this.updateConfettiButtons(preserveFocus);+ this.updateConfettiButton(); } - private updateConfettiButtons(preserveFocus = false): void {- const label = localize('sessionsChatBackground.confettiButton', "Celebrate");- for (const [cell, codiconCell] of this.codiconCells) {- if (!codiconCell.animationElement) {- continue;- }+ private updateConfettiButton(): void {+ if (!this.confettiButton) {+ return;+ } - const active = cell === this.confettiCell;- codiconCell.element.classList.toggle('sessions-chat-codicon-button', active);- codiconCell.element.tabIndex = active ? 0 : -1;- if (active) {- codiconCell.element.removeAttribute('aria-hidden');- codiconCell.element.setAttribute('role', 'button');- codiconCell.element.setAttribute('aria-label', label);- codiconCell.element.title = label;- } else {- codiconCell.element.blur();- codiconCell.element.ariaHidden = 'true';- codiconCell.element.removeAttribute('role');- codiconCell.element.removeAttribute('aria-label');- codiconCell.element.removeAttribute('title');- }+ const confettiCell = this.confettiCell;+ const cell = confettiCell ? this.codiconCells.get(confettiCell) : undefined;+ if (!confettiCell || !cell) {+ this.confettiButton.element.hidden = true;+ this.updateActiveConfettiCell();+ return; }- if (preserveFocus && this.confettiCell) {- this.codiconCells.get(this.confettiCell)?.element.focus();++ this.confettiButton.element.style.left = cell.element.style.left;+ this.confettiButton.element.style.top = cell.element.style.top;+ this.confettiButton.element.hidden = false;+ this.updateActiveConfettiCell();+ }++ private updateActiveConfettiCell(): void {+ for (const [cellId, cell] of this.codiconCells) {+ cell.element.classList.toggle('sessions-chat-codicon-button-active', cellId === this.confettiCell); } } @@ -404,8 +415,9 @@ export class SessionsChatBackgroundRenderer extends Disposable { observation.dispose(); } this.foregroundResizeObservations.clear();- for (const cell of this.codiconCells.values()) {- cell.disposable?.dispose();+ if (this.confettiButton) {+ this.confettiButton.element.blur();+ this.confettiButton.element.hidden = true; } this.codiconCells.clear(); this.confettiCandidates.clear();src/vs/sessions/services/chatBackground/browser/media/chatBackground.css11 + / 8 −
@@ -18,10 +18,6 @@ pointer-events: none; } -.sessions-chat-background.sessions-chat-background-interactive {- z-index: auto;-}- .sessions-chat-background, .sessions-chat-background-replica-viewport { inset: 0;@@ -47,11 +43,14 @@ } .sessions-chat-background > .sessions-chat-codicon-background > .codicon,-.sessions-chat-codicon-cell {+.sessions-chat-codicon-cell,+.sessions-chat-codicon-hit-target { position: absolute; } .sessions-chat-codicon-cell {+ width: var(--vscode-spacing-size240);+ height: var(--vscode-spacing-size240); border-radius: var(--vscode-cornerRadius-small); color: inherit; transform: translate(-50%, -50%);@@ -60,21 +59,25 @@ place-items: center; } -.sessions-chat-codicon-button {+.monaco-workbench .part.sessionspart > .sessions-chat-codicon-hit-target {+ width: var(--vscode-spacing-size240);+ height: var(--vscode-spacing-size240); z-index: 3;+ opacity: 0; pointer-events: auto;+ transform: translate(-50%, -50%); } .sessions-chat-codicon-button-animation { display: flex; line-height: 1; } -.sessions-chat-codicon-button:hover {+.monaco-workbench .part.sessionspart > .sessions-chat-codicon-hit-target:hover ~ .sessions-chat-background .sessions-chat-codicon-button-active { background-color: var(--vscode-toolbar-hoverBackground); } -.sessions-chat-codicon-button:focus-visible {+.monaco-workbench .part.sessionspart > .sessions-chat-codicon-hit-target:focus-visible ~ .sessions-chat-background .sessions-chat-codicon-button-active { background-color: var(--vscode-toolbar-hoverBackground); outline: var(--vscode-strokeThickness) solid var(--vscode-focusBorder); outline-offset: calc(-1 * var(--vscode-strokeThickness));