GitHub Actions - Scroll to Top Button

Adds a button on GitHub Actions pages to scroll to the top easily

2025-11-12 기준 버전입니다. 최신 버전을 확인하세요.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         GitHub Actions - Scroll to Top Button
// @namespace    https://github.com/
// @version      1.0
// @description  Adds a button on GitHub Actions pages to scroll to the top easily
// @author       chaoscreater
// @match        https://github.com/*/actions/runs/*/job/*
// @match        https://github.*.co.nz/*/*/actions/runs/*/job/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Check if current URL matches the @match patterns
    function shouldShowButton() {
        const url = window.location.href;
        // Match: https://github.com/*/actions/runs/*/job/*
        const pattern1 = /^https:\/\/github\.com\/[^/]+\/[^/]+\/actions\/runs\/[^/]+\/job\/[^/]+/;
        // Match: https://github.*.co.nz/*/*/actions/runs/*/job/*
        const pattern2 = /^https:\/\/github[^/]*\.co\.nz\/[^/]+\/[^/]+\/actions\/runs\/[^/]+\/job\/[^/]+/;
        return pattern1.test(url) || pattern2.test(url);
    }

    // Create the button
    const btn = document.createElement('button');
    btn.innerText = '⬆️ Top';
    Object.assign(btn.style, {
        position: 'fixed',
        bottom: '20px',
        left: '20px',
        padding: '8px 14px',
        fontSize: '14px',
        borderRadius: '6px',
        border: 'none',
        backgroundColor: '#2ea44f',
        color: '#fff',
        cursor: 'pointer',
        boxShadow: '0 2px 6px rgba(0,0,0,0.2)',
        zIndex: '9999',
        opacity: '0.8',
        transition: 'opacity 0.2s, transform 0.2s',
    });

    // Hover effect
    btn.addEventListener('mouseenter', () => {
        btn.style.opacity = '1';
        btn.style.transform = 'scale(1.05)';
    });
    btn.addEventListener('mouseleave', () => {
        btn.style.opacity = '0.8';
        btn.style.transform = 'scale(1.0)';
    });

    // Scroll to top on click
    btn.addEventListener('click', () => {
        window.scrollTo({ top: 0, behavior: 'smooth' });
    });

    // Update button visibility based on URL
    function updateButtonVisibility() {
        if (shouldShowButton()) {
            if (!btn.parentElement) {
                document.body.appendChild(btn);
            }
            btn.style.display = 'block';
        } else {
            btn.style.display = 'none';
        }
    }

    // Initial check
    updateButtonVisibility();

    // Monitor URL changes (GitHub uses client-side routing)
    let lastUrl = location.href;
    new MutationObserver(() => {
        const currentUrl = location.href;
        if (currentUrl !== lastUrl) {
            lastUrl = currentUrl;
            updateButtonVisibility();
        }
    }).observe(document, { subtree: true, childList: true });
})();