mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-08-05 00:47:42 +00:00
feat: browser-aware CTAs, tidier hero demo, comparison guides link
- Hero CTAs: the install buttons are compact (just the browser name) so all three fit one line; JS detects the visitor's browser and expands that one to the full "Add to X" call to action. Unknown browsers stay compact. - Hero demo: caption now sits directly under the two windows (absolutely positioned to the card cascade) instead of far below the tall scene. The scene keeps a fixed height that already fits the open popup, so the vertically centered hero never jumps when the popup toggles. - The background window now also shows a (non-interactive) extension icon, making it clear both browsers have KoalaSync installed. - Escape now also closes the demo popup. - Added a link from the comparison table to the fuller alternatives/guides hub, localized in all 15 languages. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -78,6 +78,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
}
|
||||
|
||||
// Highlight the CTA for the visitor's browser: it expands to the full
|
||||
// "Add to X" label while the others stay compact. Unknown browsers keep
|
||||
// all three compact.
|
||||
try {
|
||||
const ua = navigator.userAgent;
|
||||
let detected = null;
|
||||
if (/Firefox\//.test(ua) && !/Seamonkey\//.test(ua)) {
|
||||
detected = 'firefox';
|
||||
} else if (/Chrome\//.test(ua) || /Chromium\//.test(ua) || /Edg\//.test(ua) || /OPR\//.test(ua)) {
|
||||
detected = 'chrome';
|
||||
}
|
||||
if (detected) {
|
||||
const btn = document.querySelector('.btn-install[data-browser="' + detected + '"]');
|
||||
if (btn) btn.classList.add('is-detected');
|
||||
}
|
||||
} catch (_) { /* leave all buttons compact */ }
|
||||
|
||||
// Open collapsed section blocks when the URL directly targets them
|
||||
const hashCollapseMap = { '#faq': 'faq-collapse', '#self-hosting': 'selfhost-collapse' };
|
||||
const collapseId = hashCollapseMap[window.location.hash];
|
||||
@@ -809,6 +826,15 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
}
|
||||
|
||||
// Escape closes the popup as well
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key !== 'Escape') return;
|
||||
if (!scene.classList.contains('popup-open')) return;
|
||||
userTookOver = true;
|
||||
finishDemo();
|
||||
setPopupOpen(false);
|
||||
});
|
||||
|
||||
const runDemo = async () => {
|
||||
if (demoStarted || userTookOver || reduceMotion) return;
|
||||
demoStarted = true;
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "Fragen ausblenden",
|
||||
"SELF_SHOW_SETUP": "Setup-Anleitung anzeigen",
|
||||
"SELF_HIDE_SETUP": "Setup-Anleitung ausblenden",
|
||||
"HERO_TRUST": "Kostenlos · Open Source · Kein Account nötig"
|
||||
"HERO_TRUST": "Kostenlos · Open Source · Kein Account nötig",
|
||||
"COMP_MORE_GUIDES": "Ausführlicher Vergleich und weitere Alternativen"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "Hide questions",
|
||||
"SELF_SHOW_SETUP": "Show setup guide",
|
||||
"SELF_HIDE_SETUP": "Hide setup guide",
|
||||
"HERO_TRUST": "Free · Open source · No account needed"
|
||||
"HERO_TRUST": "Free · Open source · No account needed",
|
||||
"COMP_MORE_GUIDES": "Full comparison and more alternatives"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "Ocultar preguntas",
|
||||
"SELF_SHOW_SETUP": "Mostrar guía de instalación",
|
||||
"SELF_HIDE_SETUP": "Ocultar guía de instalación",
|
||||
"HERO_TRUST": "Gratis · Código abierto · Sin cuenta"
|
||||
"HERO_TRUST": "Gratis · Código abierto · Sin cuenta",
|
||||
"COMP_MORE_GUIDES": "Comparativa completa y más alternativas"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "Masquer les questions",
|
||||
"SELF_SHOW_SETUP": "Afficher le guide d'installation",
|
||||
"SELF_HIDE_SETUP": "Masquer le guide d'installation",
|
||||
"HERO_TRUST": "Gratuit · Open source · Sans compte"
|
||||
"HERO_TRUST": "Gratuit · Open source · Sans compte",
|
||||
"COMP_MORE_GUIDES": "Comparatif complet et autres alternatives"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "Nascondi le domande",
|
||||
"SELF_SHOW_SETUP": "Mostra la guida all'installazione",
|
||||
"SELF_HIDE_SETUP": "Nascondi la guida",
|
||||
"HERO_TRUST": "Gratuito · Open source · Senza account"
|
||||
"HERO_TRUST": "Gratuito · Open source · Senza account",
|
||||
"COMP_MORE_GUIDES": "Confronto completo e altre alternative"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "質問を隠す",
|
||||
"SELF_SHOW_SETUP": "セットアップガイドを表示",
|
||||
"SELF_HIDE_SETUP": "ガイドを隠す",
|
||||
"HERO_TRUST": "無料 · オープンソース · アカウント不要"
|
||||
"HERO_TRUST": "無料 · オープンソース · アカウント不要",
|
||||
"COMP_MORE_GUIDES": "詳しい比較とその他の選択肢"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "질문 숨기기",
|
||||
"SELF_SHOW_SETUP": "설치 가이드 보기",
|
||||
"SELF_HIDE_SETUP": "가이드 숨기기",
|
||||
"HERO_TRUST": "무료 · 오픈소스 · 계정 불필요"
|
||||
"HERO_TRUST": "무료 · 오픈소스 · 계정 불필요",
|
||||
"COMP_MORE_GUIDES": "전체 비교 및 다른 대안 보기"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "Vragen verbergen",
|
||||
"SELF_SHOW_SETUP": "Installatiehandleiding tonen",
|
||||
"SELF_HIDE_SETUP": "Handleiding verbergen",
|
||||
"HERO_TRUST": "Gratis · Open source · Geen account nodig"
|
||||
"HERO_TRUST": "Gratis · Open source · Geen account nodig",
|
||||
"COMP_MORE_GUIDES": "Volledige vergelijking en meer alternatieven"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "Ukryj pytania",
|
||||
"SELF_SHOW_SETUP": "Pokaż instrukcję instalacji",
|
||||
"SELF_HIDE_SETUP": "Ukryj instrukcję",
|
||||
"HERO_TRUST": "Za darmo · Open source · Bez konta"
|
||||
"HERO_TRUST": "Za darmo · Open source · Bez konta",
|
||||
"COMP_MORE_GUIDES": "Pełne porównanie i więcej alternatyw"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "Ocultar perguntas",
|
||||
"SELF_SHOW_SETUP": "Mostrar guia de configuração",
|
||||
"SELF_HIDE_SETUP": "Ocultar guia",
|
||||
"HERO_TRUST": "Grátis · Código aberto · Sem conta"
|
||||
"HERO_TRUST": "Grátis · Código aberto · Sem conta",
|
||||
"COMP_MORE_GUIDES": "Comparação completa e mais alternativas"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "Ocultar perguntas",
|
||||
"SELF_SHOW_SETUP": "Mostrar guia de configuração",
|
||||
"SELF_HIDE_SETUP": "Ocultar guia",
|
||||
"HERO_TRUST": "Grátis · Open source · Sem conta"
|
||||
"HERO_TRUST": "Grátis · Open source · Sem conta",
|
||||
"COMP_MORE_GUIDES": "Comparação completa e mais alternativas"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "Скрыть вопросы",
|
||||
"SELF_SHOW_SETUP": "Показать инструкцию по установке",
|
||||
"SELF_HIDE_SETUP": "Скрыть инструкцию",
|
||||
"HERO_TRUST": "Бесплатно · Открытый код · Без аккаунта"
|
||||
"HERO_TRUST": "Бесплатно · Открытый код · Без аккаунта",
|
||||
"COMP_MORE_GUIDES": "Полное сравнение и другие альтернативы"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "Soruları gizle",
|
||||
"SELF_SHOW_SETUP": "Kurulum rehberini göster",
|
||||
"SELF_HIDE_SETUP": "Rehberi gizle",
|
||||
"HERO_TRUST": "Ücretsiz · Açık kaynak · Hesap gerekmez"
|
||||
"HERO_TRUST": "Ücretsiz · Açık kaynak · Hesap gerekmez",
|
||||
"COMP_MORE_GUIDES": "Tam karşılaştırma ve diğer alternatifler"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "Приховати запитання",
|
||||
"SELF_SHOW_SETUP": "Показати інструкцію з налаштування",
|
||||
"SELF_HIDE_SETUP": "Приховати інструкцію",
|
||||
"HERO_TRUST": "Безкоштовно · Відкритий код · Без акаунта"
|
||||
"HERO_TRUST": "Безкоштовно · Відкритий код · Без акаунта",
|
||||
"COMP_MORE_GUIDES": "Повне порівняння та інші альтернативи"
|
||||
}
|
||||
|
||||
@@ -222,5 +222,6 @@
|
||||
"FAQ_HIDE_ALL": "收起问题",
|
||||
"SELF_SHOW_SETUP": "显示部署指南",
|
||||
"SELF_HIDE_SETUP": "收起指南",
|
||||
"HERO_TRUST": "免费 · 开源 · 无需账号"
|
||||
"HERO_TRUST": "免费 · 开源 · 无需账号",
|
||||
"COMP_MORE_GUIDES": "完整对比与更多替代方案"
|
||||
}
|
||||
|
||||
+62
-6
@@ -653,6 +653,21 @@ html.theme-light .koala-speech-bubble::after {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Install buttons: compact by default (just the browser name) so all three
|
||||
CTAs fit one line; the detected browser expands to the full call to action.
|
||||
The GitHub button stays compact always. */
|
||||
.btn-label-full { display: none; }
|
||||
|
||||
.btn-install:not(.is-detected),
|
||||
.btn-compact {
|
||||
padding: 0.62rem 1.05rem;
|
||||
font-size: 0.9rem;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.btn-install.is-detected .btn-label-short { display: none; }
|
||||
.btn-install.is-detected .btn-label-full { display: inline; }
|
||||
|
||||
.version-badge {
|
||||
display: inline-block;
|
||||
background: rgba(99, 102, 241, 0.1);
|
||||
@@ -3078,6 +3093,28 @@ html:not(.lang-de) [lang="de"] {
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
/* Link from the comparison table to the fuller guides/alternatives hub */
|
||||
.comparison-guides-link {
|
||||
text-align: center;
|
||||
margin: 2rem 0 0;
|
||||
}
|
||||
|
||||
.comparison-guides-link a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.45rem;
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
transition: gap 0.2s ease, opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.comparison-guides-link a:hover {
|
||||
gap: 0.7rem;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.table-footnotes:hover {
|
||||
opacity: 0.95;
|
||||
}
|
||||
@@ -3504,14 +3541,14 @@ header[id] {
|
||||
container-type: inline-size;
|
||||
}
|
||||
|
||||
/* Fixed scene height: stays below the left hero column's height so it never
|
||||
drives the grid row, and never changes when the popup toggles (no vertical
|
||||
jumping). The popup is bottom-anchored and simply grows upwards on open. */
|
||||
/* Fixed height that already fits the open popup, so toggling it never changes
|
||||
layout (the vertically centered hero never jumps). The caption is absolutely
|
||||
positioned right under the cards instead of after the tall scene, and the
|
||||
empty lower area is the invisible room the popup drops into. */
|
||||
.hero-demo-scene {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
height: max(calc(66cqw + 78px), 500px);
|
||||
height: max(calc(59cqw + 100px), 548px);
|
||||
}
|
||||
|
||||
/* While initializing, suppress all transitions so the popup can start closed
|
||||
@@ -3755,11 +3792,23 @@ header[id] {
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.hero-demo-scene:not(.popup-open) .demo-ext-launcher::after {
|
||||
.hero-demo-scene:not(.popup-open) .demo-ext-launcher:not(.demo-ext-static)::after {
|
||||
opacity: 1;
|
||||
animation: demoBlink 1.4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Card B shows the same extension icon, purely to signal the friend has it
|
||||
installed too. It is not interactive and does not blink or glow. */
|
||||
.demo-ext-static,
|
||||
.demo-ext-static:hover {
|
||||
cursor: default;
|
||||
border-color: rgba(255, 255, 255, 0.12);
|
||||
transform: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.demo-ext-static::after { display: none; }
|
||||
|
||||
/* Abstract "video" artwork with a slow cinematic pan/zoom while playing */
|
||||
.demo-video {
|
||||
position: relative;
|
||||
@@ -4023,7 +4072,14 @@ header[id] {
|
||||
}
|
||||
|
||||
/* Caption below the scene */
|
||||
/* Caption sits absolutely right below the card cascade (matching the cards'
|
||||
bottom edge, which scales with the container width), so the tall scene that
|
||||
reserves popup room does not push it far away. */
|
||||
.demo-hint {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: calc(59cqw + 82px);
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
font-size: 0.82rem;
|
||||
|
||||
+21
-10
@@ -300,17 +300,19 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="cta-group">
|
||||
<a href="https://chromewebstore.google.com/detail/koalasync/obbnmkmlaaddodakcbdljknjpagklifc" class="btn btn-primary">
|
||||
<img src="{{ASSET_PATH}}assets/chrome.svg" alt="Chrome" width="20" height="20">
|
||||
<span>{{ADD_TO_CHROME}}</span>
|
||||
<a href="https://chromewebstore.google.com/detail/koalasync/obbnmkmlaaddodakcbdljknjpagklifc" class="btn btn-primary btn-install" data-browser="chrome">
|
||||
<img src="{{ASSET_PATH}}assets/chrome.svg" alt="" width="20" height="20">
|
||||
<span class="btn-label-short">Chrome</span>
|
||||
<span class="btn-label-full">{{ADD_TO_CHROME}}</span>
|
||||
</a>
|
||||
<a href="https://addons.mozilla.org/de/firefox/addon/koalasync/" class="btn btn-firefox">
|
||||
<img src="{{ASSET_PATH}}assets/firefox.svg" alt="Firefox" width="20" height="20">
|
||||
<span>{{ADD_TO_FIREFOX}}</span>
|
||||
<a href="https://addons.mozilla.org/de/firefox/addon/koalasync/" class="btn btn-firefox btn-install" data-browser="firefox">
|
||||
<img src="{{ASSET_PATH}}assets/firefox.svg" alt="" width="20" height="20">
|
||||
<span class="btn-label-short">Firefox</span>
|
||||
<span class="btn-label-full">{{ADD_TO_FIREFOX}}</span>
|
||||
</a>
|
||||
<a href="https://github.com/Shik3i/KoalaSync/releases" target="_blank" rel="noopener" class="btn btn-secondary" style="display: inline-flex; align-items: center; gap: 8px;">
|
||||
<a href="https://github.com/Shik3i/KoalaSync/releases" target="_blank" rel="noopener" class="btn btn-secondary btn-compact" style="display: inline-flex; align-items: center; gap: 8px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="20" height="20" aria-hidden="true" style="display: block;"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
||||
GitHub Releases
|
||||
<span>GitHub Releases</span>
|
||||
</a>
|
||||
</div>
|
||||
<p class="cta-trust">{{HERO_TRUST}}</p>
|
||||
@@ -387,6 +389,9 @@
|
||||
<span class="demo-tab-dots" aria-hidden="true"><i></i><i></i><i></i></span>
|
||||
<span class="demo-tab-title"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="11" height="11" aria-hidden="true"><rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8M12 17v4"/></svg> <span class="demo-title-text-ep1">Stranger Things - S4E1</span></span>
|
||||
<span class="demo-tab-user demo-user-b">🐶 HappyDog</span>
|
||||
<span class="demo-ext-launcher demo-ext-static" aria-hidden="true" title="KoalaSync is installed here too">
|
||||
<img src="{{ASSET_PATH}}assets/NewLogoIcon.webp" alt="" width="16" height="16" loading="eager" decoding="async">
|
||||
</span>
|
||||
</div>
|
||||
<div class="demo-video">
|
||||
<div class="demo-video-art" aria-hidden="true"></div>
|
||||
@@ -730,8 +735,8 @@
|
||||
<div class="demo-cursor" id="demo-cursor" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 2l13 11.5-6 .7 3.4 6.3-2.6 1.4-3.4-6.4L5 19.5z" fill="#f8fafc" stroke="#0f172a" stroke-width="1.4" stroke-linejoin="round"/></svg>
|
||||
</div>
|
||||
<p class="demo-hint" id="demo-hint">{{DEMO_HINT}}</p>
|
||||
</div>
|
||||
<p class="demo-hint" id="demo-hint">{{DEMO_HINT}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -964,11 +969,17 @@
|
||||
<a href="https://www.teleparty.com/privacy" target="_blank" rel="noopener noreferrer">teleparty.com/privacy</a>
|
||||
</p>
|
||||
<p id="footnote-3">
|
||||
<sup>[3]</sup>
|
||||
<sup>[3]</sup>
|
||||
<span>{{COMP_FOOTNOTE_4}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="comparison-guides-link" data-reveal>
|
||||
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives">
|
||||
<span>{{COMP_MORE_GUIDES}}</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="15" height="15" aria-hidden="true"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user