Skip to content

Memorize file tree sidebar width #9719

@GalaxySnail

Description

@GalaxySnail

Description

GitHub's file tree sidebar doesn't memorize its width when opened in a new tab. I'm not familiar with refined-github's codebase, so I wrote a brief userscript with the help of claude and gemini to save the width in localStorage and auto restore it.

userscript
// ==UserScript==
// @name         Momorize GitHub file tree sidebar width
// @version      2026-06-08
// @author       GalaxySnail
// @match        https://github.com/*
// @run-at       document-end
// @grant        none
// ==/UserScript==

// SPDX-License-Identifier: MIT
// Assisted-by: Claude:claude-4.6-sonnet
// Assisted-by: Gemini:gemini-3.5-flash

(async function () {
    "use strict";

    const STORAGE_KEY = "userscript_github_file_tree_width";
    const PANE_SELECTOR = 'div.prc-PageLayout-Pane-AyzHK[data-resizable="true"]';

    function load_width() {
        const px = parseFloat(localStorage.getItem(STORAGE_KEY));
        return isFinite(px) && px > 0 ? px : null;
    }

    function save_width(px) {
        localStorage.setItem(STORAGE_KEY, String(px));
    }

    function read_width(el) {
        const px = parseFloat(el.style.getPropertyValue("--pane-width"));
        return px > 0 ? px : null;
    }

    function write_width(el, width) {
        if (width !== null) {
            el.style.setProperty("--pane-width", `${width}px`);
        }
    }

    function wait_for_pane() {
        function start(resolve) {
            const el = document.querySelector(PANE_SELECTOR);
            if (el) {
                resolve(el);
                return;
            }
            new MutationObserver((records, obs) => {
                for (const record of records) {
                    for (const node of record.addedNodes) {
                        if (node.nodeType !== Node.ELEMENT_NODE) {
                            continue;
                        }
                        const found = node.matches(PANE_SELECTOR)
                        ? node
                        : node.querySelector(PANE_SELECTOR);
                        if (found) {
                            obs.disconnect();
                            resolve(found);
                            return;
                        }
                    }
                }
            }).observe(document.documentElement, { childList: true, subtree: true });
        }

        return new Promise((resolve, reject) => {
            try {
                start(resolve);
            } catch (e) {
                reject(e);
            }
        });
    }

    const el = await wait_for_pane();

    const saved_width = load_width();
    write_width(el, saved_width);

    let expected_width = saved_width || read_width(el);
    let was_dragging = false;

    new MutationObserver(() => {
        const is_dragging = el.getAttribute("data-dragging") === "true";
        const current = read_width(el);
        console.log("github file tree width:", current);

        if (is_dragging) {
            if (current !== null) {
                expected_width = current;
            }
        } else {
            if (was_dragging) {
                if (expected_width !== null) {
                    console.log("github file tree width (drag end), saving:", expected_width);
                    save_width(expected_width);
                }
            } else {
                if (expected_width !== null && current !== null && current !== expected_width) {
                    console.log("github file tree width (auto-reset detected), restoring:", expected_width);
                    write_width(el, expected_width);
                }
            }
        }
        was_dragging = is_dragging;

    }).observe(el, {
        attributes: true,
        attributeFilter: ["style"],
    });
})();

Example URLs

https://github.com/refined-github/refined-github/tree/main/source

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions