Skip to content

Instantly share code, notes, and snippets.

@CaptainVincent
Last active February 20, 2025 00:23
Show Gist options
  • Save CaptainVincent/74a15cd9d9c450e961b867f69008ee6e to your computer and use it in GitHub Desktop.
Save CaptainVincent/74a15cd9d9c450e961b867f69008ee6e to your computer and use it in GitHub Desktop.
Improve your vscode quickinput-widget

Customize your quickinput-widget

This is a small tool designed to emulate the Sublime style Command Palette as follows.

Screenshot

It requires the use of a specific extension to load the js file from this gist.

I'm using the APC extension, and the usage is as follows.

Here is my settings.json and you should write with your own file path with extension Custom CSS and JS

"vscode_custom_css.imports": [
    "file:///Users/captainvincent/.vscode/scripts/resize-quickinput-widget.js"
]

Temporarily removed the usage of APC because it's incompatible with the current version of VS Code.

Buy Me a Coffee at ko-fi.com

/*
* 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/.
*/
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: 80px !important;
// width: 50% !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);
@raulpenate
Copy link

Appreciate it big dawg, works amazing!

For .dotfiles guys, use the vs code home env var in case you've different $HOME users between PCs:

    "apc.imports": [
      "${userHome}/.config/vscode/resize-quickinput-widget.js"
    ],

@DiammdM
Copy link

DiammdM commented Sep 25, 2024

I try it. It works well! Thank you for sharing!

@CaptainVincent
Copy link
Author

Thank you so much for your feedback! I'm glad to hear that it worked well for you. If you have any other thoughts or suggestions, feel free to share. I appreciate your input!

@DiammdM
Copy link

DiammdM commented Oct 5, 2024

Thank you so much for your feedback! I'm glad to hear that it worked well for you. If you have any other thoughts or suggestions, feel free to share. I appreciate your input!

I think making it a VSCode plugin will be more convenient for users

@CaptainVincent
Copy link
Author

Ok~ I will think about how to do it better. By the way, APC is currently incompatible with the latest version of VSCode drcika/apc-extension#230, so I have temporarily switched to using Custom CSS and JS Loader instead. I am sharing this for those who encounter the same issue.

@Sectimus
Copy link

Sectimus commented Oct 17, 2024

Doesn't seem to work for me :(

"settings": {
    "vscode_custom_css.imports": [
        "file:///home/REDACTED/.config/vscode/resize-quickinput-widget.js"
    ]
}

It does indeed exist at that path:

$ ls -la /home/REDACTED/.config/vscode/resize-quickinput-widget.js
> -rw-r--r-- 1 REDACTED domain users 6405 Oct 18 00:39 /home/REDACTED/.config/vscode/resize-quickinput-widget.js

I did try to also disable/enable the Custom CSS and JS Loader extension and restart vscode to no avail.

@CaptainVincent
Copy link
Author

CaptainVincent commented Oct 22, 2024

I'm sorry to hear about this. I'm currently using macOS with Version 1.94.2 (and it's working). Have you removed any other potential conflicting extensions, such as APC, etc.? After removal, you may also need to disable, re-enable, and reload. If possible, you can also try importing other simple style files to test if the issue is related to the extension handling.

Below is another simple example I personally use. If the background color for editor focus and non-focus states doesn't differ (split views), I think the issue in your environment might be related to the extension settings, which could be preventing proper execution. It is unlikely to be related to the this script here. You may need to seek other discussions or assistance related to the Custom CSS and JS.

"vscode_custom_css.imports": [
    "file:///Users/vincent/.vscode/scripts/resize-quickinput-widget.js",
    "file:///Users/vincent/.vscode/styles/user.css"
],
:not(.active).editor-group-container .margin {
    background-color: #181d27 !important;
}

:not(.active).editor-group-container .monaco-editor,
:not(.active).editor-group-container .monaco-editor-background {
    background-color: #181d27 !important;
}

:not(.active).editor-group-container.empty {
    background-color: #181d27 !important;
}

.editor-group-container-toolbar {
    background-color: #20242F !important;
}

.monaco-workbench .part.editor>.content .editor-group-container.empty {
    opacity: 1.0 !important;
}

.tab-border-bottom-container {
    height: 2px !important;
}

.pane-header.expanded {
    border-top: 1px solid #727A8A !important;
}

@AndreaHasani
Copy link

Is it me or this has issues with arrow navigation, just by going up (so it will go to the end) it will break it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment