Feat: navigation par slides horizontaux
All checks were successful
Deploy / Deploy to Production (push) Successful in 14s

- Nouveau store slides.svelte.js : gestion de l'état des slides (activeIndex, pendingPath, chargement progressif)
- Réécriture du router : remplace navaid par une logique custom avec chargement de la slide initiale puis des autres en arrière-plan
- App.svelte : layout slides-wrapper avec translateX, transition 1000ms
- Header.svelte : menu 100% dynamique depuis slides.all (ordre et titres multilingues depuis Kirby)
- site/controllers/site.php : navigation exposée via site->pages()->listed() avec titres par langue, home prependue

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-02-19 12:38:07 +01:00
parent 614098baf6
commit 8e01cbe611
5 changed files with 241 additions and 174 deletions

View file

@ -1,27 +1,20 @@
<script>
import { navigation } from '@state/navigation.svelte'
import { locale } from '@state/locale.svelte'
import { page } from '@state/page.svelte'
import { navigateTo } from '@router'
import { slides } from '@state/slides.svelte'
import { slideTo } from '@router'
const isMenuOpen = $derived(navigation.isMenuOpen)
const currentLang = $derived(locale.current)
const currentPage = $derived(page.template || 'home')
const activeId = $derived(slides.active?.id ?? 'home')
const menuItems = $derived(slides.all.filter(s => s.id !== 'home'))
const translations = {
expertise: { fr: 'EXPERTISE', en: 'EXPERTISE' },
games: { fr: 'GAMES', en: 'GAMES' },
play: { fr: 'PLAY', en: 'PLAY' },
about: { fr: 'À PROPOS', en: 'ABOUT' },
blog: { fr: 'BLOG', en: 'BLOG' }
}
function t(key) {
return translations[key]?.[currentLang] || translations[key]?.fr || key
function getTitle(slide) {
return slide.titles?.[currentLang] || slide.title || slide.id
}
function handleNav(path) {
navigateTo(path)
slideTo(path)
}
function toggleMenu() {
@ -52,65 +45,19 @@
/>
</div>
<div
class="navbar-item clickable"
class:active={currentPage === 'expertise'}
style="visibility: {isMenuOpen ? 'hidden' : 'visible'};"
onclick={() => handleNav('/expertise')}
onkeypress={(e) => e.key === 'Enter' && handleNav('/expertise')}
role="button"
tabindex="0"
>
{t('expertise')}
</div>
<div
class="navbar-item clickable"
class:active={currentPage === 'portfolio'}
style="visibility: {isMenuOpen ? 'hidden' : 'visible'};"
onclick={() => handleNav('/portfolio')}
onkeypress={(e) => e.key === 'Enter' && handleNav('/portfolio')}
role="button"
tabindex="0"
>
{t('games')}
</div>
<div
class="navbar-item clickable"
class:active={currentPage === 'jouer'}
style="visibility: {isMenuOpen ? 'hidden' : 'visible'};"
onclick={() => handleNav('/jouer')}
onkeypress={(e) => e.key === 'Enter' && handleNav('/jouer')}
role="button"
tabindex="0"
>
{t('play')}
</div>
<div
class="navbar-item clickable"
class:active={currentPage === 'about'}
style="visibility: {isMenuOpen ? 'hidden' : 'visible'};"
onclick={() => handleNav('/a-propos')}
onkeypress={(e) => e.key === 'Enter' && handleNav('/a-propos')}
role="button"
tabindex="0"
>
{t('about')}
</div>
<div
class="navbar-item clickable"
class:active={currentPage === 'blog' || currentPage === 'article'}
style="visibility: {isMenuOpen ? 'hidden' : 'visible'};"
onclick={() => handleNav('/blog')}
onkeypress={(e) => e.key === 'Enter' && handleNav('/blog')}
role="button"
tabindex="0"
>
{t('blog')}
</div>
{#each menuItems as slide}
<div
class="navbar-item clickable"
class:active={activeId === slide.id}
style="visibility: {isMenuOpen ? 'hidden' : 'visible'};"
onclick={() => handleNav(slide.path)}
onkeypress={(e) => e.key === 'Enter' && handleNav(slide.path)}
role="button"
tabindex="0"
>
{getTitle(slide)}
</div>
{/each}
<div
class="clickable"