Feat: navbar frosted glass au scroll

- navigation.svelte.js : ajout isScrolled + setScrolled()
- Header : scroll listener (capture) sur .page-scrollable > 100px,
  reset au changement de slide, classe navbar--scrolled conditionnelle,
  transition 0.4s sur background-color et backdrop-filter
- Expertise : $effect notifie quand currentItem > 0
- Portfolio : $effect notifie quand currentIndex > 0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-03-12 15:05:25 +01:00
parent 517143fe60
commit a0798e71d0
4 changed files with 45 additions and 2 deletions

View file

@ -1,4 +1,5 @@
<script>
import { onMount } from 'svelte'
import { navigation } from '@state/navigation.svelte'
import { locale } from '@state/locale.svelte'
import { slides } from '@state/slides.svelte'
@ -9,6 +10,13 @@
const currentLang = $derived(locale.current)
const activeId = $derived(slides.active?.id ?? 'home')
const menuItems = $derived(slides.all.filter(s => s.id !== 'home'))
const isScrolled = $derived(navigation.isScrolled)
// Reset scroll state when switching slides
$effect(() => {
void slides.activeIndex
navigation.setScrolled(false)
})
function getTitle(slide) {
return slide.titles?.[currentLang] || slide.title || slide.id
@ -17,9 +25,19 @@
function toggleMenu() {
navigation.toggleMenu()
}
onMount(() => {
function onScroll(e) {
if (e.target?.classList?.contains('page-scrollable')) {
navigation.setScrolled(e.target.scrollTop > 100)
}
}
window.addEventListener('scroll', onScroll, { capture: true })
return () => window.removeEventListener('scroll', onScroll, { capture: true })
})
</script>
<nav class="navbar" class:navbar--open={isMenuOpen}>
<nav class="navbar" class:navbar--open={isMenuOpen} class:navbar--scrolled={isScrolled && !isMenuOpen}>
<a href="/" class="navbar-logo">
<img src="/assets/img/GIF_world_game_planete.gif" alt="World Game" class="wg-logo" />
</a>
@ -64,6 +82,7 @@
position: fixed;
top: 0;
left: 0;
transition: background-color 0.4s ease, backdrop-filter 0.4s ease;
z-index: var(--z-header);
font-family: "Danzza";
font-size: var(--font-size-paragraph);
@ -100,6 +119,11 @@
display: inline;
}
.navbar--scrolled {
background-color: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(15px);
}
.navbar--open {
background-color: transparent;
backdrop-filter: none;
@ -174,6 +198,10 @@
top: 0;
}
.wg-logo {
height: 2rem;
}
.navbar-item {
display: none;
}