Created
July 20, 2025 19:05
-
-
Save ospfranco/e8224e620339e28cb0802236f3f3a002 to your computer and use it in GitHub Desktop.
A JS Snippet that allows to apply styles to the VSCode Command Palette/Quick Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* GNU GENERAL PUBLIC LICENSE | |
* Version 3, 29 June 2007 | |
* | |
* Copyright (C) [2023] [Captain Vincent] | |
* Original Source: https://gist.github.com/CaptainVincent/74a15cd9d9c450e961b867f69008ee6e | |
* | |
* Everyone is permitted to copy and distribute verbatim copies of this license document, | |
* but changing it is not allowed. | |
* | |
* Preamble | |
* | |
* The GNU General Public License is a free, copyleft license for software and other kinds of works. | |
* | |
* The licenses for most software and other practical works are designed to take away your freedom | |
* to share and change the works. By contrast, the GNU General Public License is intended to guarantee | |
* your freedom to share and change all versions of a program—to make sure it remains free software | |
* for all its users. | |
* | |
* resize-quickinput-widget.js | |
* | |
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU | |
* General Public License as published by the Free Software Foundation, either version 3 of the License, | |
* or (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without | |
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General | |
* Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License along with this program. If not, see | |
* https://www.gnu.org/licenses/. | |
*/ | |
// You need to install the Custom CC and JS Loader extension and enable this file in your settings | |
// "vscode_custom_css.imports": [ | |
// "file:///Users/[YOUR USERNAME]/.vscode/scripts/quick-input-wdiget.js" | |
// ], | |
// Follow the instructions to enable the extension | |
// Based on https://gist.github.com/CaptainVincent/74a15cd9d9c450e961b867f69008ee6e | |
var menuExist = false; | |
var quickInputListNode = null; | |
var factor = 1; | |
var refresh = false; | |
var cachedHeight = -1; | |
var cachedPreOneTop = 0; | |
const padding = 10; // up + bottom | |
// Init static style | |
var styleElement = document.createElement("style"); | |
var styles = ` | |
.quick-input-widget { | |
// box-shadow: 0 5px 10px rgba(0,0,0,0), 0 0 0 100vw rgba(0,0,0,0.15) !important; | |
top: 200px !important; | |
width: 50% !important; | |
border: 2px solid #333 !important; | |
// margin-left: 0 !important; | |
// left: 25% !important; | |
// overflow-x: auto !important; | |
} | |
.quick-input-widget .monaco-inputbox { | |
padding: 10px !important; | |
border-radius: 5px !important; | |
font-size: 14px !important; | |
} | |
.quick-input-widget .quick-input-action { | |
padding-top: 10px !important; | |
font-size: 14px !important; | |
} | |
.quick-input-widget .monaco-list-rows { | |
font-size: 13px !important; | |
} | |
.quick-input-widget .monaco-list-row { | |
padding: 5px !important; | |
height: auto !important; | |
} | |
.quick-input-widget .quick-input-list-entry { | |
position: relative; | |
padding: 0px 5px 0px 15px; | |
} | |
.quick-input-widget .quick-input-list-entry .codicon[class*=codicon-] { | |
font-size: 15px; | |
} | |
.quick-input-widget .quick-input-list .quick-input-list-entry.quick-input-list-separator-border { | |
border-top-width: 0px !important; | |
} | |
.quick-input-widget .quick-input-list .quick-input-list-label-meta .monaco-highlighted-label:before { | |
content: ' ▸ '; | |
} | |
.quick-input-widget .quick-input-list .quick-input-list-entry .monaco-action-bar.animated.quick-input-list-entry-action-bar { | |
height: unset; | |
} | |
`; | |
styleElement.textContent = styles; | |
document.head.appendChild(styleElement); | |
function zoom(obj, primaryKey, cacheKey) { | |
const v = parseInt(obj.style[primaryKey], 10); | |
if (refresh || !obj.hasOwnProperty(cacheKey) || obj[cacheKey] != v) { | |
set(obj, Math.round(v * factor), primaryKey, cacheKey); | |
return true; | |
} | |
return v === 0; | |
} | |
function set(obj, v, primaryKey, cacheKey) { | |
obj[cacheKey] = v; | |
obj.style[primaryKey] = obj[cacheKey] + "px"; | |
} | |
function setPaddingBottom(obj, v) { | |
if (parseInt(obj.style.paddingBottom, 10) != v) { | |
obj.style["paddingBottom"] = v + "px"; | |
} | |
} | |
function resize() { | |
const monacoListRows = | |
quickInputListNode.querySelector(".monaco-list-rows"); | |
const rows = quickInputListNode.querySelectorAll( | |
".monaco-list-rows .monaco-list-row" | |
); | |
refresh = false; | |
if (rows && rows.length > 0) { | |
var defaultHeight = parseInt(rows[0].style.height, 10); | |
if (defaultHeight != cachedHeight) { | |
factor = (defaultHeight + 10) / defaultHeight; | |
cachedHeight = defaultHeight; | |
refresh = true; | |
} | |
cachedPreOneTop = parseInt(rows[0].style.top, 10); | |
setPaddingBottom(quickInputListNode, 5); | |
} else { | |
setPaddingBottom(quickInputListNode, 0); | |
return; | |
} | |
zoom(quickInputListNode, "maxHeight", "cachedMaxHeight"); | |
zoom(monacoListRows, "height", "cachedHeight"); | |
zoom(monacoListRows, "top", "cachedTop"); | |
moving = false; | |
rows.forEach((row) => { | |
moving = zoom(row, "top", "cachedTop") || moving; | |
// [[Patch]] | |
// Fix a bug that some rows are not moving, so | |
// I force-set their top based on the previous one. | |
if (moving && parseInt(row.style.top, 10) < cachedPreOneTop) { | |
set( | |
row, | |
cachedPreOneTop + | |
Math.floor(parseInt(row.style.height, 10) * factor), | |
"top", | |
"cachedTop" | |
); | |
} | |
cachedPreOneTop = parseInt(row.style.top, 10); | |
}); | |
const scrollbar = quickInputListNode.querySelector(".scrollbar.vertical"); | |
if (scrollbar) { | |
zoom(scrollbar, "height", "cachedHeight"); | |
slider = scrollbar.querySelector(".slider"); | |
zoom(slider, "height", "cachedHeight"); | |
zoom(slider, "top", "cachedTop"); | |
} | |
} | |
const target = document.body; | |
const config = { attributes: true, childList: true, subtree: true }; | |
const observer = new MutationObserver((mutationsList) => { | |
for (let mutation of mutationsList) { | |
if ( | |
!menuExist && | |
mutation.type === "childList" && | |
mutation.addedNodes.length > 0 | |
) { | |
quickInputListNode = document.getElementById("quickInput_list"); | |
if (quickInputListNode) { | |
menuExist = true; | |
resize(); | |
const maxHeightObserver = new MutationObserver( | |
mutationsList => resize() | |
); | |
maxHeightObserver.observe(quickInputListNode, { | |
attributes: true, | |
childList: true, | |
subtree: true, | |
attributeFilter: ["style"], | |
}); | |
} | |
} | |
} | |
}); | |
observer.observe(target, config); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment