✨ feat(assets/reserve.js): Ajoute une fonctionnalité d'accessibilité avec synthèse vocale.
This commit is contained in:
@@ -58,6 +58,56 @@ const toggleSentry = async (status) => {
|
||||
} catch (e) { console.warn("Sentry error", e); }
|
||||
};
|
||||
|
||||
// --- UI : ACCESSIBILITÉ (Text-to-Speech) ---
|
||||
const initAccessibility = () => {
|
||||
if (document.getElementById('accessibility-toggle')) return;
|
||||
|
||||
const btn = document.createElement('button');
|
||||
btn.id = 'accessibility-toggle';
|
||||
// Positionné en bas à gauche, fond gris ardoise par défaut
|
||||
btn.className = `
|
||||
fixed bottom-24 left-8 z-50 p-4
|
||||
rounded-2xl shadow-xl border-2 border-white/10
|
||||
transition-all duration-300 hover:scale-110 active:scale-95
|
||||
`;
|
||||
|
||||
const updateBtnStyle = () => {
|
||||
const isActive = localStorage.getItem('ldk_tts_active') === 'true';
|
||||
btn.innerHTML = isActive ? '🔊' : '🔇';
|
||||
btn.classList.toggle('bg-[#f39e36]', isActive); // Orange si actif
|
||||
btn.classList.toggle('bg-slate-900', !isActive); // Noir si inactif
|
||||
btn.classList.toggle('text-white', true);
|
||||
};
|
||||
|
||||
updateBtnStyle();
|
||||
document.body.appendChild(btn);
|
||||
|
||||
btn.onclick = () => {
|
||||
const currentState = localStorage.getItem('ldk_tts_active') === 'true';
|
||||
localStorage.setItem('ldk_tts_active', !currentState);
|
||||
updateBtnStyle();
|
||||
if (currentState) window.speechSynthesis.cancel();
|
||||
};
|
||||
|
||||
// Écouteur global sur le document pour la lecture au clic
|
||||
document.addEventListener('click', (e) => {
|
||||
if (localStorage.getItem('ldk_tts_active') !== 'true') return;
|
||||
|
||||
const target = e.target.closest('p, h1, h2, h3, h4, span, label, li');
|
||||
if (target && target.innerText.trim().length > 0) {
|
||||
window.speechSynthesis.cancel();
|
||||
const utterance = new SpeechSynthesisUtterance(target.innerText);
|
||||
utterance.lang = 'fr-FR';
|
||||
|
||||
// Feedback visuel Ludik Event
|
||||
target.classList.add('outline', 'outline-2', 'outline-[#f39e36]', 'outline-offset-2');
|
||||
setTimeout(() => target.classList.remove('outline', 'outline-2', 'outline-[#f39e36]', 'outline-offset-2'), 1200);
|
||||
|
||||
window.speechSynthesis.speak(utterance);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// --- UI : LOADERS & IMAGES ---
|
||||
const initImageLoader = () => {
|
||||
const images = document.querySelectorAll('main img:not(.loaded)');
|
||||
@@ -118,14 +168,9 @@ const initBackToTop = () => {
|
||||
|
||||
const btn = document.createElement('button');
|
||||
btn.id = 'back-to-top';
|
||||
|
||||
// Modification :
|
||||
// 1. bottom-24 au lieu de bottom-8 pour laisser de la place aux cookies
|
||||
// 2. bg-[#f39e36] pour respecter ta couleur orange
|
||||
// 3. hover:bg-[#fc0e50] pour le rappel rose au survol
|
||||
btn.className = `
|
||||
fixed bottom-24 right-8 z-50 p-4
|
||||
bg-[#f39e36] text-white rounded-2xl shadow-[0_10px_25px_-5px_rgba(243,158,54,0.4)]
|
||||
bg-[#f39e36] text-white rounded-2xl shadow-xl
|
||||
border-2 border-white/20 opacity-0 translate-y-10
|
||||
pointer-events-none transition-all duration-500
|
||||
hover:bg-[#fc0e50] hover:-translate-y-2 group
|
||||
@@ -141,22 +186,15 @@ const initBackToTop = () => {
|
||||
|
||||
const handleScroll = () => {
|
||||
const isVisible = window.scrollY > 400;
|
||||
if (isVisible) {
|
||||
btn.classList.replace('opacity-0', 'opacity-100');
|
||||
btn.classList.replace('translate-y-10', 'translate-y-0');
|
||||
btn.classList.remove('pointer-events-none');
|
||||
} else {
|
||||
btn.classList.replace('opacity-100', 'opacity-0');
|
||||
btn.classList.replace('translate-y-0', 'translate-y-10');
|
||||
btn.classList.add('pointer-events-none');
|
||||
}
|
||||
btn.classList.toggle('opacity-100', isVisible);
|
||||
btn.classList.toggle('translate-y-0', isVisible);
|
||||
btn.classList.toggle('opacity-0', !isVisible);
|
||||
btn.classList.toggle('translate-y-10', !isVisible);
|
||||
btn.classList.toggle('pointer-events-none', !isVisible);
|
||||
};
|
||||
|
||||
window.addEventListener('scroll', handleScroll, { passive: true });
|
||||
|
||||
btn.onclick = () => {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
btn.onclick = () => window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
// --- LOGIQUE MÉTIER ---
|
||||
@@ -228,6 +266,7 @@ document.addEventListener('turbo:load', () => {
|
||||
initVitals();
|
||||
initImageLoader();
|
||||
initBackToTop();
|
||||
initAccessibility();
|
||||
initMobileMenu();
|
||||
initRegisterLogic();
|
||||
initCatalogueSearch();
|
||||
|
||||
Reference in New Issue
Block a user