feat: refine star toast — brand orange, idle trigger, 15s auto-hide

- Style: brand orange background with white text (visible on any bg)
- Trigger: every 5 copies OR after 10 minutes of inactivity on page
- Auto-hide: 15s (reset if toast re-triggers before expiry)
- Idle timer resets on each copy
This commit is contained in:
Samuel Berthe 2026-04-14 20:30:08 +02:00
parent 25418c5db2
commit a56d8cf2a4
No known key found for this signature in database
GPG key ID: 64863511FFBD0E3C

View file

@ -9,25 +9,22 @@ import { GITHUB_URL } from '../data/site';
aria-live="polite" aria-live="polite"
class="fixed bottom-6 right-6 z-50 hidden max-w-sm w-full" class="fixed bottom-6 right-6 z-50 hidden max-w-sm w-full"
> >
<div class="flex items-start gap-3 bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 rounded-xl shadow-lg px-4 py-3"> <div class="flex items-center gap-3 bg-brand rounded-xl shadow-xl px-4 py-3">
<svg class="w-4 h-4 text-yellow-500 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"> <svg class="w-4 h-4 text-white/80 flex-shrink-0" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" /> <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
</svg> </svg>
<div class="flex-1 min-w-0"> <p class="flex-1 text-sm text-white">
<p class="text-sm text-slate-700 dark:text-slate-200"> Useful? <a
Rule copied! If this saved you time, href={GITHUB_URL}
<a target="_blank"
href={GITHUB_URL} rel="noopener noreferrer"
target="_blank" class="font-semibold underline underline-offset-2 hover:no-underline transition-all"
rel="noopener noreferrer" >Star on GitHub</a> — it helps others discover it.
class="font-medium text-brand dark:text-brand-dark hover:underline" </p>
>star the project on GitHub</a>.
</p>
</div>
<button <button
id="star-toast-close" id="star-toast-close"
aria-label="Dismiss" aria-label="Dismiss"
class="flex-shrink-0 text-slate-400 hover:text-slate-600 dark:hover:text-slate-200 transition-colors" class="flex-shrink-0 text-white/60 hover:text-white transition-colors"
> >
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
@ -39,21 +36,18 @@ import { GITHUB_URL } from '../data/site';
<script> <script>
const COPY_COUNT_KEY = 'gh_star_copy_count'; const COPY_COUNT_KEY = 'gh_star_copy_count';
const SHOW_EVERY = 5; const SHOW_EVERY = 5;
const IDLE_MS = 10 * 60 * 1000; // 10 minutes
const toast = document.getElementById('star-toast'); const toast = document.getElementById('star-toast');
const closeBtn = document.getElementById('star-toast-close'); const closeBtn = document.getElementById('star-toast-close');
let autoHideTimer: ReturnType<typeof setTimeout> | null = null; let autoHideTimer: ReturnType<typeof setTimeout> | null = null;
let idleTimer: ReturnType<typeof setTimeout> | null = null;
function showToast() { function displayToast() {
if (!toast) return; if (!toast) return;
const count = (parseInt(sessionStorage.getItem(COPY_COUNT_KEY) ?? '0', 10) || 0) + 1;
sessionStorage.setItem(COPY_COUNT_KEY, String(count));
if (count % SHOW_EVERY !== 0) return;
if (autoHideTimer) clearTimeout(autoHideTimer); if (autoHideTimer) clearTimeout(autoHideTimer);
toast.classList.remove('hidden'); toast.classList.remove('hidden');
autoHideTimer = setTimeout(hideToast, 20000); autoHideTimer = setTimeout(hideToast, 15000);
} }
function hideToast() { function hideToast() {
@ -61,6 +55,24 @@ import { GITHUB_URL } from '../data/site';
if (autoHideTimer) { clearTimeout(autoHideTimer); autoHideTimer = null; } if (autoHideTimer) { clearTimeout(autoHideTimer); autoHideTimer = null; }
} }
function resetIdleTimer() {
if (idleTimer) clearTimeout(idleTimer);
idleTimer = setTimeout(displayToast, IDLE_MS);
}
function onCopy() {
// Increment counter and show every 5th copy
const count = (parseInt(sessionStorage.getItem(COPY_COUNT_KEY) ?? '0', 10) || 0) + 1;
sessionStorage.setItem(COPY_COUNT_KEY, String(count));
if (count % SHOW_EVERY === 0) displayToast();
// Reset the idle timer on each copy
resetIdleTimer();
}
closeBtn?.addEventListener('click', hideToast); closeBtn?.addEventListener('click', hideToast);
window.addEventListener('copy-success', showToast); window.addEventListener('copy-success', onCopy);
// Start idle timer on page load
resetIdleTimer();
</script> </script>