Fix: navigation sous-pages blog/white-papers + singleSlug
All checks were successful
Deploy / Deploy to Production (push) Successful in 25s

- App.svelte : flèches clavier bloquées sur sous-page (ArrowLeft → history.back())
- Blog/WhitePapers : reset de articleData/itemData après 1100ms (post-transition)
  pour éviter le flash pendant l'animation de changement de slide
- WhitePapers : singleSlug jamais resetté (pré-affiché à l'arrivée sur la slide)
- WhitePapers : $effect sur isActive pour replaceState + openItem si itemData null
- WhitePapers/Blog : handlePopState ignore les popstate hors de la page courante

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-03-19 07:36:43 +01:00
parent 9f8854efa5
commit fcca068868
3 changed files with 38 additions and 4 deletions

View file

@ -58,10 +58,22 @@
window.addEventListener('resize', handleResize) window.addEventListener('resize', handleResize)
const handleKeydown = (e) => { const handleKeydown = (e) => {
if (e.key !== 'ArrowRight' && e.key !== 'ArrowLeft') return
// Si on est sur une sous-page (ex: /livres-blancs/slug), ne pas changer de slide
const activePath = slides.active?.path ?? ''
const currentPath = window.location.pathname.replace(/^\/en/, '') || '/'
const isSubPage = activePath && currentPath.startsWith(activePath + '/')
if (isSubPage) {
if (e.key === 'ArrowLeft') history.back()
return
}
if (e.key === 'ArrowRight') { if (e.key === 'ArrowRight') {
const next = slides.all[slides.activeIndex + 1] const next = slides.all[slides.activeIndex + 1]
if (next) slideTo(next.path) if (next) slideTo(next.path)
} else if (e.key === 'ArrowLeft') { } else {
const prev = slides.all[slides.activeIndex - 1] const prev = slides.all[slides.activeIndex - 1]
if (prev) slideTo(prev.path) if (prev) slideTo(prev.path)
} }

View file

@ -95,10 +95,11 @@
} }
}) })
// Reset article view when leaving the blog slide // Reset après la fin de la transition de slide (1100ms) pour éviter le flash
$effect(() => { $effect(() => {
if (!isActive && articleData) { if (!isActive && articleData) {
articleData = null const timer = setTimeout(() => { articleData = null }, 1100)
return () => clearTimeout(timer)
} }
}) })
</script> </script>

View file

@ -63,6 +63,9 @@
function handlePopState() { function handlePopState() {
if (!isActive) return if (!isActive) return
// Si l'URL n'appartient plus à ce slide, le router gère — on ne touche à rien
const onThisPage = window.location.pathname.replace(/^\/en/, '').startsWith(`/${pageUri}`)
if (!onThisPage) return
const slug = getSlugFromUrl() const slug = getSlugFromUrl()
if (slug && (!itemData || itemData.uri !== `${pageUri}/${slug}`)) { if (slug && (!itemData || itemData.uri !== `${pageUri}/${slug}`)) {
openItem(slug) openItem(slug)
@ -80,8 +83,26 @@
return () => window.removeEventListener('popstate', handlePopState) return () => window.removeEventListener('popstate', handlePopState)
}) })
// Quand le slide devient actif avec un seul livre blanc :
// - remplace l'URL /parent par /parent/slug (back saute le parent)
// - ré-ouvre l'item si itemData a été vidé
$effect(() => { $effect(() => {
if (!isActive && itemData) itemData = null if (isActive && data?.singleSlug) {
if (!getSlugFromUrl()) {
const prefix = locale.current === 'en' ? '/en' : ''
history.replaceState({}, '', `${prefix}/${pageUri}/${data.singleSlug}`)
}
if (!itemData) openItem(data.singleSlug)
}
})
// Reset après la fin de la transition de slide (1100ms) pour éviter le flash
// Pas de reset pour singleSlug : le contenu reste en mémoire et est pré-affiché à l'arrivée
$effect(() => {
if (!isActive && itemData && !data?.singleSlug) {
const timer = setTimeout(() => { itemData = null }, 1100)
return () => clearTimeout(timer)
}
}) })
</script> </script>