From 1342281bef9b52758d502ae855b2faa54d0d3596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enes=20Yak=C4=B1=C5=9Ft=C4=B1r?= Date: Sat, 29 Aug 2026 22:43:55 +0300 Subject: [PATCH] fix(a11y): remove repetitive card titles, clean date buttons & simplify search header v1.2.2 --- client.js | 118 ++++++++++----------------------------------------- package.json | 2 +- style.css | 87 ++++++++++++------------------------- 3 files changed, 49 insertions(+), 158 deletions(-) diff --git a/client.js b/client.js index 36429cb..161d7b8 100644 --- a/client.js +++ b/client.js @@ -1400,7 +1400,8 @@ // -------------------------------------------------------------------------- // -------------------------------------------------------------------------- // -------------------------------------------------------------------------- - // 8. YOUTUBE-IDENTICAL SEARCH BAR & VOICE MODAL ENGINE (v1.2.1) + // -------------------------------------------------------------------------- + // 8. YOUTUBE-IDENTICAL SEARCH BAR & VOICE MODAL ENGINE (v1.2.2) // -------------------------------------------------------------------------- var activeVoiceRecognition = null; var isVoiceListeningActive = false; @@ -1604,6 +1605,7 @@ function transformToYouTubeSearchBar(searchInp, searchContainer) { if (searchInp.hasAttribute('data-yaktube-yt-styled')) return; searchInp.setAttribute('data-yaktube-yt-styled', 'true'); + searchInp.setAttribute('aria-label', getInstanceName() + ' Video Arama'); // 1. Back button for Mobile Navigation (←) var backBtn = searchContainer.querySelector('.yaktube-search-back-btn'); @@ -1611,8 +1613,8 @@ backBtn = document.createElement('button'); backBtn.type = 'button'; backBtn.className = 'yaktube-search-back-btn'; - backBtn.setAttribute('aria-label', 'Aramadan Çık (Geri)'); - backBtn.setAttribute('title', 'Aramadan Çık (Geri)'); + backBtn.setAttribute('aria-label', 'Aramadan Çık'); + backBtn.setAttribute('title', 'Aramadan Çık'); backBtn.innerHTML = '←'; searchContainer.prepend(backBtn); @@ -1638,18 +1640,10 @@ var clearBtn = document.createElement('button'); clearBtn.type = 'button'; clearBtn.className = 'yaktube-clear-search-btn'; - clearBtn.setAttribute('aria-label', 'Arama Metnini Temizle (Escape)'); + clearBtn.setAttribute('aria-label', 'Arama Metnini Temizle'); clearBtn.innerHTML = '✕'; pillWrapper.appendChild(clearBtn); - // Add Search Submit Button (🔍) - var submitBtn = document.createElement('button'); - submitBtn.type = 'submit'; - submitBtn.className = 'yaktube-search-submit-btn'; - submitBtn.setAttribute('aria-label', 'Ara'); - submitBtn.innerHTML = '🔍'; - pillWrapper.appendChild(submitBtn); - function updateClearState() { if (searchInp.value && searchInp.value.trim().length > 0) { clearBtn.style.display = 'inline-flex'; @@ -1676,21 +1670,9 @@ searchInp.focus(); announce('Arama kutusu temizlendi.'); }); - - submitBtn.addEventListener('click', function (e) { - var query = (searchInp.value || '').trim(); - if (query) { - var form = searchInp.closest('form'); - if (form) { - form.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true })); - } else { - window.location.href = '/search/videos?search=' + encodeURIComponent(query); - } - } - }); } - // 3. YouTube Circular Voice Button (🎙️) Beside the Pill Box + // 3. Single YouTube Circular Voice Button (🎙️) Beside Search Box var voiceBtn = searchContainer.querySelector('.yaktube-voice-search-btn'); if (!voiceBtn) { voiceBtn = document.createElement('button'); @@ -1725,67 +1707,7 @@ }); } - function injectMobileSearchTrigger() { - var headerRight = - document.querySelector('my-header .header-right') || - document.querySelector('my-header .buttons-container') || - document.querySelector('my-header .user-menu'); - if (!headerRight) return; - - var triggerBtn = headerRight.querySelector('#yaktube-mobile-search-open-btn'); - if (!triggerBtn) { - triggerBtn = document.createElement('button'); - triggerBtn.id = 'yaktube-mobile-search-open-btn'; - triggerBtn.type = 'button'; - triggerBtn.className = 'yaktube-mobile-search-trigger'; - triggerBtn.setAttribute('aria-label', 'Aramayı Aç'); - triggerBtn.setAttribute('title', 'Aramayı Aç'); - triggerBtn.innerHTML = '🔍'; - triggerBtn.style.cssText = - 'background: transparent; color: #fff; border: none; font-size: 18px; width: 38px; height: 38px; border-radius: 50%; display: none; align-items: center; justify-content: center; cursor: pointer; margin-right: 4px;'; - headerRight.prepend(triggerBtn); - - triggerBtn.addEventListener('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - document.body.classList.add('yaktube-mobile-search-active'); - var searchInp = document.querySelector( - 'my-search-typeahead input, my-header input[type="search"], input[type="search"]' - ); - if (searchInp) { - searchInp.focus(); - } - announce('Arama ekranı açıldı.'); - }); - } - - var mobileVoiceTrigger = headerRight.querySelector('#yaktube-mobile-voice-open-btn'); - if (!mobileVoiceTrigger) { - mobileVoiceTrigger = document.createElement('button'); - mobileVoiceTrigger.id = 'yaktube-mobile-voice-open-btn'; - mobileVoiceTrigger.type = 'button'; - mobileVoiceTrigger.className = 'yaktube-mobile-search-trigger'; - mobileVoiceTrigger.setAttribute('aria-label', 'Sesli Arama'); - mobileVoiceTrigger.setAttribute('title', 'Sesli Arama'); - mobileVoiceTrigger.innerHTML = '🎙️'; - mobileVoiceTrigger.style.cssText = - 'background: transparent; color: #fff; border: none; font-size: 18px; width: 38px; height: 38px; border-radius: 50%; display: none; align-items: center; justify-content: center; cursor: pointer; margin-right: 4px;'; - headerRight.insertBefore(mobileVoiceTrigger, triggerBtn.nextSibling); - - mobileVoiceTrigger.addEventListener('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - var searchInp = document.querySelector( - 'my-search-typeahead input, my-header input[type="search"], input[type="search"]' - ); - openYouTubeVoiceModal(searchInp); - }); - } - } - function injectSearchEnhancements() { - injectMobileSearchTrigger(); - var searchContainers = document.querySelectorAll( 'my-search-typeahead, .search-container, .header-search, my-header .search' ); @@ -1796,16 +1718,21 @@ } }); - var headerInputs = document.querySelectorAll('my-header input'); - headerInputs.forEach(function (inp) { - var parent = inp.closest('my-search-typeahead') || inp.parentElement; - if ( - parent && - (inp.type === 'search' || - inp.type === 'text' || - (inp.placeholder && inp.placeholder.toLowerCase().includes('ara'))) - ) { - transformToYouTubeSearchBar(inp, parent); + // Clean up repetitive card titles and strange relative date buttons + document.querySelectorAll('my-video-miniature, .video-miniature').forEach(function (card) { + // 1. Hide duplicate thumbnail links from screen reader so title link is read ONCE + var thumbLink = card.querySelector('a.thumbnail-link, .video-thumbnail a, a.thumbnail'); + if (thumbLink && !thumbLink.hasAttribute('aria-hidden')) { + thumbLink.setAttribute('aria-hidden', 'true'); + thumbLink.setAttribute('tabindex', '-1'); + } + + // 2. Clean up date buttons (e.g. "Bu tarih birimini ... olarak değiştir") + var dateBtn = card.querySelector('.video-date-line button, .video-date button, button[title*="tarih"]'); + if (dateBtn && !dateBtn.hasAttribute('data-cleaned')) { + dateBtn.setAttribute('data-cleaned', 'true'); + var dateText = dateBtn.textContent.trim(); + dateBtn.setAttribute('aria-label', dateText); } }); } @@ -1842,7 +1769,6 @@ // / : Focus Search Input else if (e.key === '/' && !isInputActive && !e.ctrlKey && !e.metaKey) { e.preventDefault(); - document.body.classList.add('yaktube-mobile-search-active'); var searchInp = document.querySelector( 'my-search-typeahead input, my-header input[type="search"], input[type="search"]' ); diff --git a/package.json b/package.json index 7d466b4..cde74e4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "peertube-plugin-yaktube-ondemand", - "version": "1.2.1", + "version": "1.2.2", "description": "Accessible On-Demand YouTube Import, Live Streams, Smart Recommendations and A11y Engine for PeerTube", "main": "main.js", "clientScripts": [ diff --git a/style.css b/style.css index 093bb50..76a3007 100644 --- a/style.css +++ b/style.css @@ -408,29 +408,20 @@ my-header .action-buttons { /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -/* YOUTUBE-STYLE SEARCH BAR & VOICE SEARCH MODAL (v1.2.1) */ +/* -------------------------------------------------------------------------- */ +/* YOUTUBE-STYLE SEARCH BAR & VOICE SEARCH MODAL (v1.2.2 - A11y Optimized) */ /* -------------------------------------------------------------------------- */ -/* Desktop & Common Pill Styling */ -@media (min-width: 769px) { - my-search-typeahead, - .search-container, - .header-search { - display: flex !important; - align-items: center !important; - position: relative !important; - width: 100% !important; - max-width: 580px !important; - margin: 0 auto !important; - } - - .yaktube-search-back-btn { - display: none !important; - } - - .yaktube-mobile-search-trigger { - display: none !important; - } +/* Header Search Container Pill Styling */ +my-search-typeahead, +.search-container, +.header-search { + display: flex !important; + align-items: center !important; + position: relative !important; + width: 100% !important; + max-width: 580px !important; + margin: 0 auto !important; } .yaktube-search-pill-wrapper { @@ -439,7 +430,7 @@ my-header .action-buttons { background: #121212 !important; border: 1px solid #303030 !important; border-radius: 40px !important; - padding: 2px 6px 2px 14px !important; + padding: 2px 10px 2px 14px !important; transition: all 0.2s ease !important; width: 100% !important; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.4) !important; @@ -493,28 +484,6 @@ my-header .action-buttons { color: #fff !important; } -/* Search Submit Button on Right of Pill */ -.yaktube-search-submit-btn { - background: #222222 !important; - color: #f1f1f1 !important; - border: none !important; - border-left: 1px solid #303030 !important; - border-radius: 0 40px 40px 0 !important; - padding: 8px 18px !important; - cursor: pointer !important; - display: inline-flex !important; - align-items: center !important; - justify-content: center !important; - font-size: 14px !important; - transition: all 0.2s ease !important; - margin: -2px -6px -2px 0 !important; -} - -.yaktube-search-submit-btn:hover { - background: #272727 !important; - color: #ff8f37 !important; -} - /* YouTube Circular Voice Button Beside Search Box */ .yaktube-voice-search-btn { background: #1f1f1f !important; @@ -528,7 +497,7 @@ my-header .action-buttons { justify-content: center !important; font-size: 18px !important; cursor: pointer !important; - margin-left: 10px !important; + margin-left: 8px !important; transition: all 0.25s ease !important; flex-shrink: 0 !important; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important; @@ -541,6 +510,16 @@ my-header .action-buttons { transform: scale(1.06) !important; } +/* Hide back button on desktop */ +@media (min-width: 769px) { + .yaktube-search-back-btn { + display: none !important; + } + .yaktube-mobile-search-trigger { + display: none !important; + } +} + /* YouTube-Style Voice Search Modal Overlay */ .yaktube-voice-modal-overlay { position: fixed !important; @@ -688,27 +667,13 @@ my-header .action-buttons { margin-top: 10px !important; } -/* -------------------------------------------------------------------------- */ -/* MOBILE SEARCH OVERLAY MODE (< 768px) */ -/* -------------------------------------------------------------------------- */ +/* Mobile Search Overlay (< 768px) */ @media (max-width: 768px) { - /* Default Mobile State: Hide Full Search Input */ body:not(.yaktube-mobile-search-active) my-search-typeahead, - body:not(.yaktube-mobile-search-active) .search-container, - body:not(.yaktube-mobile-search-active) .header-search { + body:not(.yaktube-mobile-search-active) .search-container { display: none !important; } - .yaktube-mobile-search-trigger { - display: inline-flex !important; - } - - /* Active Mobile Search Overlay: Full Width Bar */ - body.yaktube-mobile-search-active my-header { - padding: 0 8px !important; - position: relative !important; - } - body.yaktube-mobile-search-active my-header .header-left, body.yaktube-mobile-search-active my-header .header-right, body.yaktube-mobile-search-active my-header .user-menu,