Files
kaiser-natron/src/router/index.js
Dorian 4f6c697bc6 restore savedPosition + force smooth scroll on hash via HomePage watcher
Two fixes:
- Bring back savedPosition handling in scrollBehavior so /shop ⇄
  /shop/<slug> back-nav restores the previous scroll y.
- Add a route.hash watcher in HomePage that calls scrollIntoView with
  smooth behaviour. Vue Router's scrollBehavior alone wasn't reliably
  firing for same-route hash navigations, so this catches them
  explicitly. Also handles direct /#bundles deep-links via immediate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:15:58 +01:00

177 lines
6.6 KiB
JavaScript

import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
name: 'home',
component: () => import('@/pages/HomePage.vue'),
meta: { layout: 'none' },
},
{
path: '/shop',
name: 'shop',
component: () => import('@/pages/ShopPage.vue'),
meta: { layout: 'none' },
},
{
path: '/shop/:slug',
name: 'product',
component: () => import('@/pages/ProductPage.vue'),
meta: { layout: 'none' },
},
{
path: '/checkout/success',
name: 'checkout-success',
component: () => import('@/pages/CheckoutSuccessPage.vue'),
meta: { layout: 'none' },
},
{
path: '/checkout',
component: () => import('@/pages/CheckoutPage.vue'),
meta: { layout: 'none' },
children: [
{ path: '', redirect: '/checkout/cart' },
{
path: 'cart',
name: 'checkout-cart',
component: () => import('@/pages/checkout/CartStep.vue'),
},
{
path: 'account',
name: 'checkout-account',
component: () => import('@/pages/checkout/AccountStep.vue'),
},
{
path: 'shipping',
name: 'checkout-shipping',
component: () => import('@/pages/checkout/ShippingStep.vue'),
},
{
path: 'payment',
name: 'checkout-payment',
component: () => import('@/pages/checkout/PaymentStep.vue'),
},
],
},
{
path: '/login',
name: 'login',
component: () => import('@/pages/LoginPage.vue'),
meta: { layout: 'none' },
},
{
path: '/register',
name: 'register',
component: () => import('@/pages/RegisterPage.vue'),
meta: { layout: 'none' },
},
{
path: '/pflege',
name: 'pflege',
component: () => import('@/pages/CategoryPage.vue'),
props: { slug: 'pflege', useCase: 'care' },
meta: { layout: 'none' },
},
{
path: '/haushalt',
name: 'haushalt',
component: () => import('@/pages/CategoryPage.vue'),
props: { slug: 'haushalt', useCase: 'clean' },
meta: { layout: 'none' },
},
{
path: '/impressum',
name: 'impressum',
component: () => import('@/pages/LegalPage.vue'),
props: { kind: 'impressum' },
meta: { layout: 'none' },
},
{
path: '/datenschutz',
name: 'datenschutz',
component: () => import('@/pages/LegalPage.vue'),
props: { kind: 'datenschutz' },
meta: { layout: 'none' },
},
{
path: '/design/preview/navbar',
name: 'ds-preview-navbar',
component: () => import('@/pages/design/previews/NavbarPreview.vue'),
meta: { layout: 'none', preview: true },
},
{
path: '/design/preview/hero',
name: 'ds-preview-hero',
component: () => import('@/pages/design/previews/HeroPreview.vue'),
meta: { layout: 'none', preview: true },
},
{
path: '/design/preview/bundles',
name: 'ds-preview-bundles',
component: () => import('@/pages/design/previews/BundlesPreview.vue'),
meta: { layout: 'none', preview: true },
},
{
path: '/design/preview/revitalization',
name: 'ds-preview-revitalization',
component: () => import('@/pages/design/previews/RevitalizationPreview.vue'),
meta: { layout: 'none', preview: true },
},
{
path: '/design/preview/about',
name: 'ds-preview-about',
component: () => import('@/pages/design/previews/AboutPreview.vue'),
meta: { layout: 'none', preview: true },
},
{
path: '/design',
component: () => import('@/pages/design/DesignLayout.vue'),
meta: { layout: 'none' },
children: [
{ path: '', redirect: '/design/logo' },
{ path: 'logo', name: 'ds-logo', component: () => import('@/pages/design/LogoSection.vue') },
{ path: 'colors', name: 'ds-colors', component: () => import('@/pages/design/ColorsSection.vue') },
{ path: 'typography', name: 'ds-typography', component: () => import('@/pages/design/TypographySection.vue') },
{ path: 'radii', name: 'ds-radii', component: () => import('@/pages/design/RadiiSection.vue') },
{ path: 'shadows', name: 'ds-shadows', component: () => import('@/pages/design/ShadowsSection.vue') },
{ path: 'motion', name: 'ds-motion', component: () => import('@/pages/design/MotionSection.vue') },
{ path: 'buttons', name: 'ds-buttons', component: () => import('@/pages/design/ButtonsSection.vue') },
{ path: 'badges', name: 'ds-badges', component: () => import('@/pages/design/BadgesSection.vue') },
{ path: 'inputs', name: 'ds-inputs', component: () => import('@/pages/design/InputsSection.vue') },
{ path: 'cards', name: 'ds-cards', component: () => import('@/pages/design/CardsSection.vue') },
{ path: 'products', name: 'ds-products', component: () => import('@/pages/design/ProductsSection.vue') },
{ path: 'bundle-card', name: 'ds-bundle-card', component: () => import('@/pages/design/BundleCardSection.vue') },
{ path: 'hero', name: 'ds-hero', component: () => import('@/pages/design/HeroSection.vue') },
{ path: 'navbar', name: 'ds-navbar', component: () => import('@/pages/design/NavbarSection.vue') },
{ path: 'language', name: 'ds-language', component: () => import('@/pages/design/LanguageSwitcherSection.vue') },
{ path: 'icons', name: 'ds-icons', component: () => import('@/pages/design/IconsSection.vue') },
{ path: 'search', name: 'ds-search', component: () => import('@/pages/design/SearchSection.vue') },
{ path: 'cart-drawer', name: 'ds-cart-drawer', component: () => import('@/pages/design/CartDrawerSection.vue') },
{ path: 'quantity-stepper', name: 'ds-quantity-stepper', component: () => import('@/pages/design/QuantityStepperSection.vue') },
{ path: 'bundles', name: 'ds-bundles', component: () => import('@/pages/design/BundlesSection.vue') },
{ path: 'revitalization', name: 'ds-revitalization', component: () => import('@/pages/design/RevitalizationSection.vue') },
{ path: 'about', name: 'ds-about', component: () => import('@/pages/design/AboutSection.vue') },
],
},
]
const router = createRouter({
history: createWebHistory(),
routes,
// Scroll rules:
// • Browser back/forward → restore the previous scroll y so
// /shop ⇄ /shop/<slug> round-trips land where the user left off.
// • Hash nav (e.g. /#bundles) → smooth-scroll to the target.
// Belt-and-suspenders: HomePage also runs a route.hash watcher
// so that hash-only changes within the same route are caught
// even when Vue Router's scrollBehavior is short-circuited.
// • Everything else (forward route nav) → top of the page.
scrollBehavior(to, _from, savedPosition) {
if (savedPosition) return savedPosition
if (to.hash) return { el: to.hash, behavior: 'smooth' }
return { top: 0 }
},
})
export default router