YouTube Logo Hover Menu

YouTubeロゴにホバーすると、履歴、後で見る、再生リスト、高評価動画に素早くアクセスできるメニューを表示します。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         YouTube Logo Hover Menu
// @name:en      YouTube Logo Hover Menu
// @namespace    https://www.tampermonkey.net/
// @version      2026227
// @description  YouTubeロゴにホバーすると、履歴、後で見る、再生リスト、高評価動画に素早くアクセスできるメニューを表示します。
// @description:en Adds a hover menu to the YouTube logo for quick access to history, watch later, playlists, and liked videos.
// @author       black lagoon
// @match        https://www.youtube.com/*
// @grant        GM_addStyle
// @license      MPL2.0
// ==/UserScript==

(function() {
    'use strict';

    const isJA = navigator.language.startsWith('ja');

    const MENU_ITEMS = [
        {
            id: 'history',
            label: isJA ? '履歴' : 'History',
            path: '/feed/history',
            d: 'M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z'
        },
        {
            id: 'watch-later',
            label: isJA ? '後で見る' : 'Watch Later',
            path: '/playlist?list=WL',
            d: 'M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zm4.2 14.2L11 13V7h1.5v5.2l4.5 2.7-.8 1.3z'
        },
        {
            id: 'playlists',
            label: isJA ? '再生リスト' : 'Playlists',
            path: '/feed/library',
            d: 'M22,7H2v1h20V7z M13,12H2v-1h11V12z M13,16H2v-1h11V16z M15,19v-8l7,4L15,19z'
        },
        {
            id: 'liked',
            label: isJA ? '高評価' : 'Liked',
            path: '/playlist?list=LL',
            d: 'M18.77,11h-4.23l1.52-4.94C16.38,5.03,15.54,4,14.38,4c-0.58,0-1.13,0.24-1.53,0.65L7,11H3v10h4h1h9.43 c1.06,0,1.98-0.67,2.26-1.68l1.29-4.73C21.35,13.41,20.41,11,18.77,11z M7,20H4v-8h3V20z M19.98,14.37l-1.29,4.73 C18.59,19.64,18.02,20,17.43,20H8v-8.61l5.83-5.97c0.15-0.15,0.35-0.23,0.55-0.23c0.41,0,0.72,0.37,0.6,0.77L13.46,11h1.08h4.23 c0.54,0,0.85,0.79,0.65,1.29L19.98,14.37z'
        }
    ];

    // --- スタイル適用 ---
    const buildIconStyle = (d) => {
        const svg = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'><path d='${d}'/></svg>`;
        return `url("data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}")`;
    };

    GM_addStyle(`
        #yt-hover-quick-menu {
            position: fixed;
            top: 48px;
            left: 16px;
            background-color: var(--yt-spec-menu-background) !important;
            border: 1px solid var(--yt-spec-10-percent-layer) !important;
            border-radius: 12px !important;
            box-shadow: 0 8px 24px rgba(0,0,0,0.2) !important;
            z-index: 2147483647;
            display: none;
            flex-direction: column;
            width: 220px;
            padding: 8px 0;
        }
        .yt-menu-link {
            display: flex !important;
            align-items: center !important;
            padding: 10px 16px 10px 52px !important;
            color: var(--yt-spec-text-primary) !important;
            text-decoration: none !important;
            font-size: 14px !important;
            font-family: "Roboto", "Arial", sans-serif !important;
            position: relative;
            transition: background 0.1s;
        }
        .yt-menu-link:hover {
            background-color: var(--yt-spec-10-percent-layer) !important;
        }
        .yt-menu-link::before {
            content: '';
            position: absolute;
            left: 16px;
            top: 50%;
            transform: translateY(-50%);
            width: 24px;
            height: 24px;
            background-size: contain;
            background-repeat: no-repeat;
            filter: var(--yt-spec-icon-inactive-contrast-filter) !important;
        }
        ${MENU_ITEMS.map(item => `
            .icon-${item.id}::before { background-image: ${buildIconStyle(item.d)}; }
        `).join('\n')}
    `);

    // --- メニュー生成 ---
    const menu = document.createElement('div');
    menu.id = 'yt-hover-quick-menu';

    MENU_ITEMS.forEach(item => {
        const a = document.createElement('a');
        a.href = item.path;
        a.className = `yt-menu-link icon-${item.id}`;
        a.textContent = item.label;
        menu.appendChild(a);
    });
    document.body.appendChild(menu);

    const handleMouseOver = (e) => {
        const logo = document.querySelector('ytd-topbar-logo-renderer');
        // ロゴコンテナ内、もしくはメニュー自体へのホバーを判定
        if ((logo && logo.contains(e.target))) {
            menu.style.display = 'flex';
        } else if (!menu.contains(e.target)) {
            menu.style.display = 'none';
        }
    };

    document.addEventListener('mouseover', handleMouseOver, { passive: true });
    menu.addEventListener('mouseleave', () => menu.style.display = 'none');

})();