From 11a52003e77141c4dcea047c7ae5e2e0805f4410 Mon Sep 17 00:00:00 2001 From: Ruslan Bakiev Date: Mon, 26 Jan 2026 16:29:20 +0700 Subject: [PATCH] Make hero scroll linear - direct 1:1 scroll to height/opacity --- app/composables/useHeroScroll.ts | 29 +++++++++++------------------ app/layouts/topnav.vue | 21 +++++++++------------ 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/app/composables/useHeroScroll.ts b/app/composables/useHeroScroll.ts index e544c66..b26b7a8 100644 --- a/app/composables/useHeroScroll.ts +++ b/app/composables/useHeroScroll.ts @@ -1,41 +1,35 @@ /** * Composable for home page hero scroll behavior - * Starts with full-screen hero, collapses to fixed header on scroll + * Linear: hero shrinks 1:1 with scroll, from full screen to fixed header */ export const useHeroScroll = () => { const scrollY = ref(0) - // Hero height = viewport height minus some space (e.g., 80px for visual balance) + // Hero height = viewport height minus some space const heroBaseHeight = ref(0) const collapsedHeight = 100 // Fixed header height when collapsed // Calculate hero height based on viewport const updateHeroHeight = () => { if (import.meta.client) { - heroBaseHeight.value = window.innerHeight - 80 // Nearly full screen + heroBaseHeight.value = window.innerHeight - 80 } } - // How much to collapse (0 = full hero, 1 = fully collapsed) + // Linear: height = base - scroll, clamped to min + const heroHeight = computed(() => { + return Math.max(collapsedHeight, heroBaseHeight.value - scrollY.value) + }) + + // Linear progress 0..1 const collapseProgress = computed(() => { const maxScroll = heroBaseHeight.value - collapsedHeight if (maxScroll <= 0) return 1 return Math.min(1, Math.max(0, scrollY.value / maxScroll)) }) - // Current hero height (animated) - const heroHeight = computed(() => { - const maxScroll = heroBaseHeight.value - collapsedHeight - return Math.max(collapsedHeight, heroBaseHeight.value - scrollY.value) - }) - - // Is fully collapsed to fixed header? - const isCollapsed = computed(() => collapseProgress.value >= 1) - - // Padding for content below hero - const contentPaddingTop = computed(() => { - return heroHeight.value - }) + // Is fully collapsed? + const isCollapsed = computed(() => heroHeight.value <= collapsedHeight) const onScroll = () => { if (import.meta.client) { @@ -69,7 +63,6 @@ export const useHeroScroll = () => { heroHeight, collapseProgress, isCollapsed, - contentPaddingTop, collapsedHeight } } diff --git a/app/layouts/topnav.vue b/app/layouts/topnav.vue index 4512f1c..8c1dbb4 100644 --- a/app/layouts/topnav.vue +++ b/app/layouts/topnav.vue @@ -12,10 +12,10 @@
- +
@@ -116,12 +116,12 @@
- -
- + +
+

{{ $t('hero.title', 'Оптовая торговля') }} @@ -133,7 +133,7 @@
@@ -254,9 +254,6 @@ const navigateToCatalog = () => { router.push(localePath('/catalog')) } -// Hero expanded state (not fully collapsed) -const heroExpanded = computed(() => collapseProgress.value < 0.5) - // Theme state const theme = useState<'cupcake' | 'night'>('theme', () => 'cupcake')