diff --git a/packages/playwright-core/src/server/injected/highlight.css.ts b/packages/playwright-core/src/server/injected/highlight.css.ts new file mode 100644 index 0000000000..18955755ba --- /dev/null +++ b/packages/playwright-core/src/server/injected/highlight.css.ts @@ -0,0 +1,172 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const highlightCSS = ` +x-pw-tooltip { + backdrop-filter: blur(5px); + background-color: white; + color: #222; + border-radius: 6px; + box-shadow: 0 0.5rem 1.2rem rgba(0,0,0,.3); + display: none; + font-family: 'Dank Mono', 'Operator Mono', Inconsolata, 'Fira Mono', + 'SF Mono', Monaco, 'Droid Sans Mono', 'Source Code Pro', monospace; + font-size: 12.8px; + font-weight: normal; + left: 0; + line-height: 1.5; + max-width: 600px; + position: absolute; + top: 0; +} +x-pw-tooltip-body { + align-items: center; + padding: 3.2px 5.12px 3.2px; +} +x-pw-highlight { + position: absolute; + top: 0; + left: 0; + width: 0; + height: 0; +} +x-pw-action-point { + position: absolute; + width: 20px; + height: 20px; + background: red; + border-radius: 10px; + margin: -10px 0 0 -10px; + z-index: 2; +} +x-pw-separator { + height: 1px; + margin: 6px 9px; + background: rgb(148 148 148 / 90%); +} +x-pw-tool-gripper { + height: 28px; + width: 24px; + margin: 2px 0; + cursor: grab; +} +x-pw-tool-gripper:active { + cursor: grabbing; +} +x-pw-tool-gripper > x-div { + width: 100%; + height: 100%; + -webkit-mask-repeat: no-repeat; + -webkit-mask-position: center; + -webkit-mask-size: 20px; + mask-repeat: no-repeat; + mask-position: center; + mask-size: 16px; + -webkit-mask-image: url("data:image/svg+xml;utf8,"); + mask-image: url("data:image/svg+xml;utf8,"); + background-color: #555555; +} +x-pw-tools-list { + display: flex; + width: 100%; + border-bottom: 1px solid #dddddd; +} +x-pw-tool-item { + pointer-events: auto; + cursor: pointer; + height: 28px; + width: 28px; + border-radius: 3px; +} +x-pw-tool-item:not(.disabled):hover { + background-color: hsl(0, 0%, 86%); +} +x-pw-tool-item > x-div { + width: 100%; + height: 100%; + -webkit-mask-repeat: no-repeat; + -webkit-mask-position: center; + -webkit-mask-size: 20px; + mask-repeat: no-repeat; + mask-position: center; + mask-size: 16px; + background-color: #3a3a3a; +} +x-pw-tool-item.disabled > x-div { + background-color: rgba(97, 97, 97, 0.5); + cursor: default; +} +x-pw-tool-item.active > x-div { + background-color: #006ab1; +} +x-pw-tool-item.record.active > x-div { + background-color: #a1260d; +} +x-pw-tool-item.accept > x-div { + background-color: #388a34; +} +x-pw-tool-item.cancel > x-div { + background-color: #e51400; +} +x-pw-tool-item.record > x-div { + /* codicon: circle-large-filled */ + -webkit-mask-image: url("data:image/svg+xml;utf8,"); + mask-image: url("data:image/svg+xml;utf8,"); +} +x-pw-tool-item.pick-locator > x-div { + /* codicon: inspect */ + -webkit-mask-image: url("data:image/svg+xml;utf8,"); + mask-image: url("data:image/svg+xml;utf8,"); +} +x-pw-tool-item.assert > x-div { + /* codicon: check-all */ + -webkit-mask-image: url("data:image/svg+xml;utf8,"); + mask-image: url("data:image/svg+xml;utf8,"); +} +x-pw-tool-item.accept > x-div { + -webkit-mask-image: url("data:image/svg+xml;utf8,"); + mask-image: url("data:image/svg+xml;utf8,"); +} +x-pw-tool-item.cancel > x-div { + -webkit-mask-image: url("data:image/svg+xml;utf8,"); + mask-image: url("data:image/svg+xml;utf8,"); +} +x-pw-overlay { + position: absolute; + top: 0; + max-width: min-content; + z-index: 2147483647; + background: transparent; + pointer-events: auto; +} +x-pw-overlay x-pw-tools-list { + background-color: #ffffffdd; + box-shadow: rgba(0, 0, 0, 0.1) 0px 5px 5px; + border-radius: 3px; + border-bottom: none; +} +x-pw-overlay x-pw-tool-item { + margin: 2px; +} +x-div { + display: block; +} +* { + box-sizing: border-box; +} +*[hidden] { + display: none !important; +}`; diff --git a/packages/playwright-core/src/server/injected/highlight.ts b/packages/playwright-core/src/server/injected/highlight.ts index 16dd044949..d6253d3292 100644 --- a/packages/playwright-core/src/server/injected/highlight.ts +++ b/packages/playwright-core/src/server/injected/highlight.ts @@ -19,6 +19,7 @@ import type { ParsedSelector } from '../../utils/isomorphic/selectorParser'; import type { InjectedScript } from './injectedScript'; import { asLocator } from '../../utils/isomorphic/locatorGenerators'; import type { Language } from '../../utils/isomorphic/locatorGenerators'; +import { highlightCSS } from './highlight.css'; type HighlightEntry = { targetElement: Element, @@ -34,7 +35,8 @@ export type HighlightOptions = { tooltipText?: string; color?: string; anchorGetter?: (element: Element) => DOMRect; - decorateTooltip?: (tooltip: Element) => void; + toolbar?: Element[]; + interactive?: boolean; }; export class Highlight { @@ -67,44 +69,7 @@ export class Highlight { this._glassPaneShadow = this._glassPaneElement.attachShadow({ mode: this._isUnderTest ? 'open' : 'closed' }); this._glassPaneShadow.appendChild(this._actionPointElement); const styleElement = document.createElement('style'); - styleElement.textContent = ` - x-pw-tooltip { - align-items: center; - backdrop-filter: blur(5px); - background-color: rgba(0, 0, 0, 0.7); - border-radius: 2px; - box-shadow: rgba(0, 0, 0, 0.1) 0px 3.6px 3.7px, - rgba(0, 0, 0, 0.15) 0px 12.1px 12.3px, - rgba(0, 0, 0, 0.1) 0px -2px 4px, - rgba(0, 0, 0, 0.15) 0px -12.1px 24px, - rgba(0, 0, 0, 0.25) 0px 54px 55px; - color: rgb(204, 204, 204); - display: none; - font-family: 'Dank Mono', 'Operator Mono', Inconsolata, 'Fira Mono', - 'SF Mono', Monaco, 'Droid Sans Mono', 'Source Code Pro', monospace; - font-size: 12.8px; - font-weight: normal; - left: 0; - line-height: 1.5; - max-width: 600px; - padding: 3.2px 5.12px 3.2px; - position: absolute; - top: 0; - } - x-pw-action-point { - position: absolute; - width: 20px; - height: 20px; - background: red; - border-radius: 10px; - pointer-events: none; - margin: -10px 0 0 -10px; - z-index: 2; - } - *[hidden] { - display: none !important; - } - `; + styleElement.textContent = highlightCSS; this._glassPaneShadow.appendChild(styleElement); } @@ -180,13 +145,26 @@ export class Highlight { let tooltipElement; if (options.tooltipText) { tooltipElement = this._injectedScript.document.createElement('x-pw-tooltip'); - this._glassPaneShadow.appendChild(tooltipElement); - const suffix = elements.length > 1 ? ` [${i + 1} of ${elements.length}]` : ''; - tooltipElement.textContent = options.tooltipText + suffix; tooltipElement.style.top = '0'; tooltipElement.style.left = '0'; tooltipElement.style.display = 'flex'; - options.decorateTooltip?.(tooltipElement); + tooltipElement.style.flexDirection = 'column'; + tooltipElement.style.alignItems = 'start'; + if (options.interactive) + tooltipElement.style.pointerEvents = 'auto'; + + if (options.toolbar) { + const toolbar = this._injectedScript.document.createElement('x-pw-tools-list'); + tooltipElement.appendChild(toolbar); + for (const toolbarElement of options.toolbar) + toolbar.appendChild(toolbarElement); + } + const bodyElement = this._injectedScript.document.createElement('x-pw-tooltip-body'); + tooltipElement.appendChild(bodyElement); + + this._glassPaneShadow.appendChild(tooltipElement); + const suffix = elements.length > 1 ? ` [${i + 1} of ${elements.length}]` : ''; + bodyElement.textContent = options.tooltipText + suffix; } this._highlightEntries.push({ targetElement: elements[i], tooltipElement, highlightElement, tooltipText: options.tooltipText }); } @@ -260,13 +238,10 @@ export class Highlight { } private _createHighlightElement(): HTMLElement { - const highlightElement = this._injectedScript.document.createElement('x-pw-highlight'); - highlightElement.style.position = 'absolute'; - highlightElement.style.top = '0'; - highlightElement.style.left = '0'; - highlightElement.style.width = '0'; - highlightElement.style.height = '0'; - highlightElement.style.boxSizing = 'border-box'; - return highlightElement; + return this._injectedScript.document.createElement('x-pw-highlight'); + } + + appendChild(element: HTMLElement) { + this._glassPaneShadow.appendChild(element); } } diff --git a/packages/playwright-core/src/server/injected/recorder.ts b/packages/playwright-core/src/server/injected/recorder.ts index f262fa19bc..19545c15f5 100644 --- a/packages/playwright-core/src/server/injected/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder.ts @@ -36,8 +36,7 @@ interface RecorderDelegate { interface RecorderTool { cursor(): string; - enable?(): void; - disable?(): void; + cleanup?(): void; onClick?(event: MouseEvent): void; onDragStart?(event: DragEvent): void; onInput?(event: Event): void; @@ -70,7 +69,7 @@ class InspectTool implements RecorderTool { return 'pointer'; } - disable() { + cleanup() { this._hoveredModel = null; this._hoveredElement = null; } @@ -151,7 +150,7 @@ class RecordActionTool implements RecorderTool { return 'pointer'; } - disable() { + cleanup() { this._hoveredModel = null; this._hoveredElement = null; this._activeModel = null; @@ -447,25 +446,25 @@ class TextAssertionTool implements RecorderTool { private _selectionText: { selectedText: string, fullText: string } | null = null; private _inputHighlight: HighlightModel | null = null; private _acceptButton: HTMLElement; + private _cancelButton: HTMLElement; constructor(private _recorder: Recorder) { - this._acceptButton = this._recorder.document.createElement('button'); - this._acceptButton.textContent = 'Accept'; - this._acceptButton.style.cursor = 'pointer'; - this._acceptButton.style.pointerEvents = 'auto'; + this._acceptButton = this._recorder.document.createElement('x-pw-tool-item'); + this._acceptButton.classList.add('accept'); + this._acceptButton.appendChild(this._recorder.document.createElement('x-div')); this._acceptButton.addEventListener('click', () => this._commitAction()); + + this._cancelButton = this._recorder.document.createElement('x-pw-tool-item'); + this._cancelButton.classList.add('cancel'); + this._cancelButton.appendChild(this._recorder.document.createElement('x-div')); + this._cancelButton.addEventListener('click', () => this._cancelAction()); } cursor() { return 'text'; } - enable() { - this._recorder.injectedScript.document.designMode = 'on'; - } - - disable() { - this._recorder.injectedScript.document.designMode = 'off'; + cleanup() { this._hoverHighlight = null; this._selectionHighlight = null; this._selectionText = null; @@ -473,11 +472,6 @@ class TextAssertionTool implements RecorderTool { } onClick(event: MouseEvent) { - // Hack: work around highlight's glass pane having a closed shadow root. - const box = this._acceptButton.getBoundingClientRect(); - if (box.left <= event.clientX && event.clientX <= box.right && box.top <= event.clientY && event.clientY <= box.bottom) - return; - consumeEvent(event); const selection = this._recorder.document.getSelection(); if (event.detail === 1 && selection && !selection.toString() && !this._inputHighlight) { @@ -612,6 +606,10 @@ class TextAssertionTool implements RecorderTool { } } + private _cancelAction() { + this._resetSelectionAndHighlight(); + } + private _resetSelectionAndHighlight() { this._selectionHighlight = null; this._selectionText = null; @@ -643,7 +641,12 @@ class TextAssertionTool implements RecorderTool { } private _showHighlight(userGesture: boolean) { - const options: HighlightOptions = { color: '#6fdcbd38', tooltipText: this._generateActionPreview(), decorateTooltip: tooltip => tooltip.appendChild(this._acceptButton) }; + const options: HighlightOptions = { + color: '#6fdcbd38', + tooltipText: this._generateActionPreview(), + toolbar: [this._acceptButton, this._cancelButton], + interactive: true, + }; if (this._inputHighlight) { this._recorder.updateHighlight(this._inputHighlight, userGesture, options); } else { @@ -665,119 +668,21 @@ class Overlay { constructor(private _recorder: Recorder) { const document = this._recorder.injectedScript.document; this._overlayElement = document.createElement('x-pw-overlay'); - this._overlayElement.style.top = '0'; - this._overlayElement.style.position = 'absolute'; - - const shadow = this._overlayElement.attachShadow({ mode: 'closed' }); - const styleElement = document.createElement('style'); - styleElement.textContent = ` - :host { - position: fixed; - max-width: min-content; - z-index: 2147483647; - background: transparent; - } - - x-pw-tools-list { - box-shadow: rgba(0, 0, 0, 0.1) 0px 5px 5px; - backdrop-filter: blur(5px); - background-color: hsla(0 0% 100% / .9); - font-family: 'Dank Mono', 'Operator Mono', Inconsolata, 'Fira Mono', 'SF Mono', Monaco, 'Droid Sans Mono', 'Source Code Pro', monospace; - display: flex; - border-radius: 3px; - } - - x-pw-separator { - height: 1px; - margin: 6px 9px; - background: rgb(148 148 148 / 90%); - } - - x-pw-tool-item { - cursor: pointer; - height: 28px; - width: 28px; - margin: 2px 4px; - border-radius: 3px; - } - x-pw-tool-item:not(.disabled):hover { - background-color: hsl(0, 0%, 86%); - } - x-pw-tool-item > div { - width: 100%; - height: 100%; - -webkit-mask-repeat: no-repeat; - -webkit-mask-position: center; - -webkit-mask-size: 20px; - mask-repeat: no-repeat; - mask-position: center; - mask-size: 16px; - background-color: #3a3a3a; - } - x-pw-tool-item.disabled > div { - background-color: rgba(97, 97, 97, 0.5); - cursor: default; - } - x-pw-tool-item.active > div { - background-color: #006ab1; - } - x-pw-tool-item.record.active > div { - background-color: #a1260d; - } - x-pw-tool-gripper { - height: 28px; - width: 24px; - margin: 2px 0; - cursor: grab; - } - x-pw-tool-gripper:active { - cursor: grabbing; - } - x-pw-tool-gripper > div { - width: 100%; - height: 100%; - -webkit-mask-repeat: no-repeat; - -webkit-mask-position: center; - -webkit-mask-size: 20px; - mask-repeat: no-repeat; - mask-position: center; - mask-size: 16px; - -webkit-mask-image: url("data:image/svg+xml;utf8,"); - mask-image: url("data:image/svg+xml;utf8,"); - background-color: #555555; - } - x-pw-tool-item.record > div { - /* codicon: circle-large-filled */ - -webkit-mask-image: url("data:image/svg+xml;utf8,"); - mask-image: url("data:image/svg+xml;utf8,"); - } - x-pw-tool-item.pick-locator > div { - /* codicon: inspect */ - -webkit-mask-image: url("data:image/svg+xml;utf8,"); - mask-image: url("data:image/svg+xml;utf8,"); - } - x-pw-tool-item.assert > div { - /* codicon: check-all */ - -webkit-mask-image: url("data:image/svg+xml;utf8,"); - mask-image: url("data:image/svg+xml;utf8,"); - } - `; - shadow.appendChild(styleElement); const toolsListElement = document.createElement('x-pw-tools-list'); - shadow.appendChild(toolsListElement); + this._overlayElement.appendChild(toolsListElement); const dragHandle = document.createElement('x-pw-tool-gripper'); dragHandle.addEventListener('mousedown', event => { this._dragState = { offsetX: this._offsetX, dragStart: { x: event.clientX, y: 0 } }; }); - dragHandle.appendChild(document.createElement('div')); + dragHandle.appendChild(document.createElement('x-div')); toolsListElement.appendChild(dragHandle); this._recordToggle = this._recorder.injectedScript.document.createElement('x-pw-tool-item'); this._recordToggle.title = 'Record'; this._recordToggle.classList.add('record'); - this._recordToggle.appendChild(this._recorder.injectedScript.document.createElement('div')); + this._recordToggle.appendChild(this._recorder.injectedScript.document.createElement('x-div')); this._recordToggle.addEventListener('click', () => { this._recorder.delegate.setMode?.(this._recorder.state.mode === 'none' || this._recorder.state.mode === 'inspecting' ? 'recording' : 'none'); }); @@ -786,7 +691,7 @@ class Overlay { this._pickLocatorToggle = this._recorder.injectedScript.document.createElement('x-pw-tool-item'); this._pickLocatorToggle.title = 'Pick locator'; this._pickLocatorToggle.classList.add('pick-locator'); - this._pickLocatorToggle.appendChild(this._recorder.injectedScript.document.createElement('div')); + this._pickLocatorToggle.appendChild(this._recorder.injectedScript.document.createElement('x-div')); this._pickLocatorToggle.addEventListener('click', () => { const newMode: Record = { 'inspecting': 'none', @@ -802,7 +707,7 @@ class Overlay { this._assertToggle = this._recorder.injectedScript.document.createElement('x-pw-tool-item'); this._assertToggle.title = 'Assert text and values'; this._assertToggle.classList.add('assert'); - this._assertToggle.appendChild(this._recorder.injectedScript.document.createElement('div')); + this._assertToggle.appendChild(this._recorder.injectedScript.document.createElement('x-div')); this._assertToggle.addEventListener('click', () => { if (!this._assertToggle.classList.contains('disabled')) this._recorder.delegate.setMode?.(this._recorder.state.mode === 'assertingText' ? 'recording' : 'assertingText'); @@ -813,7 +718,7 @@ class Overlay { } install() { - this._recorder.injectedScript.document.documentElement.appendChild(this._overlayElement); + this._recorder.highlight.appendChild(this._overlayElement); this._measure = this._overlayElement.getBoundingClientRect(); } @@ -877,7 +782,7 @@ export class Recorder { private _currentTool: RecorderTool; private _tools: Record; private _actionSelectorModel: HighlightModel | null = null; - private _highlight: Highlight; + readonly highlight: Highlight; private _overlay: Overlay | undefined; private _styleElement: HTMLStyleElement; state: UIState = { mode: 'none', testIdAttributeName: 'data-testid', language: 'javascript', overlay: { offsetX: 0 } }; @@ -887,7 +792,7 @@ export class Recorder { constructor(injectedScript: InjectedScript) { this.document = injectedScript.document; this.injectedScript = injectedScript; - this._highlight = new Highlight(injectedScript); + this.highlight = new Highlight(injectedScript); this._tools = { 'none': new NoneTool(), 'inspecting': new InspectTool(this), @@ -913,7 +818,7 @@ export class Recorder { installListeners() { // Ensure we are attached to the current document, and we are on top (last element); - if (this._highlight.isInstalled()) + if (this.highlight.isInstalled()) return; removeEventListeners(this._listeners); this._listeners = [ @@ -932,7 +837,7 @@ export class Recorder { addEventListener(this.document, 'focus', event => this._onFocus(event), true), addEventListener(this.document, 'scroll', event => this._onScroll(event), true), ]; - this._highlight.install(); + this.highlight.install(); this._overlay?.install(); this.injectedScript.document.head.appendChild(this._styleElement); } @@ -941,10 +846,9 @@ export class Recorder { const newTool = this._tools[this.state.mode]; if (newTool === this._currentTool) return; - this._currentTool.disable?.(); + this._currentTool.cleanup?.(); this.clearHighlight(); this._currentTool = newTool; - this._currentTool.enable?.(); this.injectedScript.document.body?.setAttribute('data-pw-cursor', newTool.cursor()); } @@ -957,13 +861,13 @@ export class Recorder { // All good. } else { if (state.actionPoint) - this._highlight.showActionPoint(state.actionPoint.x, state.actionPoint.y); + this.highlight.showActionPoint(state.actionPoint.x, state.actionPoint.y); else - this._highlight.hideActionPoint(); + this.highlight.hideActionPoint(); } this.state = state; - this._highlight.setLanguage(state.language); + this.highlight.setLanguage(state.language); this._switchCurrentTool(); this._overlay?.setUIState(state); @@ -977,7 +881,7 @@ export class Recorder { } clearHighlight() { - this._currentTool.disable?.(); + this._currentTool.cleanup?.(); this.updateHighlight(null, false); } @@ -1062,7 +966,7 @@ export class Recorder { private _onScroll(event: Event) { if (!event.isTrusted) return; - this._highlight.hideActionPoint(); + this.highlight.hideActionPoint(); this._currentTool.onScroll?.(event); } @@ -1091,13 +995,14 @@ export class Recorder { updateHighlight(model: HighlightModel | null, userGesture: boolean, options: HighlightOptions = {}) { if (options.tooltipText === undefined && model?.selector) options.tooltipText = asLocator(this.state.language, model.selector); - this._highlight.updateHighlight(model?.elements || [], options); + this.highlight.updateHighlight(model?.elements || [], options); if (userGesture) this.delegate.highlightUpdated?.(); } private _ignoreOverlayEvent(event: Event) { - return this._overlay?.contains(event.composedPath()[0] as Element); + const target = event.composedPath()[0] as Element; + return target.nodeName.toLowerCase() === 'x-pw-glass'; } deepEventTarget(event: Event): HTMLElement { diff --git a/packages/playwright-core/src/server/recorder/recorderApp.ts b/packages/playwright-core/src/server/recorder/recorderApp.ts index 6f56db67b7..37ff723dff 100644 --- a/packages/playwright-core/src/server/recorder/recorderApp.ts +++ b/packages/playwright-core/src/server/recorder/recorderApp.ts @@ -176,9 +176,9 @@ export class RecorderApp extends EventEmitter implements IRecorderApp { this._recorder.setMode('recording'); } } - await this._page.mainFrame().evaluateExpression(((selector: string) => { - window.playwrightSetSelector(selector); - }).toString(), { isFunction: true }, selector).catch(() => {}); + await this._page.mainFrame().evaluateExpression(((data: { selector: string, userGesture?: boolean }) => { + window.playwrightSetSelector(data.selector, data.userGesture); + }).toString(), { isFunction: true }, { selector, userGesture }).catch(() => {}); } async updateCallLogs(callLogs: CallLog[]): Promise { diff --git a/packages/recorder/src/recorder.tsx b/packages/recorder/src/recorder.tsx index 6a1c6eb325..7892791183 100644 --- a/packages/recorder/src/recorder.tsx +++ b/packages/recorder/src/recorder.tsx @@ -66,8 +66,10 @@ export const Recorder: React.FC = ({ }; const [locator, setLocator] = React.useState(''); - window.playwrightSetSelector = (selector: string) => { + window.playwrightSetSelector = (selector: string, focus?: boolean) => { const language = source.language; + if (focus) + setSelectedTab('locator'); setLocator(asLocator(language, selector)); }; @@ -126,7 +128,6 @@ export const Recorder: React.FC = ({ 'assertingText': 'recording-inspecting', }[mode]; window.dispatch({ event: 'setMode', params: { mode: newMode } }).catch(() => { }); - setSelectedTab('locator'); }}>Pick locator { window.dispatch({ event: 'setMode', params: { mode: mode === 'assertingText' ? 'recording' : 'assertingText' } }); @@ -155,7 +156,7 @@ export const Recorder: React.FC = ({ }}> toggleTheme()}> - + copy(locator)} />] : []} @@ -163,7 +164,7 @@ export const Recorder: React.FC = ({ { id: 'locator', title: 'Locator', - render: () => + render: () => }, { id: 'log', diff --git a/packages/web/src/components/codeMirrorWrapper.css b/packages/web/src/components/codeMirrorWrapper.css index 5abb4cc722..1e79c18274 100644 --- a/packages/web/src/components/codeMirrorWrapper.css +++ b/packages/web/src/components/codeMirrorWrapper.css @@ -16,6 +16,10 @@ @import '../third_party/vscode/colors.css'; +.cm-wrapper { + line-height: 18px; +} + .cm-wrapper, .cm-wrapper > div { width: 100%; height: 100%; diff --git a/packages/web/src/components/codeMirrorWrapper.tsx b/packages/web/src/components/codeMirrorWrapper.tsx index 3f64a1d944..738f0cfff1 100644 --- a/packages/web/src/components/codeMirrorWrapper.tsx +++ b/packages/web/src/components/codeMirrorWrapper.tsx @@ -93,7 +93,6 @@ export const CodeMirrorWrapper: React.FC = ({ // Either configuration is different or we don't have a codemirror yet. codemirrorRef.current?.cm?.getWrapperElement().remove(); - const cm = CodeMirror(element, { value: '', mode, diff --git a/packages/web/src/components/toolbarButton.css b/packages/web/src/components/toolbarButton.css index bdf6db9ad9..813d9e4b91 100644 --- a/packages/web/src/components/toolbarButton.css +++ b/packages/web/src/components/toolbarButton.css @@ -43,10 +43,6 @@ color: var(--vscode-notificationLink-foreground); } -.toolbar-button.toggled .codicon { - font-weight: bold; -} - .toolbar-separator { flex: none; background-color: var(--vscode-menu-separatorBackground);