Automatically expands collapsed custom project fields in the GitHub issue/PR sidebar (workaround for https://github.com/orgs/community/discussions/15592).
// ==UserScript==
// @name GitHub Auto-Expand Project Fields
// @namespace https://x.com/ArtemR
// @version 1.0
// @description Automatically expands collapsed custom project fields in the GitHub issue/PR sidebar (workaround for https://github.com/orgs/community/discussions/15592).
// @author Artem Russakovskii
// @license MIT
// @match https://github.com/*/*/issues/*
// @match https://github.com/*/*/pull/*
// @run-at document-idle
// @grant none
// ==/UserScript==
(() => {
// Remember what we already started so MutationObserver doesn't re-trigger
// mid-load (for PRs, a second load() aborts the in-flight fetch).
const started = new Set();
let path = location.pathname;
function expand() {
if (location.pathname !== path) {
started.clear();
path = location.pathname;
}
// Issues: React sidebar. Prefer structure/icons over English tooltip text.
for (const section of document.querySelectorAll(
'[class*="ProjectItemSectionViewContainer"]'
)) {
const btn = section.querySelector(
'button[aria-expanded="false"]:has(.octicon-chevron-down)'
);
const key = section.querySelector('a[href*="/projects/"]')?.href;
if (!btn || !key || started.has(key)) {
continue;
}
started.add(key);
btn.click();
}
// PRs: Catalyst widget. Use load() (fetches fields); setOpen() only flips the chevron.
for (const widget of document.querySelectorAll(
"collapsible-sidebar-widget:not([open])"
)) {
const key = widget.getAttribute("url");
if (!key || typeof widget.load !== "function" || started.has(key)) {
continue;
}
started.add(key);
widget.load();
}
}
new MutationObserver(expand).observe(document.body, {
childList: true,
subtree: true,
});
expand();
})();