SPB Git

spb/sorti-ka

Public

Toutes les sorties et tous les événements du Québec, un seul endroit — 7 connecteurs, fiches SSR, design Groupe KA.

Barre de navigation mobile commune Groupe KA (KA Tabbar v1)

Pilule flottante fixe en bas (standard ka-ui/nav, version vanilla inline) :
Découvrir · Recherche · Carte · Favoris, accent magenta signature, safe-area
iOS, micro-interactions. Recherche = retour accueil + focus du champ central ;
Carte = toutes les sorties sur la carte (drapeau state.mapAll one-shot dans
isFiltering, remis à zéro à toute navigation hors tabbar).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Aug 25, 2026) parent 318cada Browse files

1 changed file +102 −1

Unified Split
modified frontend/index.html +102 −1
@@ -713,6 +713,48 @@ html.ka-menu-locked,html.ka-menu-locked body{overflow:hidden}
713 713
714 #ssr{display:none} 714 #ssr{display:none}
715 .hidden{display:none!important} 715 .hidden{display:none!important}
716+
717+/* ============================================================
718+ KA Tabbar v1 — barre de navigation mobile commune Groupe KA
719+ (canonique : ka-ui.git/nav/ka-tabbar.css — accent magenta via
720+ var(--accent) du site) ============================================ */
721+.ka-tabbar{display:none}
722+@media (max-width:760px){
723+ .ka-tabbar{
724+ --ktb-bg:rgba(250,249,245,.94);
725+ --ktb-ink:var(--ink,#16191a);
726+ --ktb-dim:var(--ink-3,#70756d);
727+ --ktb-accent:var(--accent,#d6336c);
728+ --ktb-line:var(--hairline-strong,rgba(20,24,20,.16));
729+ --ktb-shadow:0 10px 30px rgba(20,24,20,.16),0 2px 6px rgba(20,24,20,.07);
730+ position:fixed;left:max(12px,env(safe-area-inset-left));right:max(12px,env(safe-area-inset-right));
731+ bottom:calc(10px + env(safe-area-inset-bottom));z-index:var(--z-bottombar,600);
732+ display:grid;grid-auto-flow:column;grid-auto-columns:1fr;max-width:440px;margin-inline:auto;
733+ padding:5px;background:var(--ktb-bg);
734+ -webkit-backdrop-filter:blur(14px) saturate(1.1);backdrop-filter:blur(14px) saturate(1.1);
735+ border:1px solid var(--ktb-line);border-radius:18px;box-shadow:var(--ktb-shadow)}
736+ .ka-tabbar a,.ka-tabbar button{appearance:none;background:none;border:0;cursor:pointer;
737+ display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
738+ min-height:50px;padding:6px 2px 5px;border-radius:13px;
739+ font-family:var(--font-display,inherit);font-size:10px;font-weight:650;letter-spacing:.01em;
740+ line-height:1;color:var(--ktb-dim);text-decoration:none;-webkit-tap-highlight-color:transparent;
741+ transition:color .15s ease}
742+ .ka-tabbar svg{display:block;transition:transform .15s ease}
743+ .ka-tabbar a:active svg,.ka-tabbar button:active svg{transform:translateY(1px) scale(.9)}
744+ .ka-tabbar .active{color:var(--ktb-active-label,var(--ktb-ink))}
745+ .ka-tabbar .active svg{color:var(--ktb-accent);animation:ktb-pop .25s ease}
746+ .ka-tabbar .active::after{content:"";width:16px;height:2.5px;border-radius:2px;
747+ background:var(--ktb-accent);animation:ktb-under .22s ease}
748+ body:has(.ka-tabbar){padding-bottom:calc(84px + env(safe-area-inset-bottom))}
749+ body:has(.ka-tabbar) .kaa-btn.kaa-btn{bottom:calc(88px + env(safe-area-inset-bottom,0px));right:14px}
750+ body:has(.ka-tabbar) .kaa-panel.kaa-panel:not(.kaa-full){bottom:calc(154px + env(safe-area-inset-bottom,0px))}
751+}
752+@keyframes ktb-under{from{transform:scaleX(0);opacity:0}}
753+@keyframes ktb-pop{40%{transform:translateY(-2px)}}
754+@media (prefers-reduced-motion:reduce){
755+ .ka-tabbar svg{transition:none}
756+ .ka-tabbar .active svg,.ka-tabbar .active::after{animation:none}
757+}
716 </style> 758 </style>
717 </head> 759 </head>
718 <body> 760 <body>
@@ -1229,7 +1271,8 @@ function plusDays(n){
1229 } 1271 }
1230 function isFiltering(){ 1272 function isFiltering(){
1231 return !!(state.q || state.region || state.category || state.free 1273 return !!(state.q || state.region || state.category || state.free
1232− || state.from || state.to || state.near); 1274+ || state.from || state.to || state.near
1275+ || state.mapAll); // onglet Carte (KA Tabbar) : résultats sans filtre
1233 } 1276 }
1234 function params(){ 1277 function params(){
1235 const p = new URLSearchParams(); 1278 const p = new URLSearchParams();
@@ -2773,5 +2816,63 @@ init();
2773 </script> 2816 </script>
2774 <script>window.KA_AGENT={site:"sorti-ka"}</script> 2817 <script>window.KA_AGENT={site:"sorti-ka"}</script>
2775 <script src="/ka-agent.js" defer></script> 2818 <script src="/ka-agent.js" defer></script>
2819+
2820+<!-- ======== KA Tabbar v1 — navigation mobile commune Groupe KA (ka-ui/nav) ======== -->
2821+<nav class="ka-tabbar" id="ka-tabbar" aria-label="Navigation mobile">
2822+ <a data-nav data-tab="decouvrir" href="/"><svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2.2 5-4.8 2 2.2-5 4.8-2z"/></svg>Découvrir</a>
2823+ <button type="button" data-tab="recherche" id="ktb-search"><svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20.5 20.5-4.2-4.2"/></svg>Recherche</button>
2824+ <button type="button" data-tab="carte" id="ktb-carte"><svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 21s-7-5.6-7-11a7 7 0 0 1 14 0c0 5.4-7 11-7 11z"/><circle cx="12" cy="10" r="2.6"/></svg>Carte</button>
2825+ <a data-nav data-tab="favoris" href="/favoris"><svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20.5S4.5 15.8 2.6 11.4A5.3 5.3 0 0 1 12 6.6a5.3 5.3 0 0 1 9.4 4.8C19.5 15.8 12 20.5 12 20.5z"/></svg>Favoris</a>
2826+</nav>
2827+<script>
2828+/* KA Tabbar : liaisons (routeur maison data-nav + actions locales) */
2829+(function(){
2830+ const bar = document.getElementById("ka-tabbar");
2831+ bindNav(bar); // les <a data-nav> passent par le routeur SPA
2832+
2833+ function ktbSync(){
2834+ const p = location.pathname;
2835+ const mapOn = !$("results").classList.contains("hidden")
2836+ && !$("mapwrap").classList.contains("hidden");
2837+ let k = null;
2838+ if(p === "/favoris") k = "favoris";
2839+ else if(p === "/" || p.startsWith("/region/") || p.startsWith("/categorie/")
2840+ || p.startsWith("/evenement/")) k = mapOn ? "carte" : "decouvrir";
2841+ bar.querySelectorAll("[data-tab]").forEach(b =>
2842+ b.classList.toggle("active", b.dataset.tab === k));
2843+ }
2844+
2845+ /* Recherche : accueil + focus du champ central */
2846+ $("ktb-search").onclick = () => {
2847+ const wasMap = state.mapAll;
2848+ state.mapAll = false;
2849+ if(location.pathname !== "/") go("/");
2850+ else if(wasMap) load();
2851+ window.scrollTo({top:0, behavior:"smooth"});
2852+ setTimeout(() => $("q").focus({preventScroll:true}), 60);
2853+ setTimeout(ktbSync, 80);
2854+ };
2855+
2856+ /* Carte : toutes les sorties sur la carte (vue résultats forcée) */
2857+ $("ktb-carte").onclick = () => {
2858+ state.mapAll = true;
2859+ if(location.pathname !== "/") go("/");
2860+ else load();
2861+ setView("map");
2862+ setTimeout(() => $("results").scrollIntoView({behavior:"smooth", block:"start"}), 120);
2863+ setTimeout(ktbSync, 150);
2864+ };
2865+
2866+ /* toute navigation hors tabbar sort du mode carte-de-tout (one-shot) */
2867+ document.addEventListener("click", e => {
2868+ const a = e.target.closest && e.target.closest("a[data-nav]");
2869+ if(a && !bar.contains(a)) state.mapAll = false;
2870+ setTimeout(ktbSync, 80);
2871+ }, true);
2872+ window.addEventListener("popstate", () => { state.mapAll = false; setTimeout(ktbSync, 80); });
2873+
2874+ ktbSync();
2875+})();
2876+</script>
2776 </body> 2877 </body>
2777 </html> 2878 </html>
2778 2879
Menu

Theme